call、apply、bind的异同
apply()
apply方法传入的两个参数:第一个是函数上下文的对象,第二个是一个作为函数参数所组成的数组
var obj = {
name : 'dddd'
}
function func(firstName, lastName){
console.log(firstName + ' ' + this.name + ' ' + lastName);
}
func.apply(obj, ['A', 'B']); //输出结果为 A dddd B
我们可以看到obj作为func的函数上下文的obj。func中的this指向obj。参数 A 和 B 是放在数组中传入 func 函数,分别对应 func 参数的列表元素。
call()
call 方法第一个参数也是作为函数上下文的对象,但是后面传入的是一个参数列表,而不是单个数组。
var obj = {
name: 'dddd'
}
function func(firstName, lastName) {
console.log(firstName + ' ' + this.name + ' ' + lastName);
}
func.call(obj, 'C', 'D'); // C dddd D
对比 apply 我们可以看到区别,C 和 D 是作为单独的参数传给 func 函数,而不是放到数组中
call和apply是使用时刻:如果参数本来就存在一个数组当中,就使用apply,如果参数比较散乱相互之间没有联系,就用call
bind()
多次bind时只认第一次bind的值
共同点:
功能角度:三者都能改变 this 指向,且第一个传递的参数都是 this 指向的对象。 传参角度:三者都采用的后续传参的形式。
不同点:
- call,bind后面的第一个参数是指向的对象,第二个参数是往对象传的值,bind函数中this不会被修改
- apply后面的第一个参数是指向的对象,第二个参数是数组,数组里面是往对象传的值(arguments 全部参数)
- call和apply更改this指向会自动调用,bind需要手动调用
- apply和call的第一个参数都是this,区别在于apply调用时,实参是放在数组中的,而通过call调用时,实参通过逗号隔开
- 传参方面: call 的传参是单个传递(序列),而 apply 后续传递的参数是数组形式。而 bind 与call相同。
- 执行方面: call 和 apply 函数的执行是直接执行的,而 bind 函数会返回一个函数,然后我 们想要调用的时候才会执行。
- this指向永远指向最后调用它的那个对象
apply和call用法:
- 更改this指向
var obj = {
name: 'dddd'
}
function func() {
console.log(this.name+'aaa');
}
func.call(obj); // dddd call将this指向了obj 此时上面的this 指向obj 若是没有下方的输出obj.name 则会输出上方的this.name ddddaaa 当下方有obj.name时会输出ddddbbb
// 我们都知道call的第一个参数是函数上下文的对象,这里把obj传给func相当于函数里的 this //便指向了 obj 对象。
// func.call(obj); // dddd
function func(){
console.log(obj.name+'bbb')
}
- 调用函数 apply、call 方法都会使函数立即执行,因此它们也可以用来调用函数
function func() {
console.log('dddd');
}
func.call();//这里我们调用func.call()相当于直接执行func函数,会直接打印dddd
- bind方法
if (!Function.prototype.bind) {
Function.prototype.bind = function () {
var self = this, // 保存原函数
context = [].shift.call(arguments), // 保存需要绑定的this上下文
args = [].slice.call(arguments); // 剩余的参数转为数组
return function () { // 返回一个新函数
self.apply(context,[].concat.call(args, [].slice.call(arguments)));
}
}
}