最近進修JavaScript,看了“You Don't Know JS”這本書,覺得是本JavaScript內功上乘心法,有1定JavaScript基礎朋友1定要看看(不推薦入門小朋友看,怕走火入魔)。作者知識淵博,理解透徹,行文流暢,案例經典,絕對的大神級人物。
本文將對書中關于JavaScript中this的講述做1個小結,也會加入1些自己的理解。算是拋磚,以期引玉。
this是1個標志符,指向某1個對象或undefined。
JavaScript是甚么?1門編程語言;編程語言干嗎的?編寫代碼;為啥編寫代碼?履行代碼,命令計算機處理事情。好了,寫好的JavaScript代碼是用來履行的,并且JavaScript Engine會指定1個履行環境(Execution Environment)。履行環境很復雜,簡單來講,可以理解為1個履行數據容器(JavaScript里面可以叫作對象)。JavaScript的代碼(1系列的語句)會在兩個地方履行,全局區域,和函數(Function)內部。
this就是履行環境里面的1個屬性(Property),指向履行所針對的某1個對象。
為了描寫清楚this和履行環境的關系,簡單來講,可以表述以下:
Executor_Environment = { invoke_stack:[statck1, statck2, ...], params: [param1, param2, ...], scope_chain:[scop1, scope2, ...], this: execute_ object, ... }
繼續追問下去。this指向的對象又是甚么?函數調用的時候,this指向的對象是函數履行的上下文,1個目標對象,是運行時由JavaScript Engine動態綁定的。
函數里面this的綁定情況有4種,下面將逐1介紹。原書作者強調某些場景下4種情況可能會有某兩個或3個都適用,需要排列功效的強度大小,這1點,我不太贊同,我覺得還是都可以歸并到某1種場景的。
JavaScript里面new關鍵字后接1個Function調用,會新創建1個對象,履行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的作用就是強行指定Function里面this所應當指向的對象。
call的1個小例子:
function sayHi(){ console.log("Hi,"+ this.name); } var p = {name:"Kevin", age: 26}; sayHi.call(p);
這里有兩層意思,Function是對象的1個屬性,通過對象來訪問Function并立即調用。這類情況下,Function里面的this指向該對象。
例子:
function sayHi(){ console.log("Hi,"+ this.name); } var p = {name:"Kevin", age: 26, hi: sayHi}; p.hi();
通過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。
說實話,我只是猜想。全局區域的語句也需要1個履行環境,該履行環境也有1個this標志符,指向Global對象。閱讀器里面就是window。這1點“You Don't Know JS”原書中沒有提及。
全局區域輸入以下代碼試試:
var name = "James"; console.log("I am "+ this.name); // I am James
You Don't Know JS