精华内容
下载资源
问答
  • call 简易版(不支持传参的方法)实现思路: ...这样就间接绑定了this的指向,并实现call Function.prototype.mycall=function(con){ //给Function的原型对象上加上mycall方法 con.fun = this; //this即...

    call

    • 简易版(不支持传参的方法)实现思路:
      • 给目标对象创建一个属性,将要调用的方法绑定到这个属性上
      • 直接运行刚刚创建的属性
      • 删除这个属性
        这样就间接绑定了this的指向,并实现了call
    Function.prototype.mycall=function(con){   //给Function的原型对象上加上mycall方法
        con.fun = this;  //this即为要绑定的方法
        con.fun();
        delete con.fun;
    }
    
    let obj1 = {
        name:"helloworld"
    }
    
    function fn(){
        console.log(this.name);
    }
    
    fn.call(obj1);   //helloworld
    
    fn.mycall(obj1); //helloworld
    
    • 中等版,支持传参函数的call实现思路
      • 主要思路如上,不一样的是要通过arguments取出除第一位之外的所有参数放到一个数组里,然后通过展开运算符给要执行的函数或方法传参,如下:
    Function.prototype.mycall = function(con){
        con.fun = this;   //给目标对象新建一个属性,绑定这个函数
        let paramsArr = new Array();  //新建一个空数组
        for(let i=1;i<arguments.length;i++){
            paramsArr.push(arguments[i]);
        }
        con.fun(...paramsArr);  //运行一下
        delete con.fun;   //删除目标对象上的fun属性
    }
    
    let testObj = {   //定义一个对象
        num1:10,
        num2:9.5
    }
    
    function add(p1,p2,p3){   //定义函数
        console.log(this.num1+this.num2+p1+p2+p3);
    }
    
    add.call(testObj,1,2,3); //原生call    25.5
    add.mycall(testObj,1,2,3);//实现的call  25.5
    
    • 最终版(没有参数时,指向window)
    
    Function.prototype.mycall = function(con){
        con = new Object(con) || window || global;
        con.fun = this;   //给目标对象新建一个属性,绑定这个函数
        let paramsArr = new Array();  //新建一个空数组
        for(let i=1;i<arguments.length;i++){
            paramsArr.push(arguments[i]);
        }
        con.fun(...paramsArr);  //运行一下
        delete con.fun;   //删除目标对象上的fun属性
    }
    
    // let testObj = {   //定义一个对象
    //     num1:10,
    //     num2:9.5
    // }
    
    function conso(p1,p2,p3){   //定义函数
        console.log(this.num1,this.num2,p1,p2,p3);
    }
    
    conso.call(1,2,3); //原生call    undefined undefined 2 3 undefined
    conso.mycall(1,2,3);//实现的call  undefined undefined 2 3 undefined
    
    
    展开全文
  • js手动实现call,apply,bind

    千次阅读 2018-08-28 11:52:32
      我也不知道为什么只能显示一部分 好气哦 看原文吧  ... call apply返回函数结果, bind 返回新函数 call 改变this的指向  首先我们知道,对象上的方法,在调用时,this是指向对象的。 let o = { ...

    原文https://www.jianshu.com/p/3b69fb0d4c2f 

     

    我也不知道为什么只能显示一部分  好气哦  看原文吧 

    先分析下3个方法的作用

    • 改变this的指向。
    • 传入参数。
    • call apply返回函数结果, bind 返回新函数

    call

    改变this的指向 

    首先我们知道,对象上的方法,在调用时,this是指向对象的。

    let o = {
        fn:function(){
            console.log(this);
        }
    }
    o.fn() //  Object {fn: function}  

     

    // 函数原型上添加 myCall方法 来模拟call
    Function.prototype.myCall = function(obj){
        //我们要让传入的obj成为, 函数调用时的this值.
        obj._fn_ = this;  //在obj上添加_fn_属性,值是this(要调用此方法的那个函数对象)。
        obj._fn_();       //在obj上调用函数,那函数的this值就是obj.
        delete obj._fn_; // 再删除obj的_fn_属性,去除影响.
        //_fn_ 只是个属性名 你可以随意起名,但是要注意可能会覆盖obj上本来就有的属性
    }
    

    下面测试一下

    let test = {
        name:'test'
    }
    let o = {
        name:'o',
        fn:function(){
            console.log(this.name);
        }
    }
    o.fn() // "o"
    o.fn.call(test) // "test"
    o.fn.myCall(test) // "test"
    

    传入参数

    • 最简单实现,用ES6
    // 只需要在原来的基础上 用下拓展运算符 剩余运算符即可
    Function.prototype.myCall = function(obj,...arg){
        obj._fn_ = this;
        obj._fn_(...arg);
        delete obj._fn_;
    }
    //测试
    let test = {
        name:'test'
    }
    let o = {
        name:'o',
        fn:function(){
            console.log(this.name, ...arguments);  //这里把参数显示一下
        }
    }
    o.fn(1,2,3) // "o" 1 2 3
    o.fn.call(test,1,2,3) // "test" 1 2 3
    o.fn.myCall(test,1,2,3) // "test" 1 2 3
    // 没问题
    
    • 用eval 方法
      eval方法,会对传入的字符串,当做JS代码进行解析,执行。
    Function.prototype.myCall = function(obj){
        let arg = [];
        for(let i = 1 ; i<arguments.length ; i++){
            arg.push( 'arguments[' + i + ']' ) ;
            // 这里要push 这行字符串  而不是直接push 值
            // 因为直接push值会导致一些问题
            // 例如: push一个数组 [1,2,3]
            // 在下面
    展开全文
  • 手动实现call() , apply() , bind()

    千次阅读 2018-08-01 17:20:24
    这篇文章简单的介绍了实现call() , apply() , bind()的思路 实现call(obj,arg,arg....) 将目标函数的this指向传入的第一个对象,参数为不定长,且立即执行 实现思路 改变this指向:可以将目标函数作为这个对象的...

    这篇文章简单的介绍了实现call() , apply() , bind()的思路

    实现call(obj,arg,arg....)

    将目标函数的this指向传入的第一个对象,参数为不定长,且立即执行

    实现思路

    • 改变this指向:可以将目标函数作为这个对象的属性
    • 利用arguments类数组对象实现参数不定长
    • 不能增加对象的属性,所以在结尾需要delete

    那么怎么将不定长的参数传递给函数呢?有三种办法:eval,apply,ES6的解构语法

    eval('obj.fn('+args+'));
    obj.fn.apply(obj,args);
    obj.fn(...args);
    Function.prototype.mycall = function(obj){
             var args = Array.prototype.slice.apply(arguments,[1]);
             obj.fn = this;
             obj.fn(...args);//es6的解构语法,也可以使用obj.fn.apply(obj,args);
             delete  obj.fn;
    }

    使用eval时,eval会将一个字符串解析为变量,所以如果传入的参数为字符串,会报 xxx is not defined,解决办法如下:

    Function.prototype.mycall = function(obj){
            obj = obj||window;
             var args = [];
            for(var i = 1 ; i < arguments.length; i++) {
                      args.push('arguments[' + i + ']');
             }
    
             obj.fn = this;
             eval('obj.fn('+args+'));
             delete  obj.fn;
    }

     

    实现apply()

    与call()只有一个区别,apply第二个参数为数组

    Function.prototype.myapply = function(obj,arr){
            obj.fn = this;
             if(!arr){
                 obj.fn();
            }else{
                 var args = []; 
           for(var i = 0; i < arr.length; i++) {
                 args.push('arr[' + i + ']');
             }
             
             eval('obj.fn('+args+')');
     }
           
             delete  obj.fn;
    
    }

    实现bind()

    返回一个与被调函数具有相同函数体的新函数,且这个新函数也能使用new操作符。

    实现思路

    1. 返回一个新函数,可以使用闭包
    2. bind()传入的参数长度不定,使用函数内置的arguments对象数组,可利用Array.prototype.slice.call(arguments,1 )将其转化为数组
    3. 返回的新函数中,使用apply改变被调用函数的this指向,将arguments转化成的数组作为apply的第二个参数
    4. 因为返回的新函数也可以使用new操作符,所以在新函数内部需要判断是否使用了new操作符(为什么需要判断,后面会讲解到),如果使用则将apply的第一个参数设置为新创建的对象,如果没有则设置为在调用bind()时所传入的对象(不传的话默认为window)。

    需要注意的是怎么去判断是否使用了new操作符呢?在解决这个问题之前,我们先看使用new操作符时具体干了些什么,下面是new操作符的简单实现过程:

    //简洁版的new操作符实现过程
    
    function newFunc(constructor){
          //第一步:创建一个空对象obj 
            var obj = {};
           //第二步:将构造函数 constructor的原型对象赋给obj的原型
            obj.__proto__ = constructor.prototype;
          //第三步:将构造函数 constructor中的this指向obj,并立即执行构造函数内部的操作
            constructor.apply(obj);
          //第四步:返回这个对象
            return obj;
    }

    new操作符的一个过程相当于继承,新创建的构造函数的实例可以访问构造函数的原型链

    在new操作符实现过程的第三步中,会将构造函数 constructor中的this指向obj,并立即执行构造函数内部的操作,那么,当在执行函数内部的操作时,如果不进行判断是否使用了new,就会导致 " 将构造函数 constructor中的this指向obj " 这一过程失效,具体原因请看下面的模仿实现bind()的代码:

    Function.prototype.testBind = function(object){
    
              var that = this,
                  args = Array.prototype.slice.call(arguments,1),
                  bound = function(){
                        return that.apply(this instanceof fNOP?this:object||window,
                             args.concat.apply(Array.from(arguments)));
              };
    
            //创建一个中转函数fNOP,让bound间接继承目标函数的原型
              var fNOP =  function(){};
              fNOP.prototype= that.prototype;   
              bound.prototype= new fNOP();  
      
              return bound;
    }

    重点:创建一个中转函数fNOP,让bound间接继承目标函数的原型,一开始我想为什么不直接让 bound.prototype = that.prototype ,后来才发现直接赋值后,bound.prototype和that.prototype指向同一块内容,如果改变bound.prototype就会直接影响that.prototype,使用一个中转函数, bound.prototype= new fNOP()将bound.prototype的__poro__指向fNOP.prototype,然后fNOP.prototype = that.prototype,所以此时改变bound.prototype并不会影响that.prototype。

    另外:上面实现bind()的代码中使用apply的地方可以换成原生实现的代码

    展开全文
  • 1.首先,了解call方法的要点 语法:function.call(thisArg, arg1, arg2, ...) 参数: 1.thisArg 在 function 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,...

    1.首先,了解call方法的要点

    • 语法:function.call(thisArg, arg1, arg2, ...)
      参数:
      1.thisArg
      在 function 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。
      this指向:非严格模式下,指向window。严格模式下,为undefined。
      示例:
    	var a = 2;
        var obj = {
            name: 'ha',
            age: 12,
            getSome : function () {
                // 'use strict'; 非严格模式下
                console.log(this); // window
                console.log(a); // 2
            }
        }
        	obj.getSome.call(undefined);
    ---------------------------------------------------------	
    	var a = 2;
    	 var obj = {
    	        name: 'ha',
    	        age: 12,
    	        getSome : function () {
    	            'use strict'; // 严格模式下
    	            console.log(this); // undefined
    	            console.log(a); // 2
    	        }
    	    }
    
    	obj.getSome.call(undefined);
    
    • 返回值
      使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined。
      手动实现时,还必须将值return出来。

    2.手动实现call方法

    要点:

    • 返回值
    • 将调用者,转变为this下的一个方法,执行完后,记得删除。
      示例:
    const obj = {
    	  name: 'ha',
          age: 12,
          getSome : function (a, b) {
              console.log(this);
              return a + b;
          }
      }
    
      Function.prototype.myCall = function (context = window,...args) {
          var func = this,
          fn = Symbol('fn'); // 确保属性名独一无二
          context[fn] = func; // 这里的转变:调用者(函数)作为context对象的方法
          var res = context[fn](...args);
          delete context[fn]; // 记得将context对象上刚刚新增的func方法删除
          return res;
      }
    
      const res = obj.getSome.myCall(obj, 1, 2, 3);
      console.log(res);
    

    结果如下:
    在这里插入图片描述

    展开全文
  • js代码-手写代码,手动实现new,stringtify,parse,call,apply,bind等常见函数
  • 手动实现apply、call、bind

    千次阅读 2020-05-01 18:03:28
    手动实现apply、call、bind 每个Function对象都存在apply()、call()、bind()方法,其作用都是可以在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。 apply funct.apply...
  • 手动实现一个call方法 方法如下: Function.prototype.myCall = function(object) { let obj = object || window; // 如果没有传this参数,this将指向window obj.fn = this; // 获取函数本身,此时调用call...
  • 手动实现js的call, apply, bind, instanceof方法call方法apply方法bind 方法 call方法 /** * 实现一个caLl方法 */ Function.prototype.mycall = function(context) { //判断是否传入指定的对象 context = ...
  • VC2005手动添加定时器函数

    千次阅读 2011-08-09 19:15:19
    【原创】VC2005手动添加定时器函数  2008-10-23 10:26:01| 分类: VC++ Techno- | 标签: |字号大中小 订阅 如何手工在VC2005中添加定时器的功能? 文件:SmallBoxSystemDlg.cpp 中添
  • decode(record_method, ''自动'', 1, ''手动'' , 2, '''') record_method, remark, '''|| operator_id ||''' , sysdate from '|| v_table_name ||''; execute immediate V_SQL; commit; p_proc(v_seq_num, '...
  • JS手动实现一个new操作符

    万次阅读 2019-06-19 18:01:52
    手动实现一个 new 操作符,首先要知道 new 操作符都做了什么事,即构造函数的内部原理: 1.创建一个新对象; 2.链接到原型(将构造函数的 prototype 赋值给新对象的 __proto__); 3.绑定this(构造函数中的this...
  • 几种函数调用方式 __cdecl 是C DECLaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不会要求调用者传递多少...
  • 手动实现new

    2020-05-17 12:03:54
    手动实现一个new 首先来看一个案列 function Dog (name,age){ this.name = name; this.age = age; this.say = function () { console.log("I am " + this.name) } } var dog = new Dog('旺财',4) console....
  • 手动实现ES5的bind方法

    2018-10-16 23:26:14
    bind可用于实现函数,则实现时需要同时保存bind()被传入的参数arguments以及返回的新创建函数被传入的参数arguments function list() { return Array.prototype.slice.call(arguments); } var ...
  • 绘制函数调用关系图(call graph),对开发人员理解源码有非常大的帮助,特别是在以下情况: 大型项目,庞杂的代码量; 项目文档缺失,特别是设计文档、流程图的缺失; 第三方代码库,如开源项目; 检查实际函数...
  • 一、首先来看一下他们的...1、call 和 apply 都可以对函数进行直接调用,bind 方法返回的是一个函数,需要手动调用函数 let obj= { name:'小米', print(){ console.log(`${this.name}`) } } let obj1 = { name:'
  • 使用call命令在GDB中重复调用某函数

    千次阅读 2015-03-08 15:51:18
    在白盒测试中经常使用GDB进行函数的分支覆盖测试,但在测试对象函数触发很困难,测试效率就很低下。 假设测试函数fun1有10条分支。每次进入fun1需设置10个变量。 那么一般情况下要在GDB中操作10 * 10 = 100次才能将...
  • JS中的call()方法和apply()方法用法总结

    万次阅读 多人点赞 2017-04-27 15:14:48
    1. 每个函数都包含两个非继承而来的方法:call()方法和apply()方法。 2. 相同点:这两个方法的作用是一样的。都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。
  • call实现原理

    千次阅读 2020-05-20 15:54:38
    Function.prototype:call/apply/bind 是Function原型上的方法,这三个方法都是用来改变函数中的THIS的 call:[function].call([context],params1,params2,…) (1)[function]作为Function内置类的一个实例,可以...
  • web_service_call()--常用函数 调用Web服务。该函数是专门针对于Webservice协议来提供一个调用功能,webservice是基于一个XML为基础的网络API的一个接口,loadrunner使用web_service_call来进行调用的。 intweb_...
  • 手动跟踪函数的调用过程

    千次阅读 2011-10-13 21:12:57
    都知道C语言实现调用是通过桟来实现的,那么我们将函数调用过程中的过程记录叫做call frame,而上述的两个函数就是在进入函数时和退出函数时被调用。关于这个__attribute__这个东西我也不是很清楚,明天研究一下再说...
  • js手动实现promise

    千次阅读 2018-09-04 08:22:48
    构造函数内调用函数(apply参数是数组,call参数是一个一个的,调用函数改变this的指向) // resolve和reject的this都是当前的Promise对象。 使用bind方法不会立即执行函数,而是返回一个新的函数!!! fn....
  • 一、添加消息处理函数PreTranslateMessage,此函数可以通过MFC ClassWizard添加BOOL CPreTranslateMessageDlg::PreTranslateMessage(MSG* pMsg){  if (pMsg->message==WM_LBUTTONDOWN)  {  MessageBox(“三三四...
  • cflow是一款静态分析C语言代码的工具,通过它可以生成函数调用关系。 官网:https://www.gnu.org/software/cflow/ 下载:http://ftp.gnu.org/gnu/cflow/ 手册:https://www.gnu.org/software/cflow...
  • c++虚函数实现机制及内存模型

    千次阅读 2015-11-19 15:35:43
    前言 大家都应该知道C++的精髓是虚... 虚函数实现多态(动态绑定)/接口函数的基础. 可以说: 没有虚函数, C++将变得一无是处! 既然是C++的精髓, 那么我们有必要了解一下她的实现方式吗? 有必要! 既然C++是从C语言

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 76,774
精华内容 30,709
关键字:

手动实现call函数