模拟实现apply和call

call

一句话介绍call:

  • call()方法在使用一个指定的this值和若干指定的参数值的前提下调用某个函数或方法。

举个例子:

  var obj = {
      value: 1
  };
  function parson() {
    console.log(this.value);
  }

  bar.bind(foo); //1
  1. call改变了this指向,指向了parson
  2. parson函数执行了。

模拟步骤

  1. 讲函数设置为对象的属性
    2.执行该函数
    3.删除该函数
  // 第一步
  obj.fn = parson
  //第二步
  obj.fn();
  // 第三步
  detele obj.fn;

第一次尝试

  Function.prototype.call2 = function (context) {
    // 首先获取调用call的函数,用this可以获取;
    context.fn = this;
    // 传入参数确定怎么办?我们可以从arguments对象中取值,去除第二个到最后一个参数
    let args = [];
    for (var i = 1; i < arguments.length; i+) {
      args.push('arguments[' + i + ']');
    }
    // 不定参的问题解决了,我们要吧这个参数放在要执行的函数的参数中去;
    // 可以使用eval方法拼成一个函数
    eval('context.fn(' + args + ')');
    // context.fn(); // 执行函数
    detele context.fn;
  }
  
  // 测试一下
  var obj = { 
    value: 1
  }
  
  function parson() {
    console.log(name);
    console.log(age);
    console.log(this.value);
  }

  parson.call2(obj, 'name', 15);
  // name
  // 15
  // 1

ok 这样基本就实现了call的基本功能,不过还有两小点要注意一下。

1. this可以传参null,当为null的时候,指向window;

举个例子:

  var value = 1;
  
  function parson() {
    console.log(this.value);
  }
  
  parson.call(null)  // 1
2.函数是可以有返回值的

举个例子:

  var obj = {
    value: 1
  }
  
  function parson(name, age) {
    return {
      value: this.value,
      name: name,  
      age: age
    }
  }

  console.log(parson.call(obj, 'name', 15))
  // Object {
  //    value: 1,
  //    name: 'name',
  //    age: 15
  //}

好的,我们下改进后的代码

  Function.prototype.call2 = function (context) {
    context.fn = context || window; // 设置一个默认值
    let args = [];
    for (var i = 1; i < arguments.length; i+) {
      args.push('arguments[' + i + ']');
    }
    var result = eval('context.fn(' + args + ')');
    detele context.fn;
    return result;
  }
  
  // 测试一下
  var obj = { 
    value: 1
  }
  
  function parson() {
    console.log(name);
    console.log(age);
    console.log(this.value);
  }

  parson.call2(obj, 'name', 15);
  // name
  // 15
  // 1

到此,我们就完成了call的实现!

apply的模拟试下

apply的实现跟call类似,在这里直接给代码。

 Function.prototype.apply2 = function (context, arr) {
   context = context || window;
   context.fn = this;
   var result;
   if (arr) {
     var args = [];
     for (var i = 1; i < arguments.length; i++) {
       args.push('argsuments[' + i + ']');
     }
     result = eval('context.fn(' + args + ')');
   } else {
     result = context.fn()
   }
   detele = context.fn;
   renturn result;
 }

参考 [# JavaScript深入之call和apply的模拟实现
]

你可能感兴趣的:(模拟实现apply和call)