模拟实现call, apply

140 阅读1分钟
// 1. function.call(thisArg, arg1, arg2, ...)
// 2. 非严格模式下,thisArg是null,执行中this指向window
// 3. 返回值就是参数调用函数的返回值


// 1. function.call 核心实现

Function.prototype.copyCall = function (obj) {
  obj.fun = this
  obj.fun()
  delete obj.fun
}

function a () {
  console.log(this)
  console.log(this.name)
}

const obj = {
  name: 'sherry',
  age: '18'
}

a.copyCall(obj)


// 2. function.call 非严格模式下传null
Function.prototype.copyCall = function (obj) {
  var object = (typeof obj === 'undefined' || obj === null) ? window : obj
  object.fun = this
  object.fun()
  delete object.fun
}

function a () {
  console.log(this)

}

a.copyCall(null)
// 第三版
Function.prototype.call2 = function (context) {
    var context = context || window;
    context.fn = this;

    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }

    var result = eval('context.fn(' + args +')');

    delete context.fn
    return result;
}

// 测试一下
var value = 2;

var obj = {
    value: 1
}

function bar(name, age) {
    console.log(this.value);
    return {
      value: this.value,
      name: name,
      age: age
    }
}

bar.call(null); // 2

console.log(bar.call2(obj, 'kevin', 18));
// 1
// Object {
//    value: 1,
//    name: 'kevin',
//    age: 18
// }

apply

Function.prototype.apply = function (context, arr) {
    var context = Object(context) || window;
    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;
}

参考自 juejin.cn/post/684490…