iT邦幫忙

1

Javascript 運算子、型別與文法 - 原始型別及物件型別

Javascript 的型別可以分為兩大類,分別是 原始型別 以及 物件型別

https://ithelp.ithome.com.tw/upload/images/20210810/201405062dO9pafkZz.png

我們經常會使用這些型別各自的方法, 例如用 length 取得字串的長度。

但為什麼明明是 基本型別 卻會有 屬性 以及 方法 可以呼叫?

這是因為這些型別有著相對應的 包裹物件 (Primitive Wrapper),這些 包裹物件 包含了這些物件可以使用的方法,我們接著會在物件型別中做更多說明。

https://ithelp.ithome.com.tw/upload/images/20210810/20140506tTLKGZh6NM.png

原始型別

先來看關於原始型別的範例程式碼:

let a, b, c, d, e;
a = 1;       //number
b = '文字';  //string
c = true;   //boolean
d = {};     //object
e = null;   //object
console.log(typeof(a));
console.log(f); // VM1420:1 Uncaught ReferenceError: e is not defined

console.log(typeof(f)); // undefined

值得注意的是:

  1. e 雖然被指派為 null,但型別卻是 object,這是 js 長久以來的一個錯誤,沒有修正是因為許多的網站也使用了這樣的錯誤觀念完成了網站。如果修正的話會造成許多的網站因此而壞掉,所以就把這個錯誤保留了下來。
  2. f 這個未定義的變數的型別是 undefined, 這是 typeof 保護機制,如果在沒有定義 f 這個變數的情境下 console.log 的話,會出現的是 not defined

現在來看另一段範例:

let a = 'ming ';
console.log(a.length);        // 5
console.log(a.toUpperCase()); // MING 
console.log(a.trim());        // ming

上述這些方法都是針對字串所做的,但是直接 console.log(a); 也只有顯示 'ming ',並沒有顯示那些可以用的方法,而 包裹物件 則可以做得到。

物件型別

前面提到,基本型別會有「屬性」以及「方法」是因為這些型別有著相對應的包裹物件 (Primitive Wrapper)。

也就是「自動轉型」賦予 StringNumberBoolean 這些神奇的功能。

在 JavaScript 這門程式語言當中,當我們嘗試著要去存取 StringNumberBoolean 這三種基本型別的屬性時,它就只會在「那一刻」被轉型為該類別的「物件」。

let a = 'ming ';
console.log(a.length);

上面段程式碼,當我們試著去讀取 a.length 的時候,背後原理是這樣的:

let a = new String('ming ');
a.length;

a = null;
a = 'ming ';

它會透過對應的物件建構器將 'ming ' 包裝成一個 String 的「物件」,然後回傳對應的屬性後,即刻銷毀恢復成基本型別。

我們可以透過下面這段程式碼來了解 原始型別物件型別 的不同。

let a = 'ming ';

let e = new String(a);
console.log(a, e);

我們可以透過下面這段程式碼來了解 原始型別 與 物件型別 的不同。

  • a 是一個原始型別為字串的變數。
  • e 是一個透過建構式建立的物件。

透過這樣的方式宣告之後,來看看執行的結果:

https://ithelp.ithome.com.tw/upload/images/20210810/20140506FgJdGMc861.png

可以看到 [[prototype]] 就是 e 這個包裹物件的可以用的方法總集

同樣可以套用原是型別的字串身上,所以我們剛剛用的 trim lengthto UpperCase 都在這裡面喔!

然而,其實並不建議在宣告字串的時候使用字串的 包裹物件 方式宣告,這種宣告方式又稱為 建構式

後續的篇章會講到,而不建議的最大重點在於,透過建構式宣告出來的變數資料型別不會是字串,而是 物件 喔!

參考文章


尚未有邦友留言

立即登入留言