js共有7種內置類型:數組
除對象外,其餘統稱爲「基本類型」瀏覽器
咱們可用typeof來查看值的類型:安全
typeof undefined === "undefined"; // true
typeof true === "boolean"; // true
typeof 42 === "number"; // true
typeof "42" === "string"; // true
typeof { life: 42 } === "object"; // true
// ES6新增類型
typeof Symbol() === "symbol"; // true
複製代碼
null比較特殊,typeof對它處理有問題:bash
typeof null === "object"; // true
複製代碼
正確結果應該返回null,但這個bug由來已久,在js中已經存在了將近20年,因爲牽涉到太多的Web系統,「修復」它會產生更多的bug,令許多系統沒法修復。函數
咱們須要使用符合條件來檢測null的類型:spa
var a = null;
(!a && typeof a === "object"); // true
複製代碼
null是假值,也是惟一一個用typeof檢測會返回「object」的基本類型code
還有一種狀況:對象
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"
變量在未持有值的時候爲undefined,此時typeof返回「undefined」
var a;
typeof a;// "undefined"
var b = 42;
var c;
b = c;
typeof b; // "undefined"
typeof c; // "undefined"
複製代碼
大多數開發者傾向於undefined等同於undeclared(未聲明),但在js中他們徹底是兩回事
var a;
a; // undefined
b; // 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有一個特殊的安全防範機制
該安全防範機制對在瀏覽器中運行的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錯誤。