(1) 原始型別 & 物件型別的主要差異與運作原理

型別的差異

JavaScript 的型別分為以下兩種。

  1. 「原始型別」,沒有屬性與方法。
  2. 「物件型別」,可任意存取屬性與方法。

原始型別 (Primitive types) 包括

  1. number
  2. string
  3. boolean
  4. null
  5. undefined
  6. symbol (ES6)

如何確定變數是 「原始型別」 還是 「物件型別」?

使用 typeof 方法

1
2
3
4
5
var str = "string";
console.log(typeof str); // string

str.val = 100;
console.log(str.val); //undefined,在原始型別上無法設定屬性。

到這邊會有個疑問是,為什麼會說「在原始型別上無法設定屬性」? 我們在設定 string.length 或是 str.split 的時候可以操作,那位甚麼會提到我們無法設定屬性和方法。

這是因為 JS 考慮到需要節省系統資源,所以原始型別在使用時會 自動裝箱(boxing)。
形成原始型別包裹物件,使用完畢後會 自動拆箱(unboxing) 還原回原始型別。

此外原始型別包裹物件則可用 valueOf 方法取得對應的原始型別。

1
2
var obj = new String("string");
console.log(typeof obj); // object
1
2
3
obj.val = 100;
console.log(obj.val); // 100
console.log(typeof obj.valueOf()); // string

裝箱 boxing 與 拆箱 unboxing 例子

我們日常使用為以下:

1
2
var str="word";
var txt=str.substring(3);

它的內部原理

1
2
3
4
5
6
// 變成一個物件的型別
var str=new String("word");
// 就可以操作 substring
var txt=str.substring(3);
// 操作完之後,透過 .vauleof()這個方法,取得原始值
str=str.valueOf();

一些小知識

需要特別注意的是,在數學運算時

  1. 會優先呼叫 .valueOf 方法
  2. 若回傳「非原始型別」則會改呼叫 .toString 方法。

以下範例:

範例一

alert(n1) 時,回傳的是 valueOf 的 ‘five’,當使用到數學運算時,用到的就是 toString 的 5 。

1
2
3
4
5
6
7
var n1 = {
valueOf: function(){ return 5; },
toString: function(){ return 'five'; }
};

alert(n1) // 'five'
alert(n1+5) // '6'

範例二

valueOf 裡面回傳的是 物件(非原始型別) 時,就會使用 toString 方法,所以就是 15。

1
2
3
4
5
6
var n2 = {
valueOf: function(){ return {}; },
toString: function(){ return 10; }
};

n2+5 //15

(1) 原始型別 & 物件型別的主要差異與運作原理
https://phoebeho.com/js-advanced/20211216/719345942/
作者
Phoebe
發布於
2021年12月16日
許可協議