实现 call、apply、bind

手写 JavaScript 的 call、apply 和 bind 方法

问题

从零实现 callapplybind 方法。

解答

实现 call

Function.prototype.myCall = function(context, ...args) {
  context = context || window;
  const fnKey = Symbol();
  context[fnKey] = this;
  const result = context[fnKey](...args);
  delete context[fnKey];
  return result;
};

// 使用
function greet(greeting) {
  console.log(`${greeting}, ${this.name}`);
}
greet.myCall({ name: '小明' }, '你好'); // "你好, 小明"

实现 apply

Function.prototype.myApply = function(context, args = []) {
  context = context || window;
  const fnKey = Symbol();
  context[fnKey] = this;
  const result = context[fnKey](...args);
  delete context[fnKey];
  return result;
};

实现 bind

Function.prototype.myBind = function(context, ...args) {
  const fn = this;
  return function(...innerArgs) {
    return fn.apply(context, [...args, ...innerArgs]);
  };
};

关键点

  • 使用 Symbol 避免属性名冲突
  • 处理 nullundefined 的 context
  • bind 返回新函数,不立即执行