【build your own xxx】实现你自己的call和apply

简介: 【build your own xxx】实现你自己的call和apply

call


首先看看call是干什么的,从MDN上扒一张图:

image.png

举个例子

 function showName(gender, age){
      console.log(this.name, " ", gender, " ", age)
    }
    var obj = {
        name: "亚古"
    }
    showName.call(obj, "female", 22)// 亚古   female   22

梳理思路


可以看出来Func.call(obj, arg1, arg2...)实现了这么几件事:

  1. 以obj.Func的方式调用
  2. 把参数arg1, arg2 ...传递给Func
  3. 不对obj和Func造成副作用


实现


Function.prototype.Zcall = function (othis) {
        othis.fn = this;
        othis.fn();
  }
    showName.Zcall(obj) // 亚古   undefined   undefined
复制代码

第一个步骤已经实现了,但是很明显的是这样子会对传入的othis造成副作用,即给othis对象无缘无故添加了一个方法,所以:

Function.prototype.Zcall = function (othis) {
        othis.fn = this;
        othis.fn();
        delete othis.fn;
    }


副作用已经消除了,接下来就是参数的问题,这里有个问题是参数个数是不定的,貌似可以使用一个数组来arr保存住arguments里面的参数,然后再执行othis.fn(arr)。但是,这样等于说只给fn传了一个数组参数,并不能达到目的。

此时问题转化为我们如何实现像 othis.fn(arguments[0], arguments1, arguments2 ...) 这样的语句呢? 此时可以想起一个不怎么常用的方法eval

image.png

简单的说就是可以把字符串解析为JavaScript语句来执行。 借助eval,改写Zcall方法:

Function.prototype.Zcall = function (othis) {
    othis.fn = this;
    let args = [];
    for(let i = 1, len = arguments.length;i < len;i++) {
      args.push("arguments[" + i + "]");
    }
    // othis.fn();
    eval("othis.fn(" + args + ")");
    delete othis.fn;
  }
复制代码

其实就是用args把arguments用字符串的方式保存住,然后在eval方法中再把字符串重新解析为语句。


apply


同理来实现apply:

Function.prototype.Zapply = function (othis) {
    othis.fn = this;
    let argsArr = arguments[1];
    if (!arguments[1]) {
      let args = [];
      for(let i = 0, len = arguments[1].length;i < len;i++) {
        args.push("arguments[1][" + i + "]");
      }
      eval("othis.fn(" + args + ")");
    }else{
      othis.fn();
    }
    delete othis.fn;
  }

参考资料:

MDN-eval

MDN-apply

JavaScript深入之call和apply的模拟实现

相关文章
CMake Error: The source “xxx“ does not match the source “yyy“ used to generate cache. Re-run cmake
CMake Error: The source “xxx“ does not match the source “yyy“ used to generate cache. Re-run cmake
552 0
|
16天前
|
JavaScript 前端开发
|
2天前
No rule to make target ‘.xxxxxxxx‘, needed by ‘debug/xxxx.cpp‘. Stop.
No rule to make target ‘.xxxxxxxx‘, needed by ‘debug/xxxx.cpp‘. Stop.
10 5
|
前端开发
mvn clean package -Dmaven.test.skip=true 报错:[ERROR] Unknown lifecycle phase “.test.skip=true“.
mvn clean package -Dmaven.test.skip=true 报错:[ERROR] Unknown lifecycle phase “.test.skip=true“.
858 0
mvn clean package -Dmaven.test.skip=true 报错:[ERROR] Unknown lifecycle phase “.test.skip=true“.
|
JavaScript
一步一步实现call和apply方法,超简单!
前言 this 指向问题一直是一个老生常谈的问题了!我们对它可以说是又爱又恨,因为 this 指向常常没有按照我们的想法去指向谁,导致程序无缘出现许多 bug。所以我们常常直接强制改变程序中的 this 指向,我们常用的方法有 bind、apply 和 call,bind 与其它两个稍许不同,所以我们本篇文章专门讲解 call 和 apply 方法,并且手动模拟实现它们。
140 0
一步一步实现call和apply方法,超简单!
|
测试技术
gradle编译出错:Execution failed for task ':app:compileTestDebugJava'
版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/chaoyu168/article/details/50012843 随着更新gradle到1.12,出现问题。
1082 0
That command depends on command in Target 'XXX': script phase “[CP] Copy Pods Resourc 报错解决方法
That command depends on command in Target 'XXX': script phase “[CP] Copy Pods Resourc 报错解决方法
160 0
ES6—27:call_apply_bind方法总结
ES6—27:call_apply_bind方法总结
127 0
ES6—27:call_apply_bind方法总结