iT邦幫忙

2021 iThome 鐵人賽

DAY 18
0
Modern Web

我的JavaScript日常系列 第 18

JavaScript Day 18. 原始型別與物件型別

JavaScript 日常系列寫著寫著,就此進入了我的苦手範圍QQ,之後的主題應該都是我的修羅場,考驗著自己觀念有沒有打穩的每一篇;不過,我還是會加油的。

在寫這篇之前我看了許多文章,趁著記憶還新,趕緊把自己理解的部分寫下來。

前面幾篇我們有稍微談到型別,大概是小小擦個邊這樣子談到,但其實那些我們點名出來的型別都包含在 JavaScript 的兩大型別裡面,分別是「原始型別」與「物件型別」。


原始型別 ( Primitive Type)

原始型別為 Pass by value,是一個分配好的記憶體空間,他是固定的,我們無法去更動他的記憶體位置。

另一個名字為基本型別,還叫做「純值」;白話一點來說,他代表的是一個單一的值,並且沒有「方法」也不能被改變,譬如 let a = 3 的那個 3,他就是「3」而已不會變動也沒有其他意思。

在這個歸類下的型別有幾種:

  • 布林 ( Boolean )
  • Null ( 空 )
  • Undefined ( 未定義 )
  • Number ( 數值 )
  • String ( 字串 )
  • BigInt ( 整體數值 )
  • Symbol ( ES6新定義的型別 )

辨別原始型別

那麼要如何知道是否為原始型別呢?我們可以使用 typeof 去檢查,這邊要注意除了 null 以外,其他型別都是有辦法正確檢測的。

let newString = '福爾摩斯';
typeof newString; // "string"
typeof '福爾摩斯'; // "string"

let newNumber = 2018;
typeof newNumber; // "number"
typeof 2018; // "number"

let newBoolean = true;
typeof newBoolean; // "boolean"
typeof true; // "boolean"

let newUndefined = true;
typeof newUndefined; // "undefined"
typeof undefined; // "undefined"

let newNull = true;
typeof newNull; // "object"
typeof null; // "object"

null 這個部分呈現 typeof null === "object" 其實是 JavaScript 早期的一個 bug,null 應該要是 null 才對。


物件型別 ( Object Type )

物件型別針對記憶體位置去操作,是 Pass by reference,當我們將一個物件賦值給變數,他會參照那個物件的記體位置。

辨識出原始型別以後,剩下的幾乎都是物件型別了,譬如我們所熟悉的「陣列」與「函式」,甚至到全域本身都是物件型別的類別。

有什麼證據證明陣列是物件呢?讓 typeof 來證明:

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

另外,這邊也提供一個分辨陣列的方法 Array.isArray(),使用這個方法會讓函式檢查傳入的值是否為一個陣列。

語法:

Array.isArray(obj)

以下提供範例:

Array.isArray([1, 2, 3]);  // true
Array.isArray({foo: 123}); // false
Array.isArray('foobar');   // false
Array.isArray(undefined);  // false

再把話題拉回來,剛剛說到函式也是物件型別,可是當我們對函式使用 typeof 的時候會驚訝的發現,回傳的竟然不是 object

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

前幾篇我有介紹到一個牽涉到原型的方法 instanceof,在這邊剛好就可以使用他來幫我們判斷 function 到底是不是 object。

console.log( name instanceof Object ) // true

可以看到函式確實是物件型別沒錯,但為什麼會回傳 function 呢?typeof 回傳 function 的情況是,只要有一個對象有一個不為 0 的 call 屬性 / 方法,或者是 js_FunctionClass 類型,也就是這個對象裡面有 function 標記的話,就會回傳 function,其他情況則回傳 object

這邊引用開發者的解釋,稍微說明一下 call 方法是什麼:

執行與此對象關聯的代碼。通過函數調用表達式調用。內部方法的參數是一個 this 值和一個包含調用表達式傳遞給函數的參數的列表。實現此內部方法的對象是可調用的。

簡單說,一個對象如果支持了內部的 [[Call]] 方法,那麼他就可以被調用,就變成了函數,所以叫做函數對象。

另外,如果一個函數支持了內部的 [[Construct]] 方法,那麼就可以使用 new 或是 super 來調用,這時我們可以把這個函數稱為「構造函數」。


寫完這篇以後,感覺自己腦內的知識量暴增需要消化消化,但很開心能夠完整的整理出一篇這樣的文章,希望看過的人可以跟我一起知識量暴增^o^/

參考資料:
JS 原力覺醒 Day9 - 原始型別與物件型別
MDN Array.isArray()
進階 Javasctipt 概念 (3)
JavaScript的typeof原理小記


上一篇
JavaScript Day 17. 認識物件
下一篇
JavaScript Day 19. by value ( 傳值 ) 與 by reference ( 傳址 )
系列文
我的JavaScript日常31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言