call, apply, bind都可以改变函数的this的指向,那么接下来就讲解一下这3者的区别
call语法
fun.call(thisArg, arg1,arg2, ...)
thisArg: 指在fun函数运行时执行的this,即在fun函数最外层打印出来的this指向thisArg,这样就给fun函数绑定了thisArg;
arg1, arg2, ... : 表示要传的多个参数;
列子:
var cat = {
name: '小红',
eatFish(...args) {
console.log('this指向=>', this);
console.log('...args', args);
console.log(this.name + '吃鱼');
}
}
var dog = {
name: '大龙',
eatBone(...args) {
console.log('this指向=>', this);
console.log('...args', args);
console.log(this.name + '吃骨头');
}
}
// 有一天大龙想吃鱼了,可是不懂怎么去吃鱼,怎么办呢?小红就说等会我吃的时候我喂你吃
cat.eatFish.call(dog, '汪汪汪', 'call');
// 为了感谢小红,大龙决定下次他吃骨头的时候也喂小红吃
dog.eatBone.call(cat, '喵喵喵', 'call');
apply语法
fun.apply(thisArg, [argsArray])
thisArg: 在fun函数运行时指定的this,即在fun函数最外层打印出来的this指向thisArg,这样就给fun函数绑定了thisArg;
argsArray: 所需要的传的参数,以数组的形式传;
注意: apply与call的区别是参数的传递形式不一样,call的多个参数是以逗号分隔直接传的,而apply的多个参数是以数组的形式传的。
cat.eatFish.apply(dog, ['汪汪汪', 'call']);
dog.eatBone.apply(cat, ['喵喵喵', 'call']);
bind语法
fun.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg: 在fun函数运行时指定的this,即在fun函数最外层打印出来的this指向thisArg,这样就给fun函数绑定了thisArg;
arg1, arg2, ... : 表示要传的多个参数;
const test1 = cat.eatFish.bind(dog, ['汪汪汪', 'call']);
const test2 = dog.eatBone.bind(cat, ['喵喵喵', 'call']);
test1();
test2();
区别
apply与call的区别是参数的传递形式不一样,call的多个参数是以逗号分隔直接传的,而apply是以一个数组的形式传递的,就算是一个参数也是以一个数组的形式传递的。
而bind是直接改变了this的指向,指向了一个新的函数,并返回这个新的函数。每次调用这个函数的时候this都是指向bind绑定的第一个参数,bind的传参方式和call的一致。
扩展知识
由与apply的特殊性,我们可以通过Math.max.apply()得到一个数组的最大的一项,如下所示:
const max = Math.max(1,2,3);
console.log(max); // 3
const max2 = Math.max.apply(null, [1,2,3]);
console.log(max2); // 3
bind也有一个小技巧,传参的技巧,如下所示:
// 将某个函数的this指向改变,绑定新的this指向,并且在绑定的时候固定的传入几个参数,
// 之后调用新的函数的时候可以再传几个参数进来,排在固定参数后面
const obj = {};
function testFun(...args) {
console.log(args);
}
const newFun = testFun(obj, '静态参数1', '静态参数2');
newFun('动态参数1', '动态参数2'); // ['静态参数1', '静态参数2', '动态参数1', '动态参数2']
如图所示: