目录
前言
网上的解释多是说改变 this 的指向,此说法没错,但肯定没这么简单。
call、apply的两大作用
1、改变this指向
对this与对象原型的掌握牢靠的同学肯定知道,this只跟调用点的绑定方式有关!
绑定方式总共有四种:
- 默认绑定
- 明确绑定
- 隐含绑定
- new绑定
其中明确绑定就是利用 call 或 apply 来强制一个函数调用使用某个特定对象作为 this 绑定
function foo() {
console.log( this.a )
}
var obj = {
a:2
}
// 通过call,将foo的this指向绑定到obj
foo.call( obj ) // 2
2、借用原生方法
注意这里是借用,不是调用,由于很多教程会专门讲 call、apply调用方法的功能,所以很多0基础同学会可能以为这里搞错了。其实上面 this章节就体现了调用方法的一方面。在改变 this指向的同时,我们也看到了方法结果被打印出来。
我们都知道,在JavaScript中,无论数组还是字符串都有许多诸如 .toStrng .length 的原生方法。但对象能用的原生方法很少,这就需要借用别的原生方法来满足自身需要,借用的途径就是通过 call或apply.
比如我们有个类数组对象:
var anArrayLikeObj = {0:"Martin", 1:78, 2:67, 3:["Letta", "Marieta", "Pauline"], length:4 };
就可以通过call借用数组的原生方法:
// 通过call 借用Array的slice方法
var newArray = Array.prototype.slice.call(anArrayLikeObj, 0);
// 注意,类数组中的length是其长度的,不会被打印
console.log(newArray); // ["Martin", 78, 67, Array[3]]
可以看到,通过 Array.prototype.slice.call(anArrayLikeObj) 将 Array.prototype.slice 的方法 赋予了anArrayLikeObj ,仔细体会这段代码!
再看一个例子增强体会:
var bar = function () {
this.a = '2'
}
var baz = function () {
this.getNumber = function () {
console.log(this.a)
}
// 将bar的方法属性赋予this
bar.call(this)
}
var a = '5'
// 赋值会绑定丢失,所以要用new绑定
var baz = new baz()
baz.getNumber() // 2
bar.call(this) bar函数通过 call 将其方法和属性绑定到this
call与apply区别
它们的区别主要是传参方式的区别,它们第一个参数都是用作函数上下文的对象(也就是this的指向对象)。
后面的参数为调用函数的参数,call 是依次排列,apply 是装在数组中。
function foo(firstargs,lastargs){
console.log(firstargs + ',' + lastargs + ',' + this.a)
}
obj = {
a: 3
}
foo.apply(obj,['1','2']) // 1,2,3
foo.call(obj,'1','2') //1,2,3