JavaScript 日常系列寫著寫著,就此進入了我的苦手範圍QQ,之後的主題應該都是我的修羅場,考驗著自己觀念有沒有打穩的每一篇;不過,我還是會加油的。
在寫這篇之前我看了許多文章,趁著記憶還新,趕緊把自己理解的部分寫下來。
前面幾篇我們有稍微談到型別,大概是小小擦個邊這樣子談到,但其實那些我們點名出來的型別都包含在 JavaScript 的兩大型別裡面,分別是「原始型別」與「物件型別」。
原始型別為 Pass by value,是一個分配好的記憶體空間,他是固定的,我們無法去更動他的記憶體位置。
另一個名字為基本型別,還叫做「純值」;白話一點來說,他代表的是一個單一的值,並且沒有「方法」也不能被改變,譬如 let a = 3
的那個 3
,他就是「3」而已不會變動也沒有其他意思。
在這個歸類下的型別有幾種:
辨別原始型別
那麼要如何知道是否為原始型別呢?我們可以使用 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
才對。
物件型別針對記憶體位置去操作,是 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原理小記