乐趣区

关于面试:callapplybind-的区别call-和-apply-哪个性能会更好如何实现-callapplybind

相同点

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 的实现,要解决好以下几点:

  1. 绑定上下文 context
  2. 解决好参数 arguments
  3. 应用 Symbol 存储长期函数

后记

call、apply、bind 是 JavaScript 中十分重要的概念,也是前端面试中的高频面试题,无论是工作还是面试中,咱们总是绕不开它,因而必须要把握它,本文参考了许多网上大神的材料,文中若有不对之处,欢送斧正。本面试题收录在 leetoffer。

退出移动版