JavaScript 函数的call和apply方法
鉴于JavaScript
中函数的特殊性,我们可以把函数看作是特殊的对象,因此可以将call
和apply
看作是某个对象的方法,通过调用对象方法的形式简洁调用函数。
call
和apply
的第一个参数是要调用函数的母对象,他就是调用函数的上下文,在所要调用函数的内部,我们可以使用this
关键字获取对传入的第一个对象的饮用。
function func1(){
this.func();
}
var o ={};
o.func = function (){
console.log("Called by o.");
}
var b ={};
b.func = function (){
console.log("Called by b.");
}
func1.call(o);
//Called by o.
func1.apply(b);
//Called by b.
在ECMAScript 5
的严格模式中,call
和apply
的第一个实参都会变成this
的值——this
就是第一个实参,哪怕传入的第一个参数是null
或者undefined
。
而在ECMAScript 3
和非严格模式中,传入的null
和undefined
都会被被全局对象所取代
function a(){
console.log(this);
}
a.call(null);
//window.xx
对call
来说,第一个调用上下文实参之后的所有实参都是要传入所要调用的函数的参数的值。以对象obj
的方法调用func
函数,可以用下面的形式:
/* obj是对象, params是相关参数,可能有多个 */
func.call(obj, parmas);
apply
和call
稍有不同,出了第一个参数相同之外, 其余的参数以数组的形式传入,例如:
var obj = {};
obj.func = (args) => {
var sum=0;
return args.reduce((x, y) => {return x+y},0);
}
buffer=[1,2,3,4];
func.apply(obj, buffer);
//10
function func(){
this.func(buffer);
}
注意,apply
的第二个参数出了可以传递数组还可以传入类数组对象,例如函数中的arguments
。
function trace(o,m){
var original = o[m];
o[m] = function(){
console.log(new Date(),"Entering: ",m);
var ret = original.apply(this,arguments);
//这里的this指向对象o
//this==o :true
console.log(new Date(),"Exiting: ",m);
return ret;
}
}