一、內建型別
js共有7種內建型別:
- 空值(null)
- 未定義(undefined)
- 布林值(boolean)
- 數字(number)
- 字串(string)
- 物件(object)
- 符號(symbol, ES6新增)
除物件外,其他統稱為“基本型別”
我們可用typeof來檢視值的型別:
typeof undefined === "undefined";
// truetypeof true === "boolean";
// truetypeof 42 === "number";
// truetypeof "42" === "string";
// truetypeof {
life: 42
} === "object";
// true// ES6新增型別typeof Symbol() === "symbol";
// true複製程式碼
null比較特殊,typeof對它處理有問題:
typeof null === "object";
// true複製程式碼
正確結果應該返回null,但這個bug由來已久,在js中已經存在了將近20年,由於牽涉到太多的Web系統,“修復”它會產生更多的bug,令許多系統無法修復。
我們需要使用符合條件來檢測null的型別:
var a = null;
(!a &
&
typeof a === "object");
// true複製程式碼
null是假值,也是唯一一個用typeof檢測會返回“object”的基本型別
還有一種情況:
typeof function a() {
/*...*/
} === "function";
// true複製程式碼
function也是js的一個內建函式。實際上是object的一個“子型別”。具體來說,函式是“可呼叫物件”,它有一個內部屬性[[Call]],該屬性使其可以被呼叫。
函式不僅是物件,還可以擁有屬性。如:
function a(b, c) {
/*..*/
}複製程式碼
函式物件的length屬性是其宣告的引數的個數:
a.length;
// 2複製程式碼
該函式宣告瞭兩個命名引數,b、c,所以其length值為2
typeof [1, 2, 3] === "object";
// true複製程式碼
陣列也是物件,確切的說是object的一個“子型別”,陣列的元素按數字順序來進行索引,其length屬性是元素的個數
三、值和型別
js中的變數是沒有型別的,只有值才有。變數可以隨時持有任何型別的值。js不做“型別強制”,語言引擎不要求變數總是持有與其初始值同型別的值。
在對變數執行操作時,得到的結果並不是該變數的型別,而是該變數持有的值的型別,因為js中的變數沒有型別
var a = 42;
typeof a;
// "number"a = true;
typeof a;
// "boolean"複製程式碼
typeof運算子總是會返回一個字串:
typeof typeof 42;
// "string"複製程式碼
typeof 42 = “number”, typeof “number” = “string”
1、undefined和undeclared
變數在未持有值的時候為undefined,此時typeof返回“undefined”
var a;
typeof a;
// "undefined"var b = 42;
var c;
b = c;
typeof b;
// "undefined"typeof c;
// "undefined"複製程式碼
大多數開發者傾向於undefined等同於undeclared(未宣告),但在js中他們完全是兩回事
- undefined:已在作用域中宣告但還沒有賦值的變數
- undeclared:還沒有在作用域中宣告過的變數
var a;
a;
// undefinedb;
// ReferenceError: b is not defined複製程式碼
undefined 和 is not defined是兩碼事。若此時瀏覽器報錯成“b is not found” 或 “b is not declared”會更準確
var a;
typeof a;
// "undefined"typeof b;
// "undefined"複製程式碼
對於undeclared變數,typeof照樣返回”undefined”
雖然b是一個undeclared變數,但typeof b沒報錯,這是因為typeof有一個特殊的安全防範機制
2、typeof Undeclared
該安全防範機制對在瀏覽器中執行的js程式碼很有幫助,因為多個指令碼檔案會在共享的全域性名稱空間中載入變數。
如何在程式中檢查全域性變數DEBUG才不會出現RefrenceError錯誤,這是typeof的安全防範機制就能做到:
// 這樣會報錯if (DEBUG) {
console.log("Debugging is staring");
}// 這樣是安全的if (typeof DEBUG !== "undefined") {
console.log("Debugging is staring");
}複製程式碼
還有一種不通過typeof的安全防範機制的方法,就是檢查所有全域性變數是否是全域性物件的屬性,瀏覽器中的全域性物件是window
if (window.DEBUG) {
// ..
}if (!window.atob) {
// ..
}複製程式碼
與undeclared變數不同,訪問不存在的物件屬性(甚至是在全域性物件window上)不會產生RefrenceError錯誤。