1、函数属性 & arguments
函数的length属性是获取函数的形参个数,name属性是获取函数的名称。
arguments在函数中是一个特殊的对象,因为arguments的原型不是Array.prototype,所以它没有join、slice这些数组对象才有的方法,但是我们可以使用她的下标获取它对应的值,比如arguments[0]获取她对应的值。所以我们说她是类数组。
function foo(x,y,z){
arguments.length; // 2 arguments实参的个数。
arguments[0]; // 1
arguments[0] = 10;
x; // change to 10; 但在严格模式下依然是1,
arguments[2] = 100;
z; //still undefined 没有传参数 则没有绑定关系,所以不能赋值
arguments.callee === foo; // true 严格模式下“use strict”不可以使用callee
}
foo(1,2);
foo.length; //3
foo.name; //"foo"
2、apply/call方法(浏览器)
apply方法和call的使用没有什么区别,他们的第一个参数都是当前方法要绑定的this对象,如果不是对象浏览器自动转为对象,只是call方法后面的参数是扁平的方法传入的,而apply是以数组的方式传入的。如果一般模式下,对于第一个参数如果传的是null或者undefined,这时的this就会指向全局对象,对于浏览器就是window,对于nodejs会是global对象,如果是严格模式下("use static"),这时传入的null就仍然是null,undefined也会是undefined。
function foo(x,y){
console.log(x,y,this);
}
foo.call(100,1,2); //1,2,Number(100)
foo.apply(true,[3,4]); // 3,4,Boolean(true)
foo.apply(null); //undefined,undefined,window
foo.apply(undefined); //undefined,undefined,window
3、bind方法
bind方法时ES5才提供的方法,所以只有ie9以上的版本才会支持。
bind可以改变函数中this的指向:
this.x = 9;
var module = {
x:81,
getX:function(){return this.x;}
};
module.getX(); // 81
var getX = module.getX;
getX(); // 9
var boundGetX = getX.bind(module);
boundGetX();//81
bind有函数柯里化的功能,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
下面是使用bind方法把函数拆分成子函数
function add(a,b,c){
return console.log(a+b+c);
}
var func = add.bind(undefined,100);
func(1,2); // 103
var func2 = func.bind(undefined,200);
func2(10); // 310
bind和new,如果使用new来创建对象,他会忽略bind方法绑定的this,而是根据函数的返回值来确定当前对象,如果返回的不是对象,则返回函数的this,并且将this初始化为一个空对象,这个对象的原型指向函数的原型。
function foo(){
this.b = 100;
return this.a;
}
var func = foo.bind({a:1});
func(); //1;
new func(); // {b:100}
模拟bind方法
if(!Function.prototype.bind){
Function.prototype.bind = function(oThis){
console.log(oThis);
if(typeof this != 'function'){
throw new TypeError('What is trying to be bound is not callable')
}
var aArgs = Array.prototype.slice.call(arguments,1),
fToBind = this,
fNOP = function(){},
fBound = function(){
return fToBind.apply(this instanceof fNOP ? this : oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
}