8000 字讀完《JavaScript 語言精粹(修訂版)》

語言: CN / TW / HK

theme: channing-cyan

iShot2023-01-28 19.15.00.png

腦圖點選這裡獲取

視訊版點選此處播放

↑↑↑↑↑↑ 腦圖鎮樓 ↑↑↑↑↑↑

Hello,各位小夥伴大家好。

今天我們來為大家講一本書,就是這個《JavaScript 語言精粹修訂版》,作者是:道格拉斯·克羅克福德

image.png

我手裡的這本是《2017年10月第16次印刷版本》,距離現在已經有 5 年多了。但是這本書依然被奉為《講解 JavaScript 的一本神書》,特別適合 初級、中級 前端工程師進行閱讀。

但是大家要注意,雖然說這本書是 2017年 印刷的,但是書中提到的概念、定義並沒有 考慮 ES6 相關的東西,也就是說它是 純粹的、ES6 之前的 JavaScript 精華的講解

整本書中所有的內容,我把它分為 4 大塊:

  1. 前言部分
  2. 核心部分
  3. 其他部分
  4. 附錄部分

在講解完這四部分之後,我們會分析一下這本書在當下時間段針對國內開發者的優缺點,也就是最後的總結。

好,那麼廢話不多說,下面我們來看一下本書中的內容:

前言

在前言部分,作者提到了一個非常有意思的事情,那就是《為什麼一定要使用 JavaScript》,他說:因為你沒得選。

針對於 web瀏覽器而言,JavaScript 是唯一的程式語言,同時它也是世界上最被輕視的語言之一。

我們知道, JavaScript 是 布蘭登·艾克 花了 10 天的時間開發並且設計完成的,所以它內部必然包含了很多的優秀想法與糟糕的想法。

那麼都有什麼優秀的方法呢? 作者認為:

  1. 函式
  2. 弱型別
  3. 動態物件
  4. 物件字面量
  5. ...

這些東西,都可以被認為是優秀的想法,也就是 精華

但是同時,內部也有很多糟糕的想法,也就是 糟粕,比如:基於全域性變數的程式設計模型。

所以:JavaScript 是一個反差鮮明的語言,它的糟粕和精華一樣顯眼

而本書,將主要講解: JavaScript 的精華部分,至於 糟粕,將會在附錄部分進行說明。

核心

那麼下面我們就進入到本書的核心精華部分,整個精華部分被分為 6 塊,分別是:

  1. 語法
  2. 物件
  3. 函式
  4. 繼承
  5. 陣列
  6. 方法

那麼首先,咱們先來看語法部分。

語法:

整個語法部分涉及到的是整個 JavaScript 的基礎語法。

註釋

首先針對於註釋而言,作者提出 JavaScript 中的註釋主要分為兩種:

  1. 單行註釋
  2. 多行註釋

單行註釋是 兩個 / ,這個在日常開發中是比較常見的。

而針對於多行註釋來說,作者主要提供了一種,就是: 雙斜槓中間,放入兩個 ,這種多行註釋的形式,作者並 不推薦* 使用。

/* 多行註釋內容 */

但是大家要注意,在咱們現在的日常開發中,多行註釋,除了作者提到了這一種之外,其實還有另外一種,那就是:

/** * 多行註釋內容 /

這種註釋形式用在 函式上 還是非常指的推薦的。

識別符號

接下來是識別符號,所謂識別符號指的就是:JavaScript 中的保留字。

書中列舉出來了一分部,但是除此之外,還有一些其他的保留字大家需要注意。

這些保留字 不可以 被當做 變數名 使用。

數字

針對於很多程式語言來說,都提供了多種的數字型別。比如: java 就提供了 int、long、double、float 等 多種數字型別。

但是針對於 JavaScript 來說,它只有一種數字型別,就是 number,除此之外再無其他。

字串

而對於 JavaScript 中的字串型別而言,書中主要從兩個方面進行了描述:

  1. 首先是字面量:所謂字面量指的就是 快速建立某種型別的方式。對於字串來說,它有兩種字面量形式: 單引號和雙引號。在日常開發中,我們更推薦使用 單引號 的字面量形式。

  2. 第二個叫做特性:這裡的特性主要有三個:

    1. 首先第一個叫做 可拼接:多個字串是可以通過 + 的形式進行拼接的。
    2. 第二個叫做 可 length:咱們可以通過 字串.length 的形式,獲取字串的長度
    3. 第三個叫做 有方法:JavaScript 中的字串提供了非常多的方法,這個咱們把它放到 方法 這一大塊中再去說就可以。

語句

JavaScript 被稱作是一個圖靈完備的程式語言。所以它必然要具備 變數宣告、邏輯判斷 等語句。

JavaScript 中的語句可以寫在 <script> 標籤 中,每一對花括號中間就可以被叫做一組語句。

書中把 JavaScript 的語句分為 4 大塊:

  1. 首先是宣告語句:JavaScript 想要宣告變數主要有三種形式

    1. 第一種是 var :它是在 ES6 之前唯一的宣告變數的方式,現在已經不推薦使用了。
    2. 第二種是 let:在 ES6 之後可以通過它來定義變數
    3. 最後是 const:在 ES6 之後可以通過它來定義常量
  2. 其次是條件語句:JavaScript 中的條件語句主要有兩個

    1. 第一個是 if
    2. 第二個是 switch

    這兩種條件判斷形式,在很多的程式語言中都是存在的。但是 JavaScript 中判斷條件有些不太一樣的地方。

    JavaScript任何表示式 都可以被作為判斷條件,並且 有且僅有 6 個值 在條件判斷中會被作為 ,它們分別是: false、null、undefined、空字串、數字 0 、NaN。除此之外,其他的所有值都會被判斷為

  3. 再往後就是迴圈語句:JavaScript 中迴圈語句主要有三種

    1. 第一個是 for 迴圈
    2. 第二個是 while 迴圈
    3. 第三種是 do...while 迴圈

    同時,針對於 for 迴圈來說,又可以被分為: 普通 for 迴圈 和 forIn 迴圈

  4. 最後就是強制跳轉語句,所謂強制跳轉語句指的是: 會強制更改程式執行順序的語句,這些語句在日常開發中也是被經常使用的:

    1. 比如 break:它會讓程式 退出迴圈 || 退出 switch 語句
    2. continue:會讓程式 終止當前迴圈
    3. 然後是 renturn:它會終止函式的執行
    4. throw:會通過 丟擲異常的形式,終止程式執行
    5. try...catch:會通過 捕獲異常 的形式,讓程式強制跳轉到其他的邏輯中

表示式

說完語句之後,下面就是表示式。

作者對錶達式進行了明確的定義,指的是: 一組程式碼的集合,並且返回一個值

JavaScript 中的表示式 5 個,分別為:

  1. 算數表示式
  2. 字串表示式
  3. 邏輯值表示式
  4. 左值表示式
  5. 基本表示式

字面量(物件)

在前面咱們說到了 JavaScript 中存在字面量的概念。我們可以通過字面量的形式直接定義 字串

同時,字面量也有很多其他的使用場景,比如:可以使用字面量定義物件或陣列,而不需要像其他的語言一樣,必須先 new 一下。

函式

整個語法部分,最後一塊就是函式,但是在書中針對 語法部分函式 的講解比較粗糙,所以這一塊咱們放到後面單獨的函式模組進行說明。

物件

語法部分說完之後,接下來咱們來看下書中 物件 的部分。

物件在 JavaScript 中是一個非常特殊的概念。

定義

JavaScript 中資料型別主要被分為兩種:

  1. 簡單資料型別:有 number、string、boolean、null、undefined、symbol、bigint
  2. 除了簡單資料型別之外,其他的都被叫做 複雜資料型別,有: 陣列、函式、正則表示式、物件。 而 JavaScript 中,所有的複雜資料型別,都被統稱為 物件

字面量

物件有字面量的建立形式,這個在剛才已經有介紹了,所以這裡就不在多複述了。

檢索與更新

同時對於物件來說,它可以 獲取值(檢索) ,也可以 修改值(更新)

JavaScript 中提供了兩種檢索與更新的形式:

  1. 第一種是通過 . 語法:這種方式最為簡單易懂,是大多數情況下推薦使用的方式
  2. 第二種是通過 [] 語法[] 內部可以放一個變數,適用於 根據變數取值的情況

原型

同時 JavaScript 中提供了原型的概念,基於原型還延伸出了原型繼承的概念。

而對於物件的原型,咱們放到 繼承 這裡,再進行詳細說明。

反射

然後咱們來看 反射。可以很多小夥伴看到反射這個詞的時候,會比較懵。

其實在 JavaScript 裡面,沒有反射的明確定義。大家就把它作為是 作者的一個稱呼即可

反射這一塊裡面,主要包含了兩部分:

  1. 利用 typeof 獲取變數的型別
  2. 利用 hasOwnProperty 判斷 物件自身屬性中是否具有指定的屬性,具有則返回 true,否則則是 false

列舉

hasOwnProperty 這個方法在 “列舉” 的時候會非常有用。

和反射一樣,JavaScript 中同樣沒有列舉的明確概念。它一樣是作者的一個稱呼。

書中的列舉指的主要是: 遍歷一個物件並且獲取該物件自身的所有屬性

遍歷可以直接通過 forIn 迴圈執行,而判斷是否為物件自身屬性,則需要藉助 hasOwnProperty 方法

刪除

最後,針對於物件模組,作者還提到了 刪除 的概念。

我們可以利用 delete 關鍵字,直接刪除物件中的指定屬性。這也是很方便的。

函式

在物件說完之後,下面咱們就進入到了一個 大塊 了,那就是函式!

函式 這一章裡面,存在很多的 落後性描述的偏差,同時也有很多的 精華

具體是什麼,咱們往下看就知道了。

精華

在函式這一章的開篇,作者有一句話我非常喜歡,它描述了整個程式設計的本質,咱們一起來讀一下:所謂程式設計,就是將一組需求分解成一組函式與資料結構的技能

在這句話中,把函式的作用推到了一個非常重要的位置。

事實也同樣如此。

所以書中花費了非常大的章節來介紹函式,大家看腦圖也可以看的出來。

那麼下面,咱們就進入到函式的內容之中。

函式物件

咱們之前說過,在 JavaScript 中除了基本資料型別之外,其他的都是物件。

所以函式本質上也是一個物件。只不過它擁有一個叫做 “呼叫” 的屬性,可以被呼叫而已。

函式字面量

而如果想要定義函式,那麼可以通過 函式字面量 的形式來進行定義。

所謂的函式字面量,其實就是咱們平時定義函式的方式,一共分為兩種:

  1. 命名函式:function f (a, b) { ... }
  2. 匿名函式:const f = function (a, b) { ... }

呼叫

而在函式呼叫時,書中一共分為兩部分去說:

  1. 首先第一部分是 函式可以呼叫其他函式:這個只要大家使用過程式語言,那麼應該都很好理解。這種方式會 暫停當前函式執行,傳遞控制權和引數給新的函式

  2. 第二種是 附加引數:在 JavaScript 的函式中,存在兩個附加引數:

    1. 第一個是 this:它的值取決於呼叫的模式。書中把呼叫模式分成了 4 大類:

      1. 前三大類 方法呼叫、函式呼叫、構造器呼叫this 指向呼叫方
      2. 最後一大類 apply 呼叫 中, this 指向 指定值
    2. 第二個 arguments:它表示函式得到的所有實際引數

構造器模式

函式除了可以被直接 呼叫 之外,還可以被當做 構造器使用,也就是所謂的 構造器模式。

關於 構造器模式,書中主要明確了四個方面,分別是:

  1. JavaScript 是一門基於原型繼承的語言,這就意味著 物件可以直接從其他物件中繼承屬性。 關於繼承的話題,咱們在後面單獨說
  2. 第二個是: 構造器本身就是函式
  3. 第三就是: 構造器不通過小括號的形式直接呼叫,而是要 配合 new 關鍵字 使用
  4. 最後就是:根據 約定,構造器它的 首字母要大寫

這四塊是非常重要的,哪怕是在當下時間段依然是行之有效的。

apply 呼叫模式

在前面,咱們提到了 apply 呼叫模式,咱們知道所謂的 apply 呼叫模式 實際上是分為三個方法的,分別是:

  1. apply
  2. call
  3. bind

這三個方法的核心作用,就是 改變 this 指向

引數

引數 這個小節裡面,同樣書中主要提到的就是 arguments,這個咱們在前面也說過了,它主要是獲取 所有實際引數 的。

返回值

再往後,書中對 函式的返回值 進行了一些說明。

大家需要知道的,主要是有三點:

  1. 首先第一點: 函式必然存在返回值。如果你什麼都不返回,那麼函式預設返回 undefined
  2. 然後: 可以通過 renturn 讓函式提前返回指定的值,並且中止執行
  3. 第三:函式也可以配合 new 使用,這樣會返回 this

看到這大家有沒有發現,書中講過的很多東西,咱們在日常開發中大部分都是知道的。

但是書中把開發的一些 “經驗” ,變成了一套具體的 1、2、3 。

我在看的過程中,有時候確實會有一種: “哦~ 原來如此” 或者是 “嗯,確實是這樣” 的一種感覺

異常

那麼下面咱們繼續來往下看

書中專門在函式中,對異常進行了一個說明。

但是說明的重點依然是 throw 語句,丟擲異常。在丟擲異常的,它可以終止函式的執行。

擴充型別的功能

作者把基於原型繼承稱為: 擴充型別的功能

但是本質上還是 原型繼承,這個咱們依然還是在 繼承 模組中去說就可以。

遞迴

遞迴是函式呼叫非常常見並且複雜的場景。

書中也對 遞迴 進行了詳細說明,說明的方式是通過兩部分:

  1. 第一個就是什麼叫遞迴,所謂遞迴指的就是: 直接或間接呼叫自身的函式
  2. 接下來是遞迴的場景: 遞迴把一個複雜問題分解為一組相似的子問題,每一個都用一個尋常解去解決,這是典型的美式語言。同時作者還通過一個 漢諾塔遊戲 的案例,進行了舉例說明

作用域

接下來作者提到了作用域的概念。

但是這一塊,明顯具備非常大的侷限性,因為作者的很多觀念完全是基於 ES6 之前的邏輯去說的。

比如,作者提到: JavaScript 中不存在塊級作用域。

這個在當前場景下明顯是不對的。

所以我看的這本書,雖然是 2017 年 印刷的,但是內容感覺更加偏老一些。

閉包

接下來是閉包的邏輯。

這裡作者對閉包進行了定義: 內部函式可以訪問定義他們的外部函式的引數和變數 ,這樣的函式就是閉包。

我針對於這句話加上我個人的理解,也總結了一句: 可以訪問其它函式作用域中變數的函式 ,就是閉包。

大家可以看看哪個好理解,就理解哪一句就可以。

這裡我列舉了一段程式碼:

function a () {  const name = '張三'  return function b () {    return name } } ​ console.log(a()()) // 張三

在這段程式碼中, b函式 就是閉包函式

回撥

在往下是 回撥 的概念。

這裡其實主要就是說明了一點: 函式可以作為引數進行回撥使用

模組

結合 閉包回撥 ,作者提到了 模組 這樣的概念。

使用函式和閉包 時,可以構造一個模組。

那麼什麼是模組呢? 作者同樣給出了定義: 模組是一個提供介面卻隱藏狀態與實現的函式或物件

只看概念,非常難以理解,咱們通過這個程式碼來去看:

let name = '張三' // 此時 name 為全域性變數,可以被任意修改 function a () {  // 此時 name 為函式作用域變數  // 通過 const b = a() 得到 b 函式,然後進行呼叫  // name 不可以被外界修改  let name = '張三'  return function b () {    return name } }

通過這種模組的方式,來緩解 基於全域性變數的程式設計模式 所帶來的問題。

級聯

所謂 級聯,是作者的稱呼。

咱們更喜歡把它叫做 鏈式呼叫,明確了概念大家應該就知道是什麼了。

柯里化

作者專門講解了 柯里化,他對柯里化是這樣定義的,他說: 把函式與傳遞給它的引數相結合,產生一個新的函式。 這叫做柯里化。

這個定義和咱們的平常認知不同,在咱們的認知中,柯里化指的應該是: 柯里化是一種函式的轉換,它是指將一個函式從可呼叫的 f(a, b, c) 轉換為可呼叫的 f(a)(b)(c)

因為這本書原本是英文的,咱們拿到的都是 轉譯之後的譯本,所以關於一些定義,大家客觀看待就可以了。

記憶

整個函式最後一塊,提到了一個 記憶 的詞彙。

這個在咱們日常開發中不會這裡稱呼,這裡的記憶指的其實就是: 把函式的操作結果,儲存到一個物件中,從而避免重複運算

書中也拒了一些例子,但是本質上應該是一個類似演算法的概念。

總結

那麼到這裡,關於函式這一章咱們就說完了。

從函式這一章中,其實咱們就可以明確的感受出來: 書中的內容具備一定的落後性(比如:塊級作用域)譯文導致的一些描述的偏差(比如:柯里化) ,但是 其中也有很多的精華(比如:返回值、遞迴、閉包)

所以這本書,咱們再去看的時候,一定要客觀分析一下才可以。

繼承

那麼下面咱們來看 繼承 這個章節

這個章節的內容不算特別多,至少相比於 函式 是這樣的。

書中並沒有詳細的講解 JavaScript 中所有繼承的方式,以及程式碼。

更多的還是從理念的層次來去說的。同時 依然包含很多落後性

精華

首先本章一開始先明確了 JavaScript 的繼承方式: JavaScript 是弱型別的語言,提供了多種繼承的模式,而非傳統的類繼承

偽類

然後作者提到了 偽類 這樣的一個詞彙

這個偽類,說白了就是 建構函式,也就是: 首字母大寫的普通函式

物件說明符

這裡作者又提到了一個新的詞彙:物件說明符。

並且列舉出來了一個場景: 當一個函式接收多個引數時,記住引數的順序非常困難

比如:

maker(f, l, m, c, s)

所以,與其這麼寫,倒不如這樣寫:

maker({  first: f,  middle: m,  last: l,  state, s,  city: c })

簡單來說,也就是: 把多個引數,合併成一個用物件表示的引數

作者把這樣的一種方式叫做: 物件說明符

原型

原型是繼承中非常重要的概念。

但是因為書中的字數限制,作者並沒有對原型展開了詳細說,而只是明確了兩點:

  1. 首先第一點是基於原型繼承的概念: 一個新物件可以繼承一箇舊物件的屬性

  2. 第二個是差異化繼承:繼承本質上需要具備差異,通過一個小的 demo 進行了明確

    const person = {  name: '張三',  age: 18 } const newPerson = Object.create(person) newPerson.name = '李四'

    這樣,就完成了一個簡單的差異化繼承。

函式化

在講完了原型之後,作者提到了一個 函式化 的概念。

作者提出: 原型的繼承模式會導致沒有私有變數

如果大家使用過 ts 或者其他的 強型別程式語言(比如:java) 那麼可以就知道所謂私有變數是什麼意思了。

同時作者也通過一段程式碼來描述了 如何在原型繼承的模式下具備私有變數

這段程式碼比較複雜,也有點難以理解。但是在當下的場景中,因為 ES6 之後提出了 class 的概念,所以現在咱們其實是有了更簡單的方式定義私有變數的。

所以這段程式碼的意義就不大了。

部件

整個繼承最後一塊就是 部件

所謂部件指的就是: 物件(這裡是函式)的屬性或方法

每一個屬性或方法都可以被稱作是一個部件。

總結

整個繼承的章節,內容並不多。

書中也沒有大書特書的寫關於原型繼承的程式碼。

所以整個繼承章節看下來,不會很累,概念性的東西居多。

陣列

繼承講解完成之後,新的一個章節叫做 陣列

定義

這裡作者對於陣列的定義比較有意思,他拿傳統陣列和 JavaScript 陣列 進行了對比:

  1. 針對於傳統陣列來說:陣列是一段線性分配的記憶體,它通過整數計算偏移並訪問其中的元素

  2. 但是 JavaScript 中的陣列不同:

    1. 首先: JavaScript 中並不存在陣列一樣的資料結構
    2. JavaScript 只不過是提供了 類陣列特性的物件

    咱們之前說過 js 中除了基本資料型別,其他的都是物件,這裡就能夠呼應上了。

陣列字面量

這個比較簡單,就是通過 [] 定義陣列

長度

想要獲取陣列長度,通過 .length 屬性獲取

刪除

想要刪除陣列的元素,書中提到了兩種方式:

  1. 因為陣列本質上是物件,所以依然可以使用 delete 關鍵字刪除。但是這種刪除方式,會導致原來的位置留下 “空洞”
  2. 而第二種方式,是咱們比較常用的,那就是通過 splice 進行刪除

列舉

所謂的列舉,其實指的就是咱們常說的 遍歷

而陣列的遍歷常用的方式主要是兩種:

  1. forIn 迴圈,但是這樣無法保證順序
  2. 第二種是 普通的 for 迴圈,這也是咱們常用的方式

其實除了這兩種方式之外,大家應該還能想到別的,比如: forEach 方法。

容易混淆的地方

書中專門花了一個小節來去定義 陣列與物件 容易混淆的地方。

其中核心就是當使用 typeof 的時候,typeof 無法區分出 物件和陣列。

所以作者給出了一個方式來進行區分:

function is_array (value) {  return Object.prototype.toString.apply(value) === '[object Array]' }

這種方式放到現在依然可用。

除此之外,其實還有另外一種比較常用的方式,作者沒有提到,那就是 instanceof

方法

陣列中提供了一些被繼承的方法,這些方法,咱們放到 方法 這一章去說就可以了。

指定初始值

書中關於陣列的最後一個小節講解了 陣列初始值 相關的一些東西,主要是有兩點:

  1. 第一點就是: 陣列沒有預設值。通過 [] 定義陣列後,會是一個空陣列(本來難道不應該是這樣嗎?)
  2. 第二點就是:JavaScript 中本質上沒有多維陣列的概念,所謂的多維陣列不過是 以陣列為元素 產生的

總結

整個陣列的環節,內容還是比較簡單的。

相當於把 JavaScript 中陣列的一些核心特性進行了講解。

方法

再往後就是書中核心部分的最後一塊了,也就是 方法

書中對於方法的講解主要是通過兩部分:

  1. 第一部分是對方法進行了定義,所謂方法指的是:當一個函式被儲存為物件的一個屬性時,那麼這個函式就被叫做是方法。

  2. 第二部分類似於一個 API 文件。詳細的介紹了:

    1. Array
    2. Function
    3. Object
    4. Srting

    這四大類的一些原型繼承方法。

這些方法,在 MDN 文件中都可以直接檢視,咱們這裡就不去詳細說了。

核心部分總結

核心部分講解完成之後,其實書中絕大部分 精華 咱們就已經全部梳理完成了。

其他

除了大部分的精華之外,書中還提到了一些 其他 的東西,比如:

  1. 正則表示式
  2. 程式碼風格
  3. 優美的特性

咱們一個一個去說。

正則表示式

首先針對於正則表示式來說。

因為本書並不是一個專門講解正則表示式的書籍,所以書中關於正則的內容並不多。很多地方也並不詳細。

所以我並不是很推薦大家去看本書中關於正則的部分。

如果大家想要了解正則,倒不如到 MDN 文件 中進行檢視。

程式碼風格和優美的特性

針對於 程式碼風格和優美的特性 這兩塊,因為 作者對 JavaScript 語法規範的理解,但並不完全適合於國內環境,所以這兩部分對於咱們的參考意義也不是很大。

但是這裡有一句話寫的很好,我摘抄了下來,咱們可以一起看一下

我們喜歡簡單,追求簡潔易用,但是當產品缺乏這種特性時,就需要自己去創造它。

附錄

最後就是整本書的 附錄 部分。

這部分主要是分成了 5 塊。

其中前兩塊:

  1. 毒瘤
  2. 糟粕

比較有意思,咱們可以一起來看一下。

至於後三塊:

  1. JSLint
  2. 語法圖
  3. JSON

不在咱們本次的探討範圍之內。

毒瘤

作者把 JavaScript 中非常差勁的特性叫做 毒瘤。意思是: 不除不快

這裡面涉及到的語法非常的多,咱們簡單過一下即可:

  1. 全域性變數:中大型專案中,全域性變數可以被任意修改,會使得程式的行為變得極度複雜
  2. 作用域:無塊級作用域
  3. 自動插入分號:不合時宜的自動插入
  4. 保留字:大量的保留字不可以被用作變數名
  5. unicodeunicode 把一對字元視為一個單一的字元,而JavaScript認為一對字元是兩個不同的字元
  6. typeoftypeof 的返回總是很 “奇怪”
  7. parseInt:遇到非數字時會停止解析,而不是丟擲一個錯誤
  8. +:既可以讓數字相加,也可以連結字串
  9. 浮點數:二進位制的浮點數不能正確的處理十進位制的小數
  10. NaNNaN 表示不是一個數字,同時它的一些運算也會讓人感到奇怪
  11. 偽陣列:JavaScript 中沒有真正的陣列,卻又存在偽陣列的概念
  12. 假值:0、NaN、''、false、null、undefined 在邏輯判斷中都會被認為假
  13. hasOwnPropertyhasOwnProperty 是一個方法而不是運算子,所以在任何物件中,他可以被替換掉
  14. 物件:JavaScript 中的物件永遠不會是真的空物件,因為它們可以從原型鏈中取得成員屬性

糟粕

作者把一些不符合規範,但是可以使用的程式碼,叫做 糟粕

主要有:

  1. ==:不判斷型別,所以儘量不要使用它
  2. with:改變一段語句的作用域鏈
  3. eval:傳遞字串給 JavaScript 編譯器,會使得程式碼更加難以閱讀
  4. continue:作者發現移除 continue 之後,效能會得到改善
  5. switch 穿越:必須明確中斷 case,否則會穿越到下一個
  6. 缺少塊的語句
  7. ++ --:這兩個運算子鼓勵了一種不夠謹慎的程式設計風格
  8. 位運算子:JavaScript 執行環境一般不接觸硬體,所以執行非常慢
  9. function 語句對比 function 表示式:多種定義方式讓人困惑
  10. 型別的包裝物件:你應該從來沒有使用過 new Boolean(false)。所以作者認為:這是完全沒有必要,並且令人困惑的語法

總結

OK,那麼到這裡整本書中所有的內容,咱們就已經全部講解完了。

針對於《JavaScript 語言精粹修訂版》來說,它的優點是非常明確的:

  1. 體量小
  2. 初、中級工程師可以通過它快速理清 JavaScript 語言精粹

但是它的缺點也是非常突出:

  1. 內容偏老,針對 ES6 之前的語法
  2. 內容多為直譯,導致有時候一定定義和詞彙可能會讓人很困惑
  3. 書中包含大量的作者主觀表述,可能並不一定那麼精準,大家需要客觀看待。(比如: vue 中就大量的使用到了“糟粕”