JavaScript 的七種內(nèi)置類型:
- 空值(null)
- 未定義(undefined)
- 布爾值(boolean)
- 數(shù)字(number)
- 字符串(string)
- 對(duì)象(object)
- 符號(hào)(symbol,ES6 新增)
除對(duì)象之外膛堤,其他均為基本類型,對(duì)象可稱為引用類型
1. 類型的判斷
以下六種類型均有同名的字符串值與之對(duì)應(yīng):
typeof undefined === "undefined"; // true
typeof true === "boolean"; // true
typeof 42 === "number"; // true
typeof "42" === "string"; // true
typeof { life: 42 } === "object"; // true
typeof Symbol() === "symbol"; // true阁最,// ES6 新加入的類型
1.1 null
通過 typeof
關(guān)鍵字對(duì) null
進(jìn)行取值,發(fā)現(xiàn)結(jié)果是 object
骇两,這是 JavaScript 一直以來的一個(gè)語言上的 BUG速种,也許
永遠(yuǎn)不會(huì)修復(fù),因?yàn)樾迯?fù)會(huì)帶來更多的問題低千。
這是因?yàn)椴煌膶?duì)象在底層都表示為二進(jìn)制配阵,在 JavaScript 中二進(jìn)制前三位都為 0 的話會(huì)被判斷為 object
類型, null 的
二進(jìn)制表示全部都是 0示血,自然前三位也是 0棋傍,所以執(zhí)行 typeof 時(shí)會(huì)返回“object”。
typeof null === "object"; // true
1.2 function
通過 typeof
關(guān)鍵字對(duì) function
進(jìn)行取值难审,結(jié)果是 function
瘫拣,但是它并不是一個(gè)內(nèi)置類型,實(shí)際上是 object 的一個(gè)
子類型告喊。概括來說麸拄,函數(shù)是可調(diào)用的對(duì)象。具體原因是它有一個(gè)內(nèi)部屬性 [[Call]]
黔姜,該屬性讓其可執(zhí)行拢切。
另外函數(shù)還有屬性,其屬性 length 就是聲明的參數(shù)的個(gè)數(shù)秆吵。
typeof function a() {
/* .. */
} === "function"; // true
1.3 array
通過 typeof
關(guān)鍵字對(duì) function
進(jìn)行取值淮椰,結(jié)果是 object
,因?yàn)閿?shù)組也是對(duì)象纳寂。準(zhǔn)確的說是 object 的一個(gè)子類型实苞,數(shù)組的元素是按照下表來索引,length 是元素的的個(gè)數(shù)烈疚。
所以通過 typeof
關(guān)鍵字無法區(qū)分出是否是數(shù)組黔牵。
typeof [1, 2, 3] === "object"; // true
1.4 通過 toString
判斷類型
在任何值上調(diào)用 Object 原生的 toString()
方法,都會(huì)返回一個(gè) [object NativeConstructorName]
格式的字符串爷肝。每個(gè)類在內(nèi)部都有一個(gè) [[Class]]
屬性猾浦,這個(gè)屬性中就指定了上述字符串中的構(gòu)造函數(shù)名。
對(duì)于 Object 對(duì)象灯抛,直接調(diào)用 toString()
就能返回 [object Object]
金赦。而對(duì)于其他對(duì)象,會(huì)直接返回內(nèi)容的字符串对嚼,所以需要通過 call
or apply
來改變 toString()
的上下文來返回正確的類型信息夹抗。
不過此方法僅支持對(duì)內(nèi)置對(duì)象的判斷,不能檢測(cè)非原生構(gòu)造函數(shù)的構(gòu)造函數(shù)名纵竖。
Object.prototype.toString.call(""); // [object String]
Object.prototype.toString.call(1); // [object Number]
Object.prototype.toString.call(true); // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); // [object Null]
Object.prototype.toString.call(newFunction()); // [object Function]
Object.prototype.toString.call(newDate()); // [object Date]
Object.prototype.toString.call([]); // [object Array]
Object.prototype.toString.call(newRegExp()); // [object RegExp]
Object.prototype.toString.call(newError()); // [object Error]
Object.prototype.toString.call(document); // [object HTMLDocument]
Object.prototype.toString.call(window); //[object global] window 是全局對(duì)象 global 的引用
再通過簡(jiǎn)單的處理漠烧,就可以獲得需要的類型:
const type = Object.prototype.toString.call("").slice(8, -1).toLowerCase();
2. 值和類型
JavaScript 中的變量是沒有類型的杏愤,只有值才有。變量可以隨時(shí)持有任何類型的值已脓。
2.1 undefined 和 undeclared
undefined(未定義)不同于 undeclared(未聲明)珊楼。
已在作用域中聲明但還沒有賦值的變量,是 undefined 的度液。相反厕宗,還沒有在作用域中聲明 過的變量,是 undeclared 的堕担。
var a;
a; // undefined
b; // ReferenceError: b is not defined
對(duì)于 undeclared(或者 not defined)變量已慢,typeof 照樣返回 "undefined"。這是因?yàn)?typeof
有一個(gè)特殊的安全防范機(jī)制霹购。
var a;
typeof a; // "undefined"
typeof b; // "undefined"
既然 typeof
有此類的安全防范機(jī)制蛇受,那么可以利用此機(jī)制來檢查一些可能不存在的 undeclared 的變量,如下:
// 這樣會(huì)拋出錯(cuò)誤
if (DEBUG) {
console.log("Debugging is starting");
}
// 這樣是安全的
if (typeof DEBUG !== "undefined") {
console.log("Debugging is starting");
}