call和apply都是让一个对象能调用另一个对象的方法。
使用方法
// call使用:参数分开写
function.call(this, obj, obj, ……)
// apply使用:参数都放在数组中
function.apply(this, [obj, obj, ……])
简易理解
这里有一个简易的理解方法:
function.call(this, obj, obj)
function.apply(this, [obj, obj])
// 都可以将它理解成
this.function(obj, obj)
// 也就是说去掉call和apply,将要指向的对象提取到前面,这样就很好理解了
注意
:实际上是没有这种写法的,这里这样写仅仅是为了便于理解,下同。
示例
示例一:
var arr1 = new Array("1","2","3");
var arr2 = new Array("4","5","6");
Array.prototype.push.apply(arr1,arr2);
// ["1","2","3","4","5","6"]
// 按照上面的简易理解的方法,这里可以理解成
// arr1.Array.prototype.push(arr2);
// 也就是说arr1调用Array这个类的push方法
示例二:
function add(a, b){
return a + b;
}
function sub(a, b){
return a-b;
}
add.apply(sub, [4, 2]); // 6
// 这里同样可以理解成
// sub.add(4, 2)
// 也就是说sub这个对象调用了add这个方法,并传参(4, 2),最后结果就是4 + 2 = 6
注意
:
1、为什么[4, 2]变成了(4, 2)呢?因为apply的传参方式就是将所有的参数放到一个数组中,数组中的每一项应用到被调用的方法中都是一个都是单独的参数。
2、你可能会觉得好奇,sub不是一个function吗,为什么它能去调用add这个方法。那是因为你可能忘记了,其实函数也是Function类型的对象啊。
3、虽然sub是一个对象,但是它内部没有add这个方法,它又是怎么能调用add的呢?如果我说
原型链
,你是不是能想起点啥。对!它自身没有add方法,它就会往上层找这个方法。然后就在window下找到了add方法,接着就执行这个方法咯。
示例三:
// 如果我把上面的示例修改一下,把apply的第一个参数改成null
function add(a, b){
return a + b;
}
function sub(a, b){
return a-b;
}
add.apply(null, [4, 2]); // 6
// 这个时候上面的sub被改成了null,也就是说没有对象来调用add方法,那就等同于
// add(4, 2)
// 也就是说直接运行window下的add方法
// 结果同样是6
我是尾巴
对文章中表述有异议的地方,欢迎指出。