相同点
bind、apply、call 都是用来绑定函数执行时this的指向(扭转函数执行时的上下文),同时还能够传参,调用它们的对象必须是一个函数 Function。
区别
区别次要提当初传参上。
// callFunction.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。