You don't know JavaScript是github上一個系列文章
初看到這一標題的時候,感受怎麼老外也搞標題黨,用這種衝突性比較強的題目吸引眼球,以至最初真沒去看內容。直到出了中文版《你不知道的JavaScript》,一看評價你們都說好,買來一讀,內容果真很好,不少地方,讓我這個半路轉行JavaScript的人豁然開朗。中文版如今出了上卷,中卷應該很快會推出,下卷就要等久一點了javascript
1.現代JavaScript已經再也不是解釋執行的,而是編譯執行的。可是與傳統的編譯語言不一樣,它不是提早編譯,編譯結果不能進行移植。編譯過程當中,一樣會通過分詞/詞法分析,解析/語法分析,代碼生成三個階段。html
2.以var a = 2;語句爲例,對這一程序語句對處理,須要通過引擎,編譯器,做用域三者的配合。其中,引擎從頭至尾負責整個javascript程序的編譯和執行過程;編譯器負責語法分析和代碼生成;做用域負責收集並維護由全部聲明的標識符組成的系列查詢,並實施一套規則,肯定當前執行的代碼對這些標識符的訪問權限。java
3.對於var a = 2;編譯器首先查找做用域中是否已經有該名稱的變量,而後引擎中執行編譯器生成的代碼時,會首先查找做用域。若是找到就執行賦值操做,不然就拋出異常git
4.引擎對變量的查找有兩種:LHS查詢和RHS查詢。當變量出現中賦值操做左側時是LHS查詢,出現中右側是RHS查詢es6
1.詞法做用域就是定義在詞法階段的做用域。詞法做用域是由你在寫代碼時將變量和塊做用域寫在哪裏決定的,詞法處理器分析代碼時會保持做用域不變github
function foo(a){ var b = a * 2; function bar(c){ console.log(a,b,c); } bar(b * 3); } foo(2);
(function fun(){})()
1.以下示例 web
a=2; var a; console.log(a);
上述代碼輸出的不是undefined,而是2。由於上述代碼須要通過編譯器的編譯,編譯過程當中首先會進行變量聲明,而後再由引擎進行變量賦值,因此,上述變量聲明雖然寫在第二行,可是聲明過程是首先執行的ajax
console.log(a); var a = 2;
foo(); function foo(){ console.log(a);//undefined var a = 2; }
1.詞法做用域是一套引擎如何尋找變量以及會在何處找到變量的規則。詞法做用域最重要的特徵是它的定義過程發生中代碼的書寫階段segmentfault
2.動態做用域讓做用域做爲一個在運行時就被動態肯定的形式,而不是在寫代碼時進行靜態肯定的形式。設計模式
function foo(){ console.log(a);//2 } function bar(){ var a = 3; foo(); } var a = 2; bar();
詞法做用域讓foo()中的a經過RHS引用到了全局做用域中的a,因此輸出2;動態做用域不關心函數和做用域如何聲明以及在何處聲明,只關心從何處調用。換言之,做用域鏈是基於調用棧的,而不是代碼中的做用域嵌套。若是以動態做用域來看,上面代碼中執行時會輸出3
3.JavaScript不具有動態做用域,可是this機制中某種程度上很像動態做用域,this關注函數如何調用。
var obj = { msg : 'awesome', cool:function(){ setTimeout(function timer(){ console.log(this.msg); },100); } }; var msg = 'not awesome'; obj.cool(); //not awesome var obj = { msg : 'awesome', cool:function(){ var self = this; setTimeout(function timer( console.log(self.msg); },100); } }; var msg = 'not awesome'; obj.cool(); //awesome var obj = { msg : 'awesome', cool:function(){ setTimeout(() => { console.log(this.msg); },100); } }; var msg = 'not awesome'; obj.cool(); //awesome var obj = { msg : 'awesome', cool:function(){ setTimeout(function timer() { console.log(this.msg); }.bind(this),100); } }; var msg = 'not awesome'; obj.cool(); //awesome
function foo(){ console.log(this.a); } var a = 2; foo();//2
function foo(){ console.log(this.a); } var obj={ a:2, foo:foo }; obj.foo();//2
var obj = {}; Object.defineProperty( obj, "a", { value:2, writable:true, configurable:true, enumerable:true } ); obj.a;//2
var obj = { this._a_ = 2; get a(){ return this._a_; }, set a(val){ this._a_ = val * 2; } }; Object.defineProperty( obj, "b", { get:function(){return this._a_ * 2}, enumerable:true } )
本節爲以爲書中寫的有點繞,不清晰。推薦閱讀