相同点
bind、apply、call 都是用来绑定函数执行时 this 的指向(扭转函数执行时的上下文),同时还能够传参,调用它们的对象必须是一个函数 Function。
区别
区别次要提当初传参上。
// call
Function.call(obj, arg1, arg2, arg3, ...);
// apply,有两个参数,第二个是类数组
Function.apply(obj, [argArray]);
// bind,bind 办法的返回值是函数,须要手动调用才会执行,而 apply 和 call 则是立刻调用
Function.bind(obj, arg1, arg2, arg3, ...);
const obj = {name: '小鸭子',};
function say (arg1, arg2) {console.log(`${this.name ? ` 我是一只 ${this.name},` : ''}${arg1},${arg2}`);
}
say('咿呀咿呀哟', '呱呱!'); // 咿呀咿呀哟,呱呱!say.call(obj, '咿呀咿呀哟', '呱呱!') // 我是一只小鸭子,咿呀咿呀哟,呱呱!say.apply(obj, ['咿呀咿呀哟', '呱呱!']); // 我是一只小鸭子,咿呀咿呀哟,呱呱!const manualSay = say.bind(obj, '咿呀咿呀哟', '呱呱!'); // 绑定但不是立刻执行
manualSay(); // 手动执行,输入:我是一只小鸭子,咿呀咿呀哟,呱呱!
性能比拟
call 的性能要比 apply 好一些(尤其是传递给函数的参数超过三个的时候)
大略因为,apply 的第二个参数是数组,函数在执行时,解析数组获取参数,须要消耗性能。
call 实现
// call 实现
Function.prototype.myCall = function(context) {
context = context || window; // 默认 window
const args = [...arguments].slice(1); // 参数
const fn = Symbol(); // 给 context 设置一个举世无双的属性,防止笼罩原有属性
context[fn] = this; // 这里的 this 指向调用它的函数 fn
const result = context[fn](...args); // 调用之
delete context[fn]; // 删除增加的属性
return result; // 返回值
}
say.myCall(obj, '咿呀咿呀哟', '呱呱!') // 我是一只小鸭子,咿呀咿呀哟,呱呱!
apply 实现
// apply 实现
Function.prototype.myApply = function(context, args) {
context = context || window; // 默认 window
args = [...args]; // 参数
const fn = Symbol(); // 给 context 设置一个举世无双的属性,防止笼罩原有属性
context[fn] = this; // 这里的 this 指向调用它的函数 fn
const result = context[fn](...args); // 调用之
delete context[fn]; // 删除增加的属性
return result; // 返回值
}
say.myApply(obj, ['咿呀咿呀哟', '呱呱!']) // 我是一只小鸭子,咿呀咿呀哟,呱呱!
bind 实现
// bind 实现
Function.prototype.myBind = function(context) {
context = context || window; // 默认 window
const args = [...arguments].slice(1); // 参数
const fn = this; // 这里的 this 指向调用它的函数 fn
return function () {return fn.apply(context, args);
};
}
const manualSay = say.myBind(obj, '咿呀咿呀哟', '呱呱!');
manualSay(); // 手动执行,输入:我是一只小鸭子,咿呀咿呀哟,呱呱!
总结起来,call、apply、bind 的实现,要解决好以下几点:
- 绑定上下文
context
- 解决好参数
arguments
- 应用
Symbol
存储长期函数
后记
call、apply、bind 是 JavaScript 中十分重要的概念,也是前端面试中的高频面试题,无论是工作还是面试中,咱们总是绕不开它,因而必须要把握它,本文参考了许多网上大神的材料,文中若有不对之处,欢送斧正。本面试题收录在 leetoffer。