手写apply

211 阅读1分钟
    // 1.实现一个apply函数
        // 思路就是 将要改变this指向的方法挂到目标this上执行并返回

        Function.prototype.myapply = function (context) {
            if(typeof this !== 'function') {
                throw new TypeError('not function')
            }

            context = context || window
            context.fn = this
            let result

            if(arguments[1]) {
                result = context.fn(...arguments[1])
            } else {
                result = context.fn()
            }
            delete context.fn

            return result;
        }

写法2

Function.prototype.apply2 = function(context, arr) {
    context = context ? Object(context) : window;
    var fn = fnFactory(context);
    context[fn] = this;
    
    var result;
    if(!arr) {
        result = context[fn]();
    } else {
        var args = [];
        for(var i = 0, len = arr.length; i < len; i ++) {
            args.push("arr["+ i +"]")
        }
        result = eval("context[fn]("+ args +")")
    }
    delete context[fn];
    return result;
}




Function.prototype.apply2 = function(context, arr) {
  // 1. 若是传入的context是null或者undefined时指向window;
  // 2. 若是传入的是原始数据类型, 原生的call会调用 Object() 转换
  context = context ? Object(context) : window;
  // 3. 创建一个独一无二的fn函数的命名
  var fn = fnFactory(context);
  // 4. 这里的this就是指调用call的那个函数
  // 5. 将调用的这个函数赋值到context中, 这样之后执行context.fn的时候, fn里的this就是指向context了
  context[fn] = this;

  var result;
  // 6. 判断有没有第二个参数
  if (!arr) {
    result = context[fn]();
  } else {
    // 7. 有的话则用args放每一项的字符串: ['arr[0]', 'arr[1]']
    var args = [];
    for (var i = 0, len = arr.length; i < len; i++) {
      args.push("arr[" + i + "]");
    }
    // 8. 使用eval()来执行fn并将args一个个传递进去
    result = eval("context[fn](" + args + ")");
  }
  // 9. 给context额外附件了一个属性fn, 所以用完之后需要删除
  delete context[fn];
  // 10. 函数fn可能会有返回值, 需要将其返回
  return result;
};


es6实现:

Function.prototype.apply3 = function(context,arr) {
    context = context ? Object(context) : window;
    let fn = Symbol();
    context[fn] = this;
    
    let result = arr ? context[fn](...arr) : context[fn]();
    delete context[fn];
    return result;
}

扫码加群