typeof 的八种数据类型
typeof可判断类型比较有限,它的输出值只有八种,即用 typeof 判断一个变量,得到的结果只会是以下八种类型中的一种
// es5
typeof '' // string
typeof 1 // number
typeof true // boolean
typeof undefined // undefined
typeof Array // function
typeof {} // object
// es6
typeof Symbol() // symbol
// es10
typeof BigInt(1) // bigint
typeof 的实现原理
第一版 JS 的 typeof 实现如下,在 JS 诞生之初就只有六种类型判断。
if (JSVAL_IS_VOID(v)) { // 判断是否为 undefined
type = JSTYPE_VOID;
} else if (JSVAL_IS_OBJECT(v)) { // 判断是否为 object
obj = JSVAL_TO_OBJECT(v);
if (obj && (ops = obj->map->ops, ops == &js_ObjectOps)
? (clasp = OBJ_GET_CLASS(cx, obj), clasp->call || clasp == &js_FunctionClass)
: ops->call != 0) {
type = JSTYPE_FUNCTION;
} else {
type = JSTYPE_OBJECT;
}
} else if (JSVAL_IS_NUMBER(v)) { // 判断是否为 number
type = JSTYPE_NUMBER;
} else if (JSVAL_IS_STRING(v)) { // 判断是否为 string
type = JSTYPE_STRING;
} else if (JSVAL_IS_BOOLEAN(v)) { // 判断是否为 boolean
type = JSTYPE_BOOLEAN;
}
数组的判断
typeof 的输出值中没有 array 这一项,所以当需要判断数组类型时,可以使用 instanceof。instanceof 会判断右侧表达式是否在左侧表达式的原型链上,所以下面的两个 instanceof 都为 true。
typeof [1,2] // object
[1,2] instanceof Array // true
[1,2] instanceof Object // true
独树一帜的 null
可以用 typeof 判断 null 类型嘛?
答案是 NO,前面说了,typeof 只有八种类型,其中并没有 null 这一类型,如果用 typeof 判断,会得到 object 的结果。
typeof null // object
为什么?
因为在 Javascript 底层存储变量的时候,会在变量的机器码低位 1-3 位表示类型信息。而 null 的低位 1-3 解析到的为 000,而000 表示的是 obecjt 类型。
000 对象
010 浮点数
100 字符串
110 布尔值
1 整数
null:所有码都是0
undefined:用 -2^30 表示
可以用 instanceof 判断 null 类型嘛?
答案依然是 NO,因为 null 根本没有 __proto__ 属性,所以用 instanceof 去检测永远都不会返回 true
null instanceof Object // false
null instanceof null // 报错
那要怎么判断?
- 强等,最简单的判断方式
===判断是否是null - 通过
Object.prototype.toString判断
null === null // true
Object.prototype.toString.call(null) // [object Null]
拓展:Object.prototype.toString 可以判断所有类型
Object.prototype.toString.call(1) // [object Number]
Object.prototype.toString.call('') // [object String]
Object.prototype.toString.call({}) // [object Object]
Object.prototype.toString.call(true) // [object Boolean]
Object.prototype.toString.call(()=>{}) // [object Function]
Object.prototype.toString.call(null) // [object Null]
Object.prototype.toString.call(undefined) // [object Undefined]
Object.prototype.toString.call(Symbol) // [object Symbol]
Object.prototype.toString.call(1n) // [object BigInt]
instanceof 实现原理
function new_instance_of(leftValue, rightValue) {
let rightProto = rightValue.prototype;
leftValue = leftValue.__proto__;
while(true) {
if (leftValue === null) {
return false;
}
if (leftValue === rightProto) {
return true;
}
leftValue = leftValue.__proto__
}
}
课后习题
下面的表达式分别输出什么呢?如果全部回答正确,你对原型链和 instanceof 的理解应该非常到位了。
Object instanceof Object
Function instanceof Function
Function instanceof Object
Object instanceof Function