題目:
function fn(a,b){ console.log(this); console.log(a); console.log(a+b);}fn.call(1);fn.call.call(fn);fn.call.call.call(fn,1,2);fn.call.call.call.call(fn,1,2,3);
答案:
fn.call(1); // 1,undefined,NaN
fn.call.call(fn); // fn,undefined,NaN
fn.call.call.call(fn,1,2); // 1,2,NaN
fn.call.call.call.call(fn,1,2,3); // 1,2,5
深層解題思路:
fn.call(1);call的第一個參數改變call前面函數裡的關鍵字this所以輸出1;後面沒有參數所以a,b為undefined,相加結果為NaN;
fn.call.call(fn);這一塊是個痛點,不過也很好理解! fn.call 找到Function.prototype上的call方法(這也是一個函數,也是函數類
的一個執行個體,也可以繼續調用call/apply等方法)我們可以把fn.call看成一個函數 A 那麼接下就等於A.call(fn),這
裡執行call方法,把 A 中的關鍵字this修改為函數 fn ,然後再把函數 A(fn.call) 執行;
fn.call.call.call(fn,1,2);通過上一條的原型鏈的方法我們可以把 fn.call.call.call 看成 A(fn.call.call).call 執行,此時括
裡的參數 fn 已經作為函數執行了,所以就成了 A.call(1,2) 執行!1作為第一個參數改變 call 前面函數裡的this,
後面的參數作為實參傳遞到函數的形參裡!
fn.call.call.call.call(fn,1,2,3); 同上一條原理!
概括性總結:
不怎麼理解的話也可以記住這個概括性訣竅:
碰到兩個及兩個以上的call都是讓第一個參數執行,第一個參數必須是函數;
第二個參數是改變第一個參數中this;
第三個及第三個以後的參數作為實參傳給第一個參數。