一句話:改變調用方法的this指向,示例以下:bash
function a(){
console.log(this);
}
a();
a.call({name:"西瓜"});
複製代碼
能夠看到,第一次this
指向了window
,第二次this
指向了傳入的對象;app
先來看一個東西,或許就能明白函數
var a = {
name:"西瓜",
run:function(){
console.log(this);
console.log(this.name);
}
}
a.run();
複製代碼
上面這段代碼,相信小夥伴都能看懂,其實,call執行的時候,也是作了這樣的處理;。學習
Function.prototype.MyCall = function(obj){
var newObj = obj || window;
newObj.fn = this;
var params = [...arguments].slice(1);
var result = newObj.fn(...params);
delete newObj.fn;
return result;
}
複製代碼
就上面的這段代碼,就實現了一個call的功能,來看下這段代碼都作了哪些事情ui
obj
存在,則新對象等於obj
,若obj
不存在,則等於window
;fn
函數(即爲要調用的函數);fn
刪除;來驗證一下是否正確this
function test(){
console.log(this);
}
test();
test.MyCall({name:"西瓜"});
複製代碼
結果以下圖: spa
能夠看到,結果和使用call的時候輸出的一致。這樣就本身手動實現了一個call方法;function f1(a){
console.log(1);
console.log(this);
}
function f2(){
console.log(2);
console.log(this);
}
f1.call(f2);
f1.call.call(f2);
複製代碼
想一下,這段代碼打印出來的會是一個什麼結果呢? prototype
f1.call(f2)
的打印結果,相信你們都能理解,這裏就不解釋了;重點來說一下
f1.call.call(f2)
; 首先,咱們用剛剛本身實現的call方法來試試,會不會出現一樣的結果;
f1.MyCall(f2);
f1.MyCall.MyCall(f2);
複製代碼
結果固然是同樣的啦!以下: code
爲何會這樣呢,來談談我對這個結果的理解吧(可能其餘小夥伴有更好的理解)! 把上面本身實現的call方法複製下來Function.prototype.MyCall = function(obj){
var newObj = obj || window;
newObj.fn = this;
var params = [...arguments].slice(1);
var result = newObj.fn(...params);
delete newObj.fn;
return result;
}
複製代碼
當咱們執行f1.MyCall.MyCall(f2)
的時候,上面這個MyCall
方法中的this
和newObj
指的分別是什麼? 個人理解是this
爲f1.MyCall
,即爲Function.prototype.MyCall
,newObj
爲f2
方法; 所當f1.MyCall.MyCall(f2)
執行的時候,結果就變了如下結果:cdn
var newObj = f2;
f2.fn = Function.prototype.MyCall;
複製代碼
接下來MyCall
的第5行是否是會執行newObj.fn
? 其實就是執行f2.MyCall()
這個結果你們應該都知道了吧;
若是說上面這個理解了,能夠想一想下面幾個會打印出什麼內容:
f1.call.call.call(f2)
f1.call.call.call.call(f2)
f1.call.call.call.call.call(f2)
複製代碼
其實都是同樣的哈!
除了call
,還有兩個相似的方法apply,bind
,這裏就不作過多的解釋了,相信小夥伴必定也能跟着這樣的思路去手寫出來。有什麼問題就給我留言吧!