call深入理解

function fn1() {
    console.log(1);
}
function fn2() {
    console.log(2);
}
fn1.call(fn2); // 1
fn1.call.call(fn2); // 2

  
首先fn1通过原型链找到Function.prototype上的call方法,然后再让call方法通过原型再找到Function原型上的call(因为call本身的值也是一个函数,所以同样可以让Function.prototype),在第二次找到call的时候再让方法执行,方法中的thisfn1.call,而this被fn2替代,然后再让fn1.call执行。
Function.prototype.call = test;
function test (context) {
    // 改变fn中的this关键字
    // eval(....);
    
    // 让fn方法执行
    this(); // 此时的this就是fn1
};

 fn1.call.call(fn2)就是test.call(fn2);test.call(fn2)中的this就是test,然后把call中this改成fn2,然后执行

Function.prototype.call = test;
function test (context) {
    // 改变fn中的this关键字
    // eval(....);
    
    // 让fn方法执行
    fn2(); //2
};

    

Function.prototype.myCall=function(myobj,...args){
        if(typeof myobj==='Function'){
             throw new TypeError('error')
       }
      const  fn=symbol('fn')    //唯一值
      myobj=myobj || window  //若没有传入对象,则绑定到window上
      myobj[fn]=this         //把函数赋值到对象的某个属性
      const result=myobj[fn](...args)
     delete  myobj[fn]       //删除fn声明
     return result
}

   结合mycall分析:

  • 先将 fn2 赋给临时变量 myobj。
  • this 所指向的对象就是一个函数对象:Function.prototype.myCall()。所以赋给 object.fn 临时属性指向的就是 Function.prototype.myCall()方法。
  • 由于 arguments 长度为 1,所以直接执行 myobj.fn()方法,也就是 myobj.myCall(),也就是 fn2.myCall()
  • fn2.myCall()实际上执行的是 global.fn2(),具体执行过程就不再熬述了,故输出了 2,没有返回值。

 

对call,apply的看法,理解 

首先需要了解apply,call的基本用法,其目的是改变调用方法中的this指向,将其指向为传入的对象

var console = window.console || {log: function () {}};   
var log = console.log;  
console.log = function(tips,message){   
   Function.prototype.apply.call(log, console, arguments);   
   //Function.prototype.call.call(log, console, arguments);  
   //Function.prototype.call.apply(log, [console, arguments]);   
    
 //传统方式  
 //var args=[].slice.call(arguments);  
 //log.apply(console,args);  
}  

  

分析:

      该怎么理解Function.prototype.apply.call(log,console,arguments);呢

      首先可以将Function.prototype.apply看成一个整体-->FunctionApply

       FunctionApply.call(log,console,arguments);

       那么将此句翻译一下

       log.FunctionApply(console,arguments);

       然后再翻译一下,你就懂了吧,就是一个普通方法调用了

       console.log(arguments);

Function.prototype.call.apply(log,[console.arguments]);

FunctionCall.apply(log,[console,arguments]);  
log.FunctionCall(console,arguments);  
console.log(arguments);  

tips:

    Function.prototype.apply.call  等同于Function.prototype.call.call

    Function.prototype.call.apply  等同于 Function.prototype.apply.apply

function testA(a){  
    console.log('aaaa',a);  
}  
Function.prototype.apply.call(testA,window,['Mike']) == testA.apply(window,['Mike']) == window.testA('Mike');  
//Function.prototype.call.call(testA,window,['Mike']);  
//Function.prototype.apply.apply(testA,[window,['Mike']]);  
//Function.prototype.call.apply(testA,[window,['Mike']]);  

  

  

posted @ 2018-06-08 15:24  吴小样  阅读(205)  评论(0编辑  收藏  举报