摘要:最近剛剛看完了你不知道的上卷,對有了更進一步的了解。你不知道的上卷由兩部分組成,第一部分是作用域和閉包,第二部分是和對象原型。附錄詞法這一章并沒有說明機制,只是介紹了中的箭頭函數引入的行為詞法。第章混合對象類類理論類的機制類的繼承混入。
最近剛剛看完了《你不知道的 JavaScript》上卷,對 JavaScript 有了更進一步的了解。
《你不知道的 JavaScript》上卷由兩部分組成,第一部分是《作用域和閉包》,第二部分是《this 和對象原型》。下面我會按照簡單介紹一下每一章的主要內容及閱讀感受。
第一部分《作用域和閉包》
第 1 章 作用域是什么編譯原理:簡單介紹分詞/詞法分析、解析/語法分析、代碼生成的概念;
理解作用域:介紹引擎、編譯器、作用域之間的關系;
作用域嵌套。
在這一章節中,作者通過引擎、編譯器、作用域之間的對話,將這三者之間的關系及作用生動形象地展現出來,并引出了 LHS 查詢和 RHS 查詢的概念。
第 2 章 詞法作用域詞法作用域及其相關概念;
欺騙詞法的方式:
在代碼運行時修改詞法作用域,如 eval();
在代碼運行時創建新的詞法作用域,如 with。
這一章作者介紹了詞法作用域以及欺騙詞法的方式。說來慚愧,在看這章之前,我完全沒聽說過「詞法作用域」這個概念,一開始我還以為是個很高大上的東西,看完之后你會覺得其實也沒什么,就是你平時都在寫的東西,只不過你沒有留意而已。
第 3 章 函數作用域和塊作用域函數作用域:函數聲明和函數表達式的區別、具名函數和匿名函數;
塊作用域:with、try/catch、let、const。
這一章作者介紹了 JavaScript 中的函數作用域及塊作用域,講了函數聲明和函數表達式的區別,其實很簡單,就是看 function 這個關鍵字是否是在聲明中的第一個詞,如果是,那就是函數聲明,否則就是函數表達式。另外,作者還簡單地介紹了下 ES6 中具有塊作用域作用的 let 和 const 關鍵字。
在這之前,我一直以為 ES6 之前是沒有塊作用域的,只有全局作用域和函數作用域,看完這章之后,我才知道其實在 ES3 的時候就有塊作用域了。比如,with 。再比如,try/catch 中的 catch,一般我們是這樣寫的:
try { // do something } catch (err) { console.log(err) }
其中這個 err 只存在 catch 分句內部,從別處引用時會拋出錯誤。這不就是塊作用域嗎?
第 4 章 提升這一章節作者簡單地介紹了一下變量聲明提升和函數聲明提升。沒什么好說的,需要注意的是函數表達式是賦值操作,并不會提升。
第 5 章 作用域閉包閉包;
作用域和閉包;
模塊機制。
閉包是 JavaScript 中的一大難點,在這章中作者用了 4 個小節來介紹閉包,還有 1 個小節來介紹模塊機制。不要看閉包有四個小節,其實也不過 8 頁而已,核心的文字加起來也就 2 頁,但就是這短短的 2 頁,就把閉包給講得非常清楚。
下面是書中給出關于閉包的定義:
當函數可以記住并訪問所在的詞法作用域時,就產生了閉包,即使函數是在當前詞法作用域之外執行。
看了是不是還是不懂,沒關系,讓我們來提取關鍵字:
函數;
記住并訪問所在的詞法作用域;
當前詞法作用域之外執行。
再來看下書中的一段代碼,看完之后再結合書中的定義來理解,我相信你對閉包肯定會有更進一步的理解。
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() 的函數作用域,但是,在這里,它卻是在自己定義的詞法作用域以外的地方執行。
怎么樣,通過上面的分析,是不是對閉包有了進一步的理解了。
附錄 A 動態作用域作者在這一章中簡單地分析了下動態作用域,并通過一小段代碼將它與詞法作用域做了對比。詞法作用域與動態作用域的主要區別在于:詞法作用域是在定義時確定的,而動態作用域是在運行時確定的。
附錄 B 塊作用域的替代方案這一章簡單地介紹了塊作用域的替代方案 Traceur,以及因此可能會帶來的性能問題。
附錄 C this 詞法這一章并沒有說明 this 機制 ,只是介紹了 ES6 中的箭頭函數引入的行為 —— this 詞法。關于 this 機制的詳細說明是在第二部分《this 和對象原型》中的第 1 章和 第 2 章。
附錄 D 致謝這一章作者致謝了一大堆的人,光人名的排版就占了兩頁多,說真的,我都懷疑是不是在湊字數了(純調侃,沒別的意思)。
第二部分《this 和對象原型》
第 1 章 關于 thisthis 的指向;
this 的作用域。
這一章中作者先是提出我們「為什么要使用 this?」這個問題,然后再指出「this 到底是什么?」,為第 2 章做鋪墊。
這一章我個人認為最核心的就是兩句話。第一句是「當一個函數被調用時,會創建一個活動記錄(有時也稱為執行上下文)。這個記錄會包含函數在哪里被調用(調用棧)、函數的調用方式、傳入的參數等信息。this 就是這個記錄的一個屬性,會在函數執行的過程中用到」。也就是說,this 是活動記錄里的一個屬性,與函數執行的過程有關。
第二句話是「this 實際上是函數被調用時發生的綁定,它指向什么完全取決于函數在哪里被調用?!?。第 2 章實際上就是在講這個綁定。
第 2 章 this 全面解析調用位置;
綁定規則:
默認綁定;
隱式綁定;
顯式綁定:call()、apply()、bind();
new 綁定;
箭頭函數的綁定;
一些例外的綁定。
綁定規則的優先級。
作者在這一章中全面介紹了 this 的綁定規則。
要弄清楚 this 的綁定對象,需要明白以下兩點:
調用位置
綁定規則
什么是調用位置?簡單來說,就是函數在代碼中被調用的位置。為了找到調用位置,我們需要分析調用棧,也就是為了到達當前執行位置所調用的所有函數,而調用位置就在當前正在執行的函數的前一個調用中。
而綁定規則就是說 this 綁定的對象是有規則的,并且這些規則是有優先級的,總的來說有下面四點:
由 new 調用的,綁定到新創建的對象;
由 call、apply、bind 調用的,綁定到指定的對象;
由上下文對象調用的,綁定到該上下文對象;
默認的,在嚴格模式下綁定到 undefined,在非嚴格模式下綁定到全局對象。
當然了,ES6 中新增的箭頭函數并不在這四條規則里面,而是繼承外層第一個非箭頭函數調用的 this 綁定。
在看這一章之前,我對 this 一知半解,網上找的答案也是五花八門,根本不知道哪個對哪個錯。在看完這一章之后,我算是對 this 的所綁定的對象有了較為清晰的認識,以后再遇到類似的問題時,直接套用上面的規則就可以了。
第 3 章 對象JavaScript 中的數據類型;
內置對象;
對象屬性與方法;
數組;
對象復制;
屬性描述符;
[[Get]] 操作與 [[Put]] 操作;
Getter 和 Setter;
遍歷及 ES6 中的 Symbol.iterator。
這一章講到了很多平時我并沒有注意到的東西,比如,一般來說,我們使用數組的時候都是下標/值對,但是,給數組添加屬性居然也是可以,雖然這并不會改變數組的長度。當我看到這一部分的內容時心里在想:我去,這是什么騷操作?這樣居然也可以?后面想了想,數組其實也是對象,是一個特殊的對象,從這一方面來說也是行得通的;再比如,屬性訪問與賦值時發生的 [[Get]] 操作與 [[Put]] 操作,能夠更好地了解其工作原理;還有,我們可以利用 ES6 中的 Iterator 接口實現自己的迭代邏輯。
第 4 章 混合對象 “類”類理論;
類的機制;
類的繼承;
混入。
這一章講到了 “類” 這一設計模式,以及 JavaScript 中各種實現這一模式的方法。
這一章的核心就是:類的本質是復制,多態和繼承也是。這一點很重要,JavaScript 中也有類,但是兩者的本質是不同的,這一點在《第 5 章 原型》和《第 6 章 行為委托》里面有詳細的說明。
這一章一開始看的時候我是很模糊的,因為作為一名 JavaScript 開發者,說實話我對于 “類” 這個東西的理解不是很明白,所以我跳過了這一章,等到看完了后面三章之后再回過來看,瞬間感覺清晰很多了。
第 5 章 原型[[Prototype]] 屬性;
屬性設置和屏蔽;
JavaScript 中的 “類”;
(原型)繼承;
對象關聯。
這一章中,第一小節的 [[Prototype]] 屬性可以和第 3 章中的 [[Put]] 操作結合一起看,這樣能夠完整的了解屬性賦值的工作原理;屬性設置和屏蔽這一部分可以和第 4 章結合著閱讀,以便更好地了解 JavaScript 中的類與其它語言中的類的區別。
第 6 章 行為委托這一章作者主要從類理論與委托理論(其實也就是對象關聯)兩種不同的設計模式來介紹他們之間在代碼上實現的不同,可以看做是第 4 章和第 5 章的對象關聯的實踐部分。
附錄 A ES6 中的 Class這一章作者分析了 ES6 中新增的 Class 語法的優點與缺點。
全書感悟
以上就是本書中的一些主要內容介紹,我寫得比較簡單,其實書中還有很多比較細小的東西,有興趣的同學可以去買來看看。總的來說,這本書還是挺不錯的,能讓你學到一些平時沒有注意到的東西,作者偏向于用口語化的文字來介紹知識點,不會顯得枯燥。
最后,拋塊磚,希望能引塊玉。下面是我在閱讀本書過程中的做的思維導圖。導圖的內容比較多,不是很簡潔,因為我希望盡量把書中作者提到的概念提取出來,所以可能會顯得比較啰嗦。
最后,歡迎關注我的微信公眾號:前端路漫慢。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/108382.html
摘要:前言有過面試經驗的同學應該都被問過瀏覽器兼容性的問題,對于面試官的問題,常常猝不及防,因為通常他們都是這么問的。來談談瀏覽器兼容的問題吧,你對瀏覽器的兼容性有了解過嗎,那么如何才是我們正確回答這個問題的姿勢呢。 前言 有過面試經驗的同學應該都被問過瀏覽器兼容性的問題,對于面試官的問題,常常猝不及防,因為通常他們都是這么問的。來談談瀏覽器兼容的問題吧,你對瀏覽器的兼容性有了解過嗎,那么如...
摘要:前言有過面試經驗的同學應該都被問過瀏覽器兼容性的問題,對于面試官的問題,常常猝不及防,因為通常他們都是這么問的。來談談瀏覽器兼容的問題吧,你對瀏覽器的兼容性有了解過嗎,那么如何才是我們正確回答這個問題的姿勢呢。 前言 有過面試經驗的同學應該都被問過瀏覽器兼容性的問題,對于面試官的問題,常常猝不及防,因為通常他們都是這么問的。來談談瀏覽器兼容的問題吧,你對瀏覽器的兼容性有了解過嗎,那么如...
摘要:如果提升改變了代碼執行的順序,會造成非常嚴重的破壞。聲明本身會被提升,而包括函數表達式的賦值在內的賦值操作并不會提升。要注意避免重復聲明,特別是當普通的聲明和函數聲明混合在一起的時候,否則會引起很多危險的問題 你不知道的JS(上卷)筆記 你不知道的 JavaScript JavaScript 既是一門充滿吸引力、簡單易用的語言,又是一門具有許多復雜微妙技術的語言,即使是經驗豐富的 Ja...
摘要:的分句會創建一個塊作用域,其聲明的變量僅在中有效。而閉包的神奇作用是阻止此事發生。依然持有對該作用域的引用,而這個引用就叫做閉包。當然,無論使用何種方式對函數類型的值進行傳遞,當函數在別處被調用時都可以觀察到閉包。 date: 16.12.8 Thursday 第一章 作用域是什么 LHS:賦值操作的目標是誰? 比如: a = 2; RHS:誰是賦值操作的源頭? 比如: conso...
摘要:遮蔽效應作用域查找會在找到第一個匹配的標識符時停止,不會繼續往上層作用域查找,這就會產生遮蔽效應。會發現每一次輸出的都是為啥勒所有的回調函數回在循環結束后才會執行事件循環。 三劍客 編譯,顧名思義,就是源代碼執行前會經歷的過程,分三個步驟, 分詞/詞法分析,將我們寫的代碼字符串分解成多個詞法單元 解析/語法分析,將詞法單元集合生成抽象語法樹(AST) 代碼生成,抽象語法樹(AST)轉...
閱讀 2453·2021-11-23 09:51
閱讀 503·2019-08-30 13:59
閱讀 1820·2019-08-29 11:20
閱讀 2529·2019-08-26 13:41
閱讀 3238·2019-08-26 12:16
閱讀 729·2019-08-26 10:59
閱讀 3321·2019-08-26 10:14
閱讀 602·2019-08-23 17:21