JavaScript 的型別有兩大類,分別為 原始型別、物件型別,接下來會分別對這兩種型別做一些介紹,並搭配著簡單的範例來讓大家了解。
原始型別沒有屬性 ( Property ) 與方法 ( Methods ),JavaScript 為了節省系統資源,原始型別再使用時會自動裝箱 ( Boxing ) 來形成 原始型別包裹物件 ( Primitive Wrapper )
,使用完畢後則會自動拆箱 ( unboxing ) 來還原原始型別。
原始型別包裹物件可用 valueOf 的方法來取得對應的原始型別。
ES6 引入 Symbol 這個原始型別的原因是,因為以往物件中的屬性名稱都是字串,這很容易造成名稱上的衝突,例如你引用了一個其他人提供的物件,又想對這個物件添加新的方法,這時候就有可能與舊的方法產生衝突,而這時候 Symbol 就保證了每個屬性都是獨一無二的。
let string = Symbol();
console.log(typeof string) // symbol
裝箱的最大作用是將原始型別當作物件來使用,當我們在調用原始型別的方法時,其實 JavaScript 就在你不知不覺當中使用了裝箱與拆箱了呢。
就讓我們來看一段範例吧!
let me = "金城武";
console.log(typeof me); // string
me.manPower = 100;
console.log(me.manPower) // undefined
對於我是金城武,這點大家都毫無疑問,但要如何讓我的 ManPower 達到滿分呢?
我們可以使用 new 的方式,new 大家可以把它當成創建一個物件。
所以我們就可以用以下方法來使我的 ManPower 達到滿分
let me = new String("金城武");
console.log( typeof me ); // object
me.manPower = 100;
console.log(me.manPower); // 100
console.log(typeof me.valueOf()); // valueOf() 來取得原始型別包裹物件的對應原始型別
以上就是實現裝箱的方式,若有同學不太懂 valueOf 這個方法,我在文末有附上一些資料,可稍做參考。
那既然都實現了裝箱,我們該如何實作拆箱呢?
其實非常簡單,請看以下範例
me = me.valueOf(); // 利用取得原始型別包裹物件的對應原始型別來指定
console.log(typeof me); // string
是不是非常簡單呢?
那平常 JavaScript 在什麼時候會用到這樣的機制?
其實在我們調用 String 的方法時,就用到囉
let str = "stay foolish stay hungry";
str.indexOf('stay');
上面看似簡單的兩行,其實 JavaScript 幫我們做了這些
let str = new String("stay foolish stay hungry"); // 裝箱
let txt = str.indexOf("stay");
str = str.valueOf(); // 拆箱
這裡的原始型別包裹物件與上面提到的原始型別的 number、string、boolean 是不同的哦!
我們可以從以下範例得證
let objString = new String("I'm a string"); // object
let string = "I'm a string"; // string
console.log(objString == string) // 以值來說為 true
console.log(objString === string) // 但以類別來區分就為 false
呼,型別系統就先介紹到這邊,一不小心就打了這麼多,希望看完這篇文章的同學能對 型別系統 有個概念,如果有錯誤的地方,還請不吝指教哦!
參考資料:Tommy - 深入 JavaScript 核心課程
阮一峰 - ECMAScript 6 入門 - Symbol
MDN - valueOf