曾經我以為我掌握了this,直到不斷學習,才發現真是個無知...
在前面的系列中我們已經知道,當函式被呼叫執行時,變數物件會生成,這個這時候,this的指向會被確定。因此我們首先要牢記一個非常重要的結論,當前函式的this是在函式被呼叫執行的時候才確定的。如果當前的執行上下文處於函式呼叫棧的棧頂,那麼這個時候變數物件會變成活動物件,同時this的指向確認。
正是由於這個原因,才導致一個函式內部的this到底指向誰是非常靈活且不確定的,這也是this難以被真正理解的原因所在。例如,下面的例子,同一個函式由於呼叫的方式不同,它內部的this指向了不同的物件。
var a = 10;
var obj = {
a: 20
}
function fn() {
console.log(this.a);
}
fn(); //10
fn.call(obj);//20複製程式碼
通過a值的不同表現,我們可以知道this分別指向了window與obj。
接下來,我們一步步來分析this中的具體表現。
1. 全域性物件中的this
在之前變數物件的筆記中曾提到過,全域性物件的變數物件是一個比較特殊的存在。在全域性物件中,this指向它本身,因此相對簡單,沒有那麼多複雜的情況需要考慮。
//通過this繫結到全域性物件
this.a1 = 20;
//通過宣告繫結到變數物件,但在全域性環境中,變數物件就是它本身
var a2 = 10;
//僅僅只有賦值操作,識別符號會隱式繫結全域性物件
a3 = 30;
複製程式碼
2. 函式中的this
在一開始的例子中,同一個函式中的this由於呼叫方式不同導致this指向不同,因此,this最終指向誰,與呼叫該函式的方式息息相關。
在一個函式的執行上下文中,this由該函式的呼叫者提供,由呼叫函式的方式來決定其指向。
function fn() {
console.log(this);
}
fn(); //fn為呼叫者複製程式碼
如果呼叫者被某一個物件所擁有,那麼在呼叫該函式時,內部的this指向該物件。如果呼叫者函式獨立呼叫,那麼該函式內部的this則指向undefined。但是在非嚴格模式中,當this指向undefined時,他會自動指向全域性物件。
//為了能夠準確判斷,我們在函式內部使用嚴格模式
//因為非嚴格模式會自動指向全域性
function fn() {
'use strict';
console.log(this);
}
fn(); //fn是呼叫者,獨立呼叫,this為undefined
window.fn(); //fn是呼叫者,被window所擁有,this為window物件複製程式碼
函式是獨立呼叫,還是被某個物件所擁有,是非常容易辨認的。綜合上面的結論,下面結合一些簡單的例子來分析。
//demo01
var a = 20;
var obj = {
a: 40
}
function fn() {
console.log('fn this: ',this);
function foo() {
console.log(this.a)
}
foo();
}
fn.call(obj);
fn();複製程式碼
算了,不寫了..................................................
越寫下去,發現自己記錄的這些,還不如'飢人谷方應杭'說的一句話:this 就是 call 的第一個引數!call 的其他引數統稱為 arguments。
當你明白了方方說的,call/apply/bind都不是問題了...
這些都是我以往的學習筆記。如果您看到此筆記,希望您能指出我的錯誤。有這麼一個群,裡面的小夥伴互相監督,堅持每天輸出自己的學習心得,不輸出就出局。希望您能加入,我們一起終身學習。歡迎新增我的個人微訊號:Pan1005919589