iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 8
0
Modern Web

跟著 YDKJS 作者 Kyle Simpson 打造全新 JavaScript Mindset系列 第 8

[day07] YDKJS (Type/Coercion) : 來讀 Abstract Operations Spec. : ToPrimitive()

  • 分享至 

  • xImage
  •  

Type 總結

如果你是 Java 的使用者,你會很熟悉,但是建議你不要使用在 Primitive types ,
對於 Primitive types 可以直接用 var str = String(somethings)
下列是比較常用的方法:

前面 day05 文章 的例子有提到會有型別判定問題,後續也會提到有 Coercion (強制轉型)問題。

  • Day05:
    Reference code : MDN
    typeof new Boolean(true) === 'object'; // 這樣會令人混淆。不要這樣用!
    typeof new Number(1) === 'object'; // 這樣會令人混淆。不要這樣用!
    typeof new String("abc") === 'object';  // 這樣會令人混淆。不要這樣用!

    typeof Boolean(true) === 'boolean'; // 但是不要使用這種方式!
    typeof Number(1) === 'number'; // 但是不要使用這種方式!
    typeof String("abc") === 'string'; // 但是不要使用這種方式!


    // 對於 Array
    typeof [1, 2, 4] === 'object'; // 建議使用 Array.isArray 

You-Dont-Know-JS 複習

JavaScript 有七種內建(built-in) 型別:nullundefinedbooleannumberstringobjectsymbol。它們可以被 typeof 運算子識別。

變數沒有型別,但是值有型別。這些型別定義了值的固有行為。

許多開發者會認為“undefined”和“undeclared”大體上是同一個東西,但是在 JavaScript 中,它們是十分不同的。
undefined 是一個可以由被宣告的變數持有的值。undeclared 意味著一個變數從來沒有被宣告過。

JavaScript 很不幸地將這兩個詞在某種程度上混為了一談,不僅體現在它的錯誤訊息上(“ReferenceError: a is not defined”),也體現在 typeof 的回傳值上:對於兩者它都回傳 "undefined"。
JavaScript 內顯示都是 undefined,但你要知道其兩者意義不一樣。

然而,當對一個未宣告的變數使用 typeof 時,typeof 上的安全防衛機制(防止一個錯誤)可以在特定的情況下非常有用(至少你程式不會直接因為錯誤死掉不能執行,不情願地感謝 JavaScript 自作聰明)。

這邊沒有對於 Value 多著墨,可以參照 You-Dont-Know-JS/types-grammar/ch1.md

簡體翻譯 + 新同文堂(這是我的 gist 連結,是設定檔,可以直接匯入)


Coercion

中文有人用:型別轉換、強制轉型

abstract operations

翻譯用舊版(ES5.1 中文版)的,新版懶得翻 XD

ECMAScript 執行時系統會在需要時從事自動型別轉換。為了闡明某些結構的語義,定義一集轉換運算子是很有用的。
這些運算子不是語言的一部分;在這裡定義它們是為了協助語言語義的規範。轉換運算子是多型的 — 它們可以接受任何 ECMAScript 語言型別 的值,但是不接受 規範型別 。

為了方便其使用本規範的多個部分,叫做 抽象操作 (abstract operations) 的一些演算法編寫成帶名稱的可傳參函式化形式,所以在其他演算法裡可以透過名稱引用它們。

所以說 abstract operations 不是 JavaScript 的東西,它們不像一個可以某種方式呼叫的函式,只是 spec文件 用這種形式來描述比較容易。

因此,每當你有一些不是 Primitive 的東西並且它需要成為一個 Primitive 的概念時,
我們需要做的是這組 演算法,這就是所謂的 ToPrimitive

好像它是一個可以被呼叫的函式(但不是函式,是演算法),因此ToPrimitive 是一種 abstract operations,並且標註 type 'hint'。

  • spec 中的演算法,它們本身就是遞回的,如果有一組 non-primitive , 它執行 ToPrimitive() 之後仍然不是 Primitive , 它會繼續執行 ToPrimitive() 操作直到 Primitive 或是 Error 為止。

ToPrimitive 7.1.1

ToPrimitive 運算子接受一個值,和一個可選的 期望型別(PreferredType) 作引數。
ToPrimitive 運算子把其值引數轉換為非物件型別。
如果物件有能力被轉換為不止一種原語型別,可以使用可選的 期望型別 來暗示那個型別。

這邊特別抓 spec 講,後面就部分省略不貼,直接點連結就好。

Note 有說, default 多數狀態下是 number。遇到 object 會有例外。


ToPrimitive 抽象運算子中,有兩個方法:

  1. toString()
  2. valueOf()

不過,我們可以直接把內容轉化成:

  1. 期望型別(hint) 對象是 "number"

如果預期對象是 "number" ,先用 valueOf() 嘗試轉換成 "number" ,
如果不能用 valueOf() ,再嘗試用 toString(),如果兩種都失敗,就以 error 結束。

  1. 期望型別(hint) 對象是 "string"

如果預期對象是 "string" ,先用 toString() 嘗試轉換成 "number" ,
如果不能用 toString() ,再嘗試用 valueOf(),如果兩種都失敗,就以 error 結束。

  • 期望型別 這邊使用 hint 來表示。

上一篇
[day06] YDKJS (Type) : 特殊值:undefined / undeclared / TDZ ? , NaN , 負數 0
下一篇
[day08] YDKJS (Coercion:spec) : 來讀 Spec.  ToString(), ToNumber() , ToBoolean()
系列文
跟著 YDKJS 作者 Kyle Simpson 打造全新 JavaScript Mindset31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言