iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 6
0
自我挑戰組

你為什麼不問問神奇 JavaScript 呢?系列 第 6

Day6 - Native

就是內建函式。

先列出常用的

  • String()
  • Number()
  • Boolean()
  • Array()
  • Object()
  • Function()
  • ReqExp()
  • Date()
  • Error()
  • Symbol() (ES6 新增)

之前提過,JavaScript 利用偽裝的行銷手法,所以他可以做到下面的事。JavaScript 弄的跟 Java 非常像,不只名稱連程式碼都是。

var s = new String( "Hello World!" );
console.log( s.toString() );  // "Hello World!"

可是實際上

typeof s;                          // "object" ... 不是 "String"
s instanceof String;               // true
Object.prototype.toString.call(s); // "[object String]"

new String("Hello World!") 建立的字串包裹器的物件。裡面包著 "Hello World!",而不是建立純值(primitive)本身。

有些人習慣把內建函式 ( natives ) 當建構子用,這不是真的 JavaScript

(嘗試著用一句話,引出整段的重點,方便閱讀。)

Internal[[Class]]

typeof 為 "object" 的值,會有額外內部 [[class]] 內建的特性。
[[class]]不是一般的類別,(這邊會用到原型 prototype 的概念)。請當做是在 Javascript 內部的分類項目,無法直接取用。
要透過 Object.prototype.toString(..)方法,以目標值呼叫來間接顯露。

這邊分為三個區塊
是否為純質(primitive),和是否為內建函式(natives)。

  • primitive + Natives
  • primitive + Natives
  • primitive + Natives

primitive + natives

內部的 [[class]] 的值,會對應到關聯的內建原生建構器。

Object.prototype.toString.call( [1,2,3] );          
// "[object Array]"
Object.prototype.toString.call( /regex-literal/i ); 
// "[object RegExp]"

primitive + Natives

雖然不存在 native,但還是會顯示出來了!

Object.prototype.toString.call( null );          
// "[object Null]"
Object.prototype.toString.call( undefined );
// "[object Undefined]"

primitive + Natives

雖然顯示了,但背後有做很多事情。

Object.prototype.toString.call( "haha" );
// "[object String]"
Object.prototype.toString.call( 1208 );
// "[object Number]"
Object.prototype.toString.call( true );
// "[object Boolean]"

基本型別 ( primitives ) 都會自動被他們所對應的物件包裹器 ( object wrappers ) 所封裝 ( boxed ),這就是為何露出來的內部[[class]] 值分別會是 "String", "Number", 以及 "Boolean"了。

:::success
但成為了物件,JS引擎對顯示型別做了一些偽裝。
:::

封裝用包裹器 (object wrappers)

基本型別沒有屬性或方法。(他怎麼做到下面的事情?)

var a = "haha";

a.length;      // 4
a.toUpperCase; // "HAHA"

因為 JavaScript 自動幫你封裝了基本型別!以利這種存取。

(怎麼封的還沒提到,就是用到基本型別的物件包裹器。
這邊隱含著意思是,基本型別雖然不是物件,但有需要會幫你包一個方法。基本型別直接成為物件會降低效能。)

所以,既然他會幫你包,幫你最佳化。你就別再宣告 new String() 或 new Number() 再包一次。直接用字面值的基本型別。

JS做出了一些貼心的幫忙

物件包裹器的陷阱

var a = new Boolean( false );

if (!a) {
    console.log( "Oops" ); // 永遠不會執行!
}

因為把 false 包裹起來,但物件是 truthy,當然不會執行。

手動封裝基本型別,還可以使用 Object(..) 函式。這和用 new 關鍵字完全相同。

var a = "abc";

var b = new String( a );
var c = Object( a );

所以沒必要再替自己添麻煩

解封裝

現在想取出已封裝物件下的基本型別,兩種方法:valueOf()、隱性強制轉型。

valueOf()

var a = new String( "abc" );
a.valueof(); // "abc"

隱性強制轉型

借用這個方法,可以把型別從物件轉回來。

var a = new String( "abc" );
var b = a + ""; // b

typeof a; // "object"
typeof b; // "string"

參考資料

你所不知道的 JS


上一篇
Day5 - 值(下)
下一篇
Day7 - Native 適合用來做建構器嗎?
系列文
你為什麼不問問神奇 JavaScript 呢?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言