每个函数都包含两个非继承而来的方法:call()和apply()。这两个方法的用途都是在特定的作用中调用函数,实际上等于设置函数体内this的值(改变了this的指向)。
apply(对象,[参数1,参数2...])方法接受两个参数:一个是在其中运行函数的作用域,另一个是参数数组(该参数可以是Array的实例,也可以是arguments对象)。
举例1:
function sum(num1,num2) {
return num1+num2;
}
function callsum1(num1,num2) {
//这里面的this表示callsum1函数,arguments表示传入的参数。
//可以理解为callsum1使用了sum()方法,并为sum()传入了参数。(apply是应用,使用的意思)
return sum.apply(this,arguments);
}
function callsum2(num1,num2) {
return sum.apply(this,[num1,num2]);//传入数组
}
alert(callsum1(10,20));//30
alert(callsum2(10,20));//30
在严格模式下,未指定环境对象而调用函数,则this值不会转型为window。除非明确把函数添加到某个对象或调用apply()或call(),否则this的值将是undefined。
call(对象,参数1,参数2...)方法的作用与apply()方法的作用相同,区别在于:call()方法的第一个参数亦是this,而第二个参数是直接传递给函数的。
举例2:
function sum(num1,num2) {
return num1+num2;
}
function callsum(num1,num2) {
return sum.call(this,num1,num2);//明确传递每一个参数
}
alert(callsum(10,20));//30
以上这两个例子说明了:如果当前对象想使用其他对象(函数也是一个对象)的某个方法,那么就用其他对象.apply(,当前对象,[参数1,参数2...]) 或者 其他对象.call(,当前对象,参数1,参数2...)。这样这个方法就会被当前对象所使用了。
上述例子中的sum.call(this,num1,num2)与window.sum.call(this,num1,num2)一个意思,只不过window可以省略不写。
事实上他们真正强大的地方是能够扩充函数赖以运行的作用域。
举例3:
window.color="red";
var o={color:"blue"};
function saycolor() {
alert(this.color);
}
saycolor();//red
saycolor.call(this);//red
saycolor.apply(window);//red
saycolor.call(o);//blue 此时函数体的this指向了o,对象o使用window对象的saycolor()方法。所以saycolor()中的this指向了o
使用call() 或者apply()来扩充作用域的最大好处,就是对象与方法不需要有任何耦合关系。
ECMAScript5还定义了一个方法:bind()。这个方法会创建一个函数的实例,其中this值会被绑定到传给bind()函数的值。
举例4:
window.color="red";
var o={color:"blue"};
function saycolor() {
alert(this.color);
}
var objSayColor=saycolor.bind(o);//saycolor.bind(o)表示this被绑定到了o上面
objSayColor();//blue
支持bind()方法的浏览器有IE9+,Firefox4+,Safair5.1+,Opera12+,Chrome.