使用symbol、object.defineProperty和es6的剩余参数相互配合手写call

180 阅读1分钟

本次手写相对于上一次做了一些优化

1.当传入的参数的null和undefined时,this指向为全局(兼容浏览器环境和node环境)
2.使用symbol修饰符作为唯一标识
Function.prototype.myCall2 = function (context, ...args) {
  //context为传入的对象   ...args为传入的剩余参数 这里运用了es6的剩余参数比较方便

  //注意点1:globalThis既存在于node环境又存在于浏览器环境,二者环境兼容该方法才无可挑剔
  context === undefined || context === null
    ? (context = globalThis)
    : Object(context);

  //注意点2:使用es6的symbol数据类型可以使新建的函数唯一,避免覆盖掉原对象中的属性
  let key = Symbol("temp");
  //将this(此时的this指向对调用的对象)挂载到fn属性上
  //最好不要这样(context.fn = this)定义属性,会导致原属性被覆盖

  //这里使用es5的Object.defineProperty为context定义属性
  Object.defineProperty(context, key, {
    enumerable: false,
    value: this,
  });
  //执行fn函数并传入剩余参数得到结果
  let result = context[key](...args);
  //将fn属性从context对象中删除
  delete context[key];
  //返回result
  return result;
};