實務上應避免使用 Constructor Function 建立 Primitive Type

我們知道 string 雖然是 Primitive Type,但也可藉由 Constructor Function 建立,但建立之後為 object,與原本的 string 型別並不相同。

這與主流語言如 C# 的觀念並不一樣。

Version


ECMAScript 5
ECMAScript 2015
C# 7.2

CSharp


1
2
3
4
var s1 = new String("abc");
var s2 = "abc";

Console.WriteLine(s1 == s2);

s1String Constructor 建立;而 s2 為直接指定為 string。

wrapper000

  1. 結果為 true

ECMAScript


1
2
3
4
var s1 = new String("abc");
var s2 = "abc";

console.log(s1 === s2);

s1String Constructor Function 建立;而 s2 為直接指定為 String Literal。

wrapper001

  1. 出現驚人的結果,C# 為 true,但 ECMAScript 為 false

Why ?

平心而論,C# 的 true 比較符合一般語言的預期,但為什麼 ECMAScript 為 false 呢 ?

wrapper002

  1. s1object,也就是所謂的 Wrapper Object,而 s2string,也就是 s1s2 從型別已經不同了,因此使用 === 比對一定會錯
  2. s2 隨然為 object,但原來 string 的值依然存在內部,有 index 也有 length,也就是所謂的 Array-like Object,注意其 prototype 仍然是 String

wrapper003

  1. 若要讓 Wrapper Object 與 Primitive Type 的 string 比對為 true,只要使用 valueOf() 取出即可

Conclusion


  • C# 使用 String Constructor 建立時,其型別是 string;但 ECMAScript 由 String Constructor Function 建立時,其型別是 object,也就是所謂的 Wrapper Object,因此與 Primitive 的 string 型別不同,因此 ===false
  • Wrapper Object 可靠 valueOf() 取出內部的 primitive
  • 實務上應避免使用 Constructor Function 建立 Primitive Type

Reference


Dr. Axel Rauschmayer, Speaking JavaScript

2018-11-10