最近剛剛看完了《你不知道的 JavaScript》上卷,對 JavaScript 有了更進一步的瞭解。javascript
《你不知道的 JavaScript》上卷由兩部分組成,第一部分是《做用域和閉包》,第二部分是《this 和對象原型》。下面我會按照簡單介紹一下每一章的主要內容及閱讀感覺。java
第一部分《做用域和閉包》es6
在這一章節中,做者經過引擎、編譯器、做用域之間的對話,將這三者之間的關係及做用生動形象地展示出來,並引出了 LHS 查詢和 RHS 查詢的概念。設計模式
eval()
;with
。這一章做者介紹了詞法做用域以及欺騙詞法的方式。說來慚愧,在看這章以前,我徹底沒據說過「詞法做用域」這個概念,一開始我還覺得是個很高大上的東西,看完以後你會以爲其實也沒什麼,就是你平時都在寫的東西,只不過你沒有留意而已。數組
with
、try/catch
、let
、const
。這一章做者介紹了 JavaScript 中的函數做用域及塊做用域,講了函數聲明和函數表達式的區別,其實很簡單,就是看 function
這個關鍵字是不是在聲明中的第一個詞,若是是,那就是函數聲明,不然就是函數表達式。另外,做者還簡單地介紹了下 ES6 中具備塊做用域做用的 let
和 const
關鍵字。閉包
在這以前,我一直覺得 ES6 以前是沒有塊做用域的,只有全局做用域和函數做用域,看完這章以後,我才知道其實在 ES3 的時候就有塊做用域了。好比,with
。再好比,try/catch
中的 catch
,通常咱們是這樣寫的:app
try { // do something } catch (err) { console.log(err) }
其中這個 err
只存在 catch
分句內部,從別處引用時會拋出錯誤。這不就是塊做用域嗎?函數
這一章節做者簡單地介紹了一下變量聲明提高和函數聲明提高。沒什麼好說的,須要注意的是函數表達式是賦值操做,並不會提高。性能
閉包是 JavaScript 中的一大難點,在這章中做者用了 4 個小節來介紹閉包,還有 1 個小節來介紹模塊機制。不要看閉包有四個小節,其實也不過 8 頁而已,核心的文字加起來也就 2 頁,但就是這短短的 2 頁,就把閉包給講得很是清楚。this
下面是書中給出關於閉包的定義:
當函數能夠記住並訪問所在的詞法做用域時,就產生了閉包,即便函數是在當前詞法做用域以外執行。
看了是否是仍是不懂,不要緊,讓咱們來提取關鍵字:
再來看下書中的一段代碼,看完以後再結合書中的定義來理解,我相信你對閉包確定會有更進一步的理解。
function foo() { var a = 2; function bar() { console.log(a); } return bar; } var baz = foo(); baz(); // 2 —— 朋友,這就是閉包的效果。
下面結合咱們剛剛提取的關鍵字來理解。
bar()
;bar()
當前所在的詞法做用域是 foo()
的函數做用域。bar()
的詞法做用域可以訪問 foo()
的內部做用域。bar()
當作一個值類型傳遞給外部,在這句代碼中 var baz = foo();
,咱們將 foo()
的返回值(也就是 bar()
)賦值給變量 baz
並調用 baz()
,實際上就是調用 bar()
。上面第 2 點裏咱們說了,bar()
的做用域是 foo()
的函數做用域,可是,在這裏,它倒是在本身定義的詞法做用域之外的地方執行。怎麼樣,經過上面的分析,是否是對閉包有了進一步的理解了。
做者在這一章中簡單地分析了下動態做用域,並經過一小段代碼將它與詞法做用域作了對比。詞法做用域與動態做用域的主要區別在於:詞法做用域是在定義時肯定的,而動態做用域是在運行時肯定的。
這一章簡單地介紹了塊做用域的替代方案 Traceur,以及所以可能會帶來的性能問題。
這一章並無說明 this
機制 ,只是介紹了 ES6 中的箭頭函數引入的行爲 —— this
詞法。關於 this
機制的詳細說明是在第二部分《this 和對象原型》中的第 1 章和 第 2 章。
這一章做者致謝了一大堆的人,光人名的排版就佔了兩頁多,說真的,我都懷疑是否是在湊字數了(純調侃,沒別的意思)。
第二部分《this 和對象原型》
這一章中做者先是提出咱們「爲何要使用 this?」這個問題,而後再指出「this 究竟是什麼?」,爲第 2 章作鋪墊。
這一章我我的認爲最核心的就是兩句話。第一句是「當一個函數被調用時,會建立一個活動記錄(有時也稱爲執行上下文)。這個記錄會包含函數在哪裏被調用(調用棧)、函數的調用方式、傳入的參數等信息。this
就是這個記錄的一個屬性,會在函數執行的過程當中用到」。也就是說,this
是活動記錄裏的一個屬性,與函數執行的過程有關。
第二句話是「this 其實是函數被調用時發生的綁定,它指向什麼徹底取決於函數在哪裏被調用。」。第 2 章實際上就是在講這個綁定。
call()
、apply()
、bind()
;做者在這一章中全面介紹了 this
的綁定規則。
要弄清楚 this
的綁定對象,須要明白如下兩點:
什麼是調用位置?簡單來講,就是函數在代碼中被調用的位置。爲了找到調用位置,咱們須要分析調用棧,也就是爲了到達當前執行位置所調用的全部函數,而調用位置就在當前正在執行的函數的前一個調用中。
而綁定規則就是說 this
綁定的對象是有規則的,而且這些規則是有優先級的,總的來講有下面四點:
new
調用的,綁定到新建立的對象;call
、apply
、bind
調用的,綁定到指定的對象;undefined
,在非嚴格模式下綁定到全局對象。固然了,ES6 中新增的箭頭函數並不在這四條規則裏面,而是繼承外層第一個非箭頭函數調用的 this
綁定。
在看這一章以前,我對 this
只知其一;不知其二,網上找的答案也是五花八門,根本不知道哪一個對哪一個錯。在看完這一章以後,我算是對 this
的所綁定的對象有了較爲清晰的認識,之後再遇到相似的問題時,直接套用上面的規則就能夠了。
這一章講到了不少平時我並無注意到的東西,好比,通常來講,咱們使用數組的時候都是下標/值對,可是,給數組添加屬性竟然也是能夠,雖然這並不會改變數組的長度。當我看到這一部分的內容時內心在想:我去,這是什麼騷操做?這樣竟然也能夠?後面想了想,數組其實也是對象,是一個特殊的對象,從這一方面來講也是行得通的;再好比,屬性訪問與賦值時發生的 [[Get]] 操做與 [[Put]] 操做,可以更好地瞭解其工做原理;還有,咱們能夠利用 ES6 中的 Iterator 接口實現本身的迭代邏輯。
這一章講到了 「類」 這一設計模式,以及 JavaScript 中各類實現這一模式的方法。
這一章的核心就是:類的本質是複製,多態和繼承也是。這一點很重要,JavaScript 中也有類,可是二者的本質是不一樣的,這一點在《第 5 章 原型》和《第 6 章 行爲委託》裏面有詳細的說明。
這一章一開始看的時候我是很模糊的,由於做爲一名 JavaScript 開發者,說實話我對於 「類」 這個東西的理解不是很明白,因此我跳過了這一章,等到看完了後面三章以後再回過來看,瞬間感受清晰不少了。
這一章中,第一小節的 [[Prototype]] 屬性能夠和第 3 章中的 [[Put]] 操做結合一塊兒看,這樣可以完整的瞭解屬性賦值的工做原理;屬性設置和屏蔽這一部分能夠和第 4 章結合着閱讀,以便更好地瞭解 JavaScript 中的類與其它語言中的類的區別。
這一章做者主要從類理論與委託理論(其實也就是對象關聯)兩種不一樣的設計模式來介紹他們之間在代碼上實現的不一樣,能夠看作是第 4 章和第 5 章的對象關聯的實踐部分。
這一章做者分析了 ES6 中新增的 Class 語法的優勢與缺點。
全書感悟
以上就是本書中的一些主要內容介紹,我寫得比較簡單,其實書中還有不少比較細小的東西,有興趣的同窗能夠去買來看看。總的來講,這本書仍是挺不錯的,能讓你學到一些平時沒有注意到的東西,做者偏向於用口語化的文字來介紹知識點,不會顯得枯燥。
最後,拋塊磚,但願能引塊玉。下面是我在閱讀本書過程當中的作的思惟導圖。導圖的內容比較多,不是很簡潔,由於我但願儘可能把書中做者提到的概念提取出來,因此可能會顯得比較囉嗦。