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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM