iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 9
1
Modern Web

JavaScript 原力覺醒 - 成為絕地武士之路系列 第 9

JS 原力覺醒 Day9 - 原始型別與物件型別

一路上感謝各位讀者們的支持和回饋。
本 30 天系列文目前已經將篇幅重新整理、編纂成冊。
《JavaScript 概念三明治》在天瓏書局上架囉!
喜歡這個系列,想閱讀更詳細原理說明的讀者可以參考:
https://www.tenlong.com.tw/products/9789864347575

今天要講到 JS 型別概念,雖然你平常寫 JS 的時候可以看到很多種類別,但其實大致上可以分為兩個比較主要的大分類。

Outline

  • 物件型別 ( Object Type )
  • 原始型別(Primitive Type)

物件型別 ( Object Type )

第一種叫做「物件型別」,「物件」指的是物件。恩,但其實有很多東西本身也算是物件,例如陣列和函式,不相信嗎?讓我們繼續看下去,你可以再 JS 裡面宣告一個陣列,然後用 typeof 去得到這個陣列的型別,結果一定會讓你感到意外:

let arr = []  
console.log(typeof arr)  //object

那麽這樣我要怎麼判斷出陣列了呢? JS 提供了 Array.isArray() 的方法,來讓我們知道某物件是不是陣列。好,那麼函式也是物件型別嗎?當我一樣用 typeof 去觀察的時候,居然得到了不同的結果!

 let hello = function(){
	console.log('hello') 
} 
console.log(typeof hello) // function

「 看吧!聽你在亂講 」,你一定想這麼說,別急,換另一個方法來觀察看看, instanceof 是一個可以觀察某對象是不是另外一個對象的後代,那我們來看看 function 是不是物件的後代:

 console.log( hello instanceof Object ) // true

答案是沒錯。不過為什麼會這樣呢?函式在 JS 裡面算是一個比較特別的物件,稱為「 函式物件 ( Function Object ) 」,所以剛才我們用 typeof 乍看之下才會得到 function 的結果。 而正是因為「函式同時也是物件」這樣的特性,前面我們提到的「函式表達式 ( Function Expression ) 」才能成功!

let someVariable = function() {...} 

而函式物件特別的地方在於,只要搭配 new 關鍵字,他也能夠用來產生新的物件,這與其他物件導向語言產生物件的方法非常類似:

const Foo = function () {};
const bar = new Foo();
bar; // {}
bar instanceof Foo; // true
bar instanceof Object; // true

原始型別 ( Primitive Type )

原始型別又稱為純值 ( Primitive Type ) ,用來表示只代表單一值的一種資料型別,如 12 只代表12,沒有其他意思了,原始型別上也不像 物件型別上,有一些預設方法讓我們能夠直接取用,( Array.isArray )這樣子的東西,不像物件那麼複雜,所以稱為純值。此外,因為 JS 內只有兩種分類,所以「除了原始型別的型別,都是物件型別」,因此只要弄清楚哪些是原始型別,就可以很輕易找出物件型別。

JS 裡面有六種純值:

  • null
  • undefined
  • number ( 0 )
  • string ( “string”)
  • boolean ( true )
  • symbol (目前少用)

其中比較特別的純值是 ES6 之後才出現的 Symbol ,Symbol 類別是透過 Symbol () 方法產生,由於每個 Symbol 值所對到的記憶體位置不一樣,因此很適合用來避免物件屬性意外的被修改。

const a = {};
const symbol1 = Symbol('123');
const symbol2 = Symbol('123'); // they have different memory address in JS 
console.log(typeof symbol1);// expected output: "symbol"

a.symbol1 = 'Hello!';
a[symbol1] // undefined
a['symbol1'] // "Hello!"

上面可以看出使用字串來存取物件屬性跟以 Symbol 來存取會得到不同的結果,因為以往物件的屬性除了用 「.」運算子來存取,但這樣很容易因為重複赴值而被意外的修改,因此 Symbol 就可以用來避免這個問題發生。

" A symbol value may be used as an identifier for object properties; this is the data type's only purpose. " - MDN Docs

結論

  1. Function 只是一種特殊型態的物件 (函式物件)
  2. Function 可以用來創造新的物件 (搭配 new 關鍵字)
  3. 不是所有的型別都是物件,但是除了純值以外的型別都是物件。
  4. JS 裡面有六種純值
  5. Symbol 可以用來防止物件屬性被意外的修改

上一篇
JS 原力覺醒 Day08 - Closures
下一篇
JS 原力覺醒 Day010 - 自動轉型 (Coercion)
系列文
JavaScript 原力覺醒 - 成為絕地武士之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
唐唐
iT邦新手 5 級 ‧ 2019-10-05 16:18:57

a['mySymbol'] 是不是應該要改成 a['symbol1'] ?

const a = {};
const symbol1 = Symbol('123');
const symbol2 = Symbol('123'); // they have different memory address in JS 
console.log(typeof symbol1);// expected output: "symbol"

a.symbol1 = 'Hello!';
a[symbol1] // undefined
a['mySymbol'] // "Hello!"
Spark iT邦新手 5 級 ‧ 2019-10-05 23:06:33 檢舉

唐唐你好:
感謝你的回覆,確認後發現真的是我的筆誤,不好意思,那邊只是要表現使用字串來存取物件跟使用 Symbol 會得到不ㄧ樣的結果 ,已經修改了,非常謝謝!

我要留言

立即登入留言