最近進修JavaScript,看了“You Don't Know JS”這本書,覺得是本JavaScript內功上乘心法,有一定JavaScript基礎朋友一定要看看(不推薦入門小朋友看,怕走火入魔)。作者知識淵博,理解透徹,行文流暢,案例經典,絕對的大神級人物。
本文將對書中關於JavaScript中this的講述做一個小結,也會加入一些自己的理解。算是拋磚,以期引玉。
JavaScript裏面this到底是什麼?
this是一個標誌符,指向某一個對象或者undefined。
JavaScript是什麼?一門編程語言;編程語言幹嘛的?編寫代碼;爲啥編寫代碼?執行代碼,命令計算機處理事情。好了,寫好的JavaScript代碼是用來執行的,並且JavaScript Engine會指定一個執行環境(Execution Environment)。執行環境很複雜,簡單來說,可以理解爲一個執行數據容器(JavaScript裏面可以叫作對象)。JavaScript的代碼(一系列的語句)會在兩個地方執行,全局區域,以及函數(Function)內部。
this就是執行環境裏面的一個屬性(Property),指向執行所針對的某一個對象。
爲了描述清楚this和執行環境的關係,簡單來說,可以表述如下:
Executor_Environment = {
invoke_stack:[statck1, statck2, ...],
params: [param1, param2, ...],
scope_chain:[scop1, scope2, ...],
this: execute_ object,
...
}
繼續追問下去。this指向的對象又是什麼?函數調用的時候,this指向的對象是函數執行的上下文,一個目標對象,是運行時由JavaScript Engine動態綁定的。
函數裏面this的4種場景
函數裏面this的綁定情況有4種,下面將逐一介紹。原書作者強調某些場景下四種情況可能會有某兩個或者三個都適用,需要排列效用的強度大小,這一點,我不太贊同,我覺得還是都可以歸併到某一種場景的。
new關鍵字
JavaScript裏面new關鍵字後接一個Function調用,會新創建一個對象,執行Function的時候,JavaScript Engine會把新創建的對象賦值給this,即此時this指向新創建的對象。下面給出兩個例子:
new例子1:
function Func1(){
this.a = 3;
}
var a1 = new Func1();
console.log(a1.a); // 3
new例子2:
function Func2(){
this.a = 3;
return {};
}
var a2 = new Func2();
console.log(a2.a); // undefined
後面的例子是想說,如果Function裏面有return語句,那麼new語句新創建的對象會被丟棄!
call和apply
call和apply的作用就是強行指定Function裏面this所應該指向的對象。
call的一個小例子:
function sayHi(){
console.log("Hi,"+ this.name);
}
var p = {name:"Kevin", age: 26};
sayHi.call(p);
作爲對象的屬性調用
這裏有兩層意思,Function是對象的一個屬性,通過對象來訪問Function並立即調用。這種情況下,Function裏面的this指向該對象。
例子:
function sayHi(){
console.log("Hi,"+ this.name);
}
var p = {name:"Kevin", age: 26, hi: sayHi};
p.hi();
直接調用Function
通過Function的名字,直接調用Function,通常JavaScript Engine會把Global綁定給this。瀏覽器裏面Global是window。不過據說"use strict"情況下,this指向undefined(嚴格來說undefined在JavaScript裏面不是對象)。
Function直接調用的小例子:
function sayHi(){
console.log("Hi,"+ this.name);
console.log(this);
}
var name = "Just Joke";
sayHi(); // output:Hi, Just Joke
// followed global object, which contain name, sayHi。
全局區域裏面的this代表什麼
說實話,我只是猜測。全局區域的語句也需要一個執行環境,該執行環境也有一個this標誌符,指向Global對象。瀏覽器裏面就是window。這一點“You Don't Know JS”原書中沒有提及。
全局區域輸入以下代碼試試:
var name = "James";
console.log("I am "+ this.name); // I am James