iT邦幫忙

2022 iThome 鐵人賽

DAY 5
1
Modern Web

咩色用得好,歸剛沒煩惱 - 從 ECMAScript 偷窺 JavaScript Array method系列 第 5

Day 5 咩色用得好 - 我要如何看得懂 ECMAScript ?(part -2)

  • 分享至 

  • xImage
  •  

Prelude

我是阿傑,我們在 Day 4 介紹了 ECMAScript 中的 Abstraction Operations、List、Internal Methods、Internal Slots 等 4 個名詞,今天繼續聊聊以下另外 4 個:

  • Record
  • Completion Record
  • ReturnIfAbrupt
  • ReturnIfAburpt Shorthand - ? & !

放心,這 4 個講完就結束了,真的...

甘安捏


Record

Record 是 ECMAScript 內部的一種規範類型 (specification type),它看起來就像 JavaScript 的物件,但又不是...

聽聽看你在講什麼

為什麼這麼說?因為它少了很多 JavaScript 物件該有的特性 (例如原型鏈)!我們可以試著把它抽象化一些,應該就會比較好理解 - 可以把 Record 想像成是一個純粹的資料集合體 (aggregation),就這樣,沒有其他特別的!而這個集合體的每筆資料都是一個 name field , 以一對 key-value 的形式呈現,會像這樣:

{ [[Fild1]]:42, [[Field2]]: false, [[Field3]]: empty }

上面便定義了一筆有 3 個 field 的 Record,這些 field 是無序的,因為它並不是靠索引來取值的,而它也沒有像 JavaScript 物件那樣有原型鏈的繼承關係,它只是單純地列出了擁有哪些 field,換句話說,就是一個簡單的資料集合。

除了 JavaScript 用物件的形式來實現 Record, 常見的還有資料表 (data table) 的呈現方式,例如下面這張表格 (圖 5.1):

5.1

Note:
這種 [[ ]] 雙括號的表示法不是 Record field 的專利,在 ECMAScript 中,Internal MethodInternal Slot 也是使用此種寫法


Completion Record

Completion Record 是 ECMAScript 專用的規範類型,它是一種特殊的 Record,它可以用來解釋在運行期間 (runtime) ,值的傳遞及流程控制 (control flow)的轉移,可以看作是流程執行到特定步驟的一個運行結果;換句話說,就是在規範中的每個步驟執行完都會明確地或隱性地回傳一個結果 - Completion Record。

Completion Record 包含 3 個 field,如下圖所示 (圖 5.1):

5.2

  • [[Type]] - 即當下產生的 Completion Record 類型, 它的值為 normal、break、continue、retrun 跟 throw 5 選 1,但我們目前專注在 normal 跟 throw 即可。
  • [[Value]] - 當下產生的值會被記錄在這裡,可以是除了 Competion Record 以外的任何值 - 我們主要會看到正常生成的值、拋出異常的值或者為空。
  • [[Target]] - 表示控制流程要轉移到的目標,這邊可以先暫時略過。

當 Completion Record 的 [[Type]] 為 normal 時,代表它是一個 normal completion,否則,一律是一個 abrupt completion

要讀取一個 Completion Record 的值,前提它必須是一個 normal completion,不能是一個 abrupt completion。

這邊必須記住一件非常重要的事 - 就是一個可被呼叫的物件 (callable object) 永遠只會回傳 normal completion 或 throw completion 這兩者之一,這也是為什麼我們目前只需專注在它們兩個身上即可。

我們先來看一下它常出沒的地方 - 一個 abstrac opertaion 裡 (圖 5.3):

5.3

這個 ToObject abstract operation 明確地告訴你它會回傳一個包含 Object 的 normal completion 或一個異常的 throw completion。

為什麼要定義這個東西啊,是不是搞得太複雜了???這點我也很疑惑,直到我看到了 ECMAScript 閱讀指南How to Read the ECMAScript 的解釋,才總算有點理解,他們都不約而同的提到了一個東西 - try-catch block

沒錯,ECMASript 裡並沒有 try-catch block 的存在,所以我們必須明確地處理每個可能出現的異常,也就是讓 [[Value]] 也同時擁有攜帶異常的能力;因為規範中使用了非常多的邏輯調用,如果沒有專門來處理異常的機制,那將會變得非常可怕,有興趣了解可以看看這兩篇文章的解釋!


ReturnIfAbrupt

ECMAScript 裡使用了大量的 Abstract Operation,目的是讓整份規範看起來更乾淨!

當 Abstract Operation 執行完畢會回傳一個 Completion Record,如果這個 Completion Record 是一個 normal completion 就直接將它的 [[Value]] 取出,如果是一個 abrupt completion,便直接回傳這個 completion。

ReturnIfAbrupt 的出現就是要簡化上述的這一系列步驟 (圖 5.4):

5.4

而且因為 Abstact Opertaion 是一個 callable 的物件,所以它只會回傳 normal completion 或 throw completion。

這也就表示,ReturnIfAbrupt(AbstractOperation()) 的結果會是一個從 completion record 取出的值,不然就會回傳一個 throw completion。

如果你有稍微翻閱過 ECMAScript ,你會發現 ReturnIfAbrupt 出現的頻率其實很低,取而代之的是一套更精簡的寫法 - ?!


ReturnIfAbrupt Shorthand - ? & !

我們可以將 ReturnIfAbrupt(OperationName) 直接簡寫成 ? OperationName(),也就是在 abstract operation 前面加上 ? 這個前綴,我們先來看看它出現在規範裡的樣子:

5.5

上面這個 ? ToObject(this value) 最終可能會成為一個值或回傳一個 throw completion,也就表示這個 O 如果沒有拿到一個值,就會出現了一個異常情況 (exception)。

那有沒有操作是不會丟出異常的?答案是肯定的,所以也就有了 ! 的出現,它代表這個操作永遠不會回傳 abrupt completion,我們來看看它出現在規範的哪 (圖 5.6):

5.6

上面這個 ! ToString(F(k)) 一定會是一個從 normal completion 的 [[Value]] field 取出來的值,永遠不會回傳 throw completion,但如果你點進這個 ToString(F(k))
abstract operation 觀看,你會發現它是有機會 throw exception 的,那為什麼這邊又使用了 ! 呢?我想答案會在它的參數 F(k) 上。


Conclusion

我的老天鵝,辛苦大家看到這邊了...

從來沒有這麼累過

大家如果還是很迷惑也不要擔心,我們接下來會直接從 Array method 來看 ECMAScript 怎麼寫,屆時就會看到想吐了,一定會熟悉的,沒事兒沒事兒!

希望大家可以開心地使用各種咩色,體驗它帶給你的便利,祝大家歸剛沒煩惱。


參考資源


上一篇
Day 4 咩色用得好 - 我要如何看得懂 ECMAScript ?(part -1)
下一篇
Day 6 咩色用得好 - Array.prototype.find
系列文
咩色用得好,歸剛沒煩惱 - 從 ECMAScript 偷窺 JavaScript Array method30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
安揪拉
iT邦新手 4 級 ‧ 2022-09-21 15:28:41

我為什麼跪著讀(part-2)

我要留言

立即登入留言