一、了解call、apply、bind
a. 字面上理解 call(调用)、apply(应用)、bind(绑定);
b. 举例子理解一下,比如我们要磨豆腐的话,我们不可能去买一头驴和一台石磨,那怎么办呢?我们可以去邻居家里借用一下, 这样我们就不用自己去造轮子,还节省成本。 驴和石磨就相当于这三个函数 call、apply、bind, 磨豆腐用的豆子就相当于我们的上下文对象。驴和石磨转圈圈下来,把豆子干成了豆腐,赤裸裸的改变了豆子的命运。同理call、apply、bind会改变对象的上下文。
二、call、apply、bind从哪里冒出来的?
call、apply、bind本质是三个函数,都是继承Function.prototype
console.log(Function.prototype.hasOwnProperty("call")); //true
console.log(Function.prototype.hasOwnProperty("apply")); //ture
console.log(Function.prototype.hasOwnProperty("bind")); //true
这里说一点题外话,其实我们平时开发中,也是可以模仿这三个方法的特点,来写自己工具类方法。
三、使用上的区别
fn.call(obj, params1, params2, params3, ...);
fn.apply(obj, [params1, params2, params3, ...]);
fn.bind(obj, params1, params2, params3, ...)();
call和apply都是直接返回结果,bind是返回一个函数;
传参方面call和bind是一样的,apply则是传入一个数组。
四、应用
1、将伪数组(arguments 、获取dom元素数组)转化成真正的数组等,也可以自己写一个伪数组测试,
const pseudo = {
0: "zh",
1: "cn",
length: 2
}
console.log(Array.isArray(pseudo)) //false
const arr = Array.prototype.slice.call(pseudo);
console.log(arr); // ["zh", "cn"]
console.log(Array.isArray(arr)) //true
IE8兼容写法:
function listToArray(list) {
let ary = [];
try {
//IE8不支持 slice
ary = Array.prototype.slice.call(list)
} catch (e) {
for (let i = 0, item; item = list[i++];) {
ary[ary.length] = item;
}
}
return ary;
}
2、apply的第二参数是数组的形式,可以用来向数组里添加另一个数组,或者结合Math工具类使用;
let list1 = [1, 2, 3], list2 = [4, 5, 6];
Array.prototype.push.apply(list1, list2);
console.log(list1);
//[1,2,3,4,5,6]
当然也可以用es6的写法 list1.push(...list2);
var arr = [1, 2, 34]
console.log(Math.max.apply(arr)); // 34
console.log(Math.min.apply(arr)); // 1
3、常见的使用,改变this指向
var obj = {
name: "zhangshan",
sayName() {
console.log(this.name);
}
}
var kobj = {
name: "lisi"
}
console.log(obj.sayName.call(kobj)); //lisi
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。