• Function.prototype.apply.call 理解分析


    首先需要了解apply,call的基本用法,其目的是改变调用方法中的this指向,将其指向为传入的对象,改变this的指向,两种方法接收参数的方式不同。

    代码:console.log

    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);  
    }  

    执行结果:

    console.log("测试","This is test");  
    测试 This is test  

    分析:

    该怎么理解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']);  
    //Function.prototype.call.call(testA,window,['Mike']);  
    //testA.apply(window,['Mike']);  
    //window.testA('Mike');  
    //Function.prototype.apply.apply(testA,[window,['Mike']]);  
    //Function.prototype.call.apply(testA,[window,['Mike']]);  

    以上执行结果都一样

    为:aaaa Mike

    总结使用用法:

    XXX可以是call或者是apply,child一定是parent可指向的对象

    Function.prototype.XXX.call(child,parent,arguments||array);

    Function.prototype.XXX.apply(child,[parent,arguments||array]);

    --------------------------------------------------------------------------------------------------------------------------------------------------------------

    终极方法

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

    这么一对比,第三种方案妥妥的胜出啊,不用考虑兼容,代码简短,虽然不是很好理解~~

    说了这么多废话,Function.prototype.apply.call什么时候用,就是在这种应用场景。

    如果还有其他的话,那就是那些奇葩面试题,比如:

    var f1=function(){console.log(1)};
    var f2=function(){console.log(2)};
    Function.prototype.call.call(Function.prototype.call,f2)//2
    Function.prototype.call.call(f1,f2);//1
    昨天在网上看到一个很有意思的js面试题,就跟同事讨论了下,发现刚开始很绕最后豁然开朗,明白过来之后发现还是挺简单的,跟大家分享下!
    题目如下:var a = Function.prototype.call.apply( function(a){return a;},  [0,4,3] );        alert(a);
    分析步骤如下:
    1、将Function.prototype.call当成整体,call方法是由浏览器实现的本地方法,是函数类型的内部方法
    var a = (Function.prototype.call).apply(function(a){return a;}, [0,4,3]);
     
    2、fun.apply(obj,args)等价于obj.fun(args),这一步是重点,必须理解!
    (function(a){return a;}).apply(0,[4,3])
    (function(a){return a;}).call(0,4,3)
     
    3、 到这步结果就很明显了,a就是4,alert的结果就是4
     
    这个题目迷惑的点就在于Function.prototype.call,理解好了,就清晰明了了!
    ------------------------------------------------------------------------------------------------------------
    ------------------------------------------------------------------------------------------------------------
    补充理解:

    根据 call 方法的调用规则,Function.prototype.apply.call( fn, thisArg, args ) 中的第一个参数 fn,将作为 Function.prototype.apply(以下简称为: apply) 中 this 的值,剩余的两个参数 thisArg 和 args 都将被传递给 apply。

    (为便于以下的说明,我们先来看一下 apply 的正常使用方式:fn.apply( thisArg, args ),也就是说,我们要通过 apply 的方式来调用函数 fn,此时 fn 中 this 的值为 apply 的第一个参数 thisArg, apply 的第二个参数 args 则被传递给了 fn,从而实现对 fn 的调用。然而,这里有一个要点,一般来说,我们都不会太去关注,那就是,apply 方法中的 this 此时应该指向哪个值呢?没错,应该指向 fn。好了,我们继续往下看)

    虽然我们对 apply 的具体实现细节不清楚,但可以肯定的是,apply 中 this 的值即是要通过 apply 的方式来调用的函数(在此例中为 fn)。既然已经知道要通过 apply 方法来调用 fn,那么我们继续往下看:

    根据 apply 方法的调用规则,在此例中,传递给 apply 方法的第一个参数 thisArg 将作为 fn 中 this 的值,第二个参数 args 将被传递给 fn,从而实现对 fn 的调用。到这里我们就可以看到 Function.prototype.apply.call( fn, thisArg, args ) 这个调用其实等价于 fn.apply( thisArg, args ) 这个调用。

    转载自:https://zhuanlan.zhihu.com/p/62678594

  • 相关阅读:
    docker安装rabbitmq
    ios 崩溃日志揭秘
    Ubuntu apache2下建立django开发环境
    Ubuntu tomcat
    MySQLdb插入后获得插入id
    使用终端实现DMG、ISO格式互转
    ios学习笔记:jison(转)
    ios开发应用内实现多语言自由切换 (转)
    获取项目的名称及版本号
    工具收集
  • 原文地址:https://www.cnblogs.com/web-record/p/10477778.html
Copyright © 2020-2023  润新知