call,apply和bind

185 阅读2分钟

1.概述异同

call和apply本质上来说并没有什么区别,作用都是一致的,他们的差别是传入给func的参数不同
call是多次传入要使用的参数,而apply传入的是一个包含要使用参数的类数组

call/apply与bind的区别体现在他们的返回值不同,
call和apply的返回值是func的执行结果,在改变this指向后立即执行函数,
而bind的返回值是func的拷贝,在改变this指向后不会立即执行函数,即需要自行调用得到的这个新函数

2.语法

func.call(thisArg,param1,param2,...)    //call接收一个参数列表
func.apply(thisArg,[param1,param2,...]) //apply接收一个包含多个参数的数组
func.bind(thisArg,param1,param2)        //bind接收一个参数列表

参数:

thisArg(必选):

func的this将指向thisArg;
非严格模式下若thisArg指定为null或是undefined,则func的this指向window对象;
严格模式下若thisArg指定为null或是undefined,则func的this指向undefined

param(可选):

如果不传该参数或是传入null或undefined,则表示不传入任何参数;
apply的第二个参数为类数组对象,传入func的参数是数组内各项的值

3.实例

3.1实例1

let obj={
    name:"Qiu",
    say:function(){
        console.log(this.name);
	}
}
let obj2={
    name:"qiqi"
}
obj.say()//Qiu
obj.say.call(obj2)//qiqi
obj.say.apply(obj2)//qiqi  

3.2 实例2

let obj={
    name:"Qiu",
    say:function(){
    console.log(arguments);
    console.log(this.name);
    }
}
let obj2={
    name:"qiqi"
}
obj.say()
//Arguments [callee: ƒ, Symbol(Symbol.iterator): ƒ]
//Qiu 
obj.say.call(obj2,1,2,3)//直接调用
//Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
//qiqi
obj.say.apply(obj2,[1,2,3])//以数组方式传入,直接调用
//Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
//qiqi  

3.3实例3

let obj={
    name:"Qiu",
    say:function(){
    console.log(arguments);
    console.log(this.name);
    }
}
let obj2={
    name:"qiqi"
}
obj.say()
//Arguments [callee: ƒ, Symbol(Symbol.iterator): ƒ]
//Qiu 
obj.say.call(obj2,1,2,3)//直接调用
//Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
//qiqi
obj.say.apply(obj2,[1,2,3])//以数组方式传入,直接调用
//Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
//qiqi
let sayClone=obj.say.bind(obj2,1,2,3)//拷贝
sayClone()
//Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
//qiqi

4.总结

总结三者异同:

相同点:call,apply,bind的作用都是用来修改this指向的,或者说是借用方法
区别:call和apply是立即调用函数, 而bind是返回对应函数需另调用