今天要講到 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
結論
- Function 只是一種特殊型態的物件 (函式物件)
- Function 可以用來創造新的物件 (搭配 new 關鍵字)
- 不是所有的型別都是物件,但是除了純值以外的型別都是物件。
- JS 裡面有六種純值
- Symbol 可以用來防止物件屬性被意外的修改