首先,这三个都是用来改变函数的this对象的指向的;
然后,他们第一个参数都是要指向的对象;
最后,后续的参数用来传参。
有个例子特别好:
var xw = {
name : "小王",
gender : "男",
age : 24,
say : function() {
alert(this.name + " , " + this.gender + " ,今年" + this.age);
}
}
var xh = {
name : "小红",
gender : "女",
age : 18
}
xw.say();
那么结果当然不用说,显示是 小王,男,今年24.
那么我们如何显示xh的数据呢。
如果用call
xw.say.call(xh); //即xw中的say方法的调用者改成了xh,改变了this的指向。
如果用apply
xw.say.apply(xh); //即xw中的say方法的调用者改成了xh,改变了this的指向。
如果用bind
xw.say.bind(xh)(); //此处,bind返回的是一个函数,如果要执行,需要()进行调用。
上面可以看出,三者都改变了原方法的this指向,apply、call和bind的区别也很明显。
那么apply和call的区别呢
那我们修改一下上面的这个例子
var xw = {
name : "小王",
gender : "男",
age : 24,
say : function(school,grade) {
alert(this.name + " , " + this.gender + " ,今年" + this.age + " ,在" + school + "上" + grade);
}
}
var xh = {
name : "小红",
gender : "女",
age : 18
}
ok,多个两个参数
如果用call
xw.say.call(xh,”XX小学”,”六年级”);
如果用apply
xw.say.apply(xh,[”XX小学”,”六年级”]);
区别就是apply后面传数组,call是一个个传参,一一对应。
当然bind也可以传参
xw.say.bind(xh)(”XX小学”,”六年级”);
解释同上,因为bind返回的是一个函数,所以我们是在调用的时候传参。
所以最大的区别就是apply、call是立即调用函数,bind不是。
1、巧用apply
Math.max函数用于取得最大值,但是它必须以一个传入参数,而不是数组形式。So
const arr = [1,2,3,4,5,6]
const max = Math.max.apply(null, arr)
console.log(max) // 6
2、验证数组(前提是toString()方法没有被重写过)
function isArray(obj){
return Object.prototype.toString.call(obj) === '[object Array]' ;
}
原型链找到末端的函数进行调用,就是obj调用了原型链上的公共函数toString。
3、让类数组拥有数组的方法
比如arguments对象,获取到的文档节点等,并没有数组的那些方法:
Array.prototype.slice.apply(argument);
//理论上来说这个比较快,直接在原型上查找slice方法
//但实际上比较慢
或者
[].slice.apply(arguments);
//理论上来说这个比较慢,因为要Array做一个实例化再查找slice方法
//实际上比较快,因为现在的各种自动化工具会把上一种方法转换为这种,而第二种代码比较简洁,所以会比较快
也就是说:不是数组,但是却可以使用数组的函数。