Skip to content

实现一个 apply 方法

Function.prototype 上有一个 apply() 方法,可以改变函数运行时 this 的值。

Code

javascript
/**
 * apply 实现
 * @param {object} context
 * @returns {any}
 */
Function.prototype.myApply = function (context) {
  const ctx = context ? Object(context) : globalThis;
  // 借助 Symbol 创建一个唯一的 key
  const key = Symbol('fn');
  // 将函数挂载到对象上
  ctx[key] = this;
  let result;
  // 无参调用无法使用展开运算符,因此需要进行判断
  if (arguments[1]) {
    result = ctx[key](...arguments[1]);
  } else {
    result = ctx[key]();
  }
  // symbol 属性无法通过 delete 进行删除,因此使用 Reflect
  Reflect.deleteProperty(ctx, key);
  // 返回函数运行结果
  return result;
};

Test Cases

javascript
require('./apply');

function logAge() {
  return this.age;
}

function getAgeWithArgs(...nums) {
  return this.age + nums.reduce((acc, cur) => acc + cur, 0);
}
const obj = {
  age: 18,
};
describe('test apply', () => {
  it('should be undefined', () => {
    expect(logAge()).toBe(undefined);
  });
  it('should be 18', () => {
    expect(logAge.myApply(obj)).toBe(18);
  });
  it('should be 24', () => {
    // has arguments
    expect(getAgeWithArgs.myApply(obj, [1, 2, 3])).toBe(24);
  });
  it('should be 18', () => {
    // no arguments
    expect(getAgeWithArgs.myApply(obj)).toBe(18);
  });
});