Chipmunk & Panda

-- 鼠熊部落格

All work and no play makes Jack a dull boy.

JavaScript 变量类型判断方法

常用方法包括 typeofinstanceofconstructortoString

变量定义

1
2
3
4
5
6
7
8
9
let undefinedV
let boolV = true
let numV = 9527
let strV = '9527'
let symbolV = Symbol('9527')
let nullV = null
let arrV = [9, 5, 2, 7]
let objV = new Object()
let funcV = function () {}

typeof

typeof 用于确定值的原始类型

1
2
3
4
5
6
7
8
9
10
11
12
13
console.log(typeof undefinedV) // undefined
console.log(typeof boolV) // boolean
console.log(typeof numV) // number
console.log(typeof strV) // string
console.log(typeof symbolV) // symbol
console.log(typeof nullV) // object
console.log(typeof arrV) // object
console.log(typeof objV) // object
console.log(typeof funcV) // function

class Parent {}
class Child extends Parent {}
let child = new Child()

typeof 对原始类型变量以及 function 都能够正常判断,但是对于引用类型一律视作 Object,因此不能用来判断引用类型。

值得注意的是,typeof 对于 null 类型变量也会输出 'object',这是因为 JavaScript 最初使用低位存储变量类型信息,Object 类型变量的机器码标识低 3 位为 0,null 类型变量的机器码标识为全 0。typeof 进行类型判断时,直接根据机器码低位标识进行判断,导致二者识别结果重复(均为’000’),故使得 typeof null 输出为 'object'

因为这个 bug 遗留太久了,因此后续也就没再修复,以免影响太大。

instanceof

instanceof 用于确定对象(引用值)的具体类型。

1
2
3
4
5
6
console.log(arrV instanceof Array) // true
console.log(objV instanceof Object) // true
console.log(funcV instanceof Function) // true

console.log(child instanceof Child) // true
console.log(child instanceof Parent) // true
  • instanceof 对变量原型链上所有对象都会返回 true
  • instanceof 不能用于 nullundefined,会报错。
  • 使用 instanceof 检测任何引用值与 Object 构造函数都会返回 true,例如 arrV instanceof Object === true
  • 使用 instanceof 检测任何原始值都会返回 false,例如 boolV instanceof Object === false

constructor

1
2
3
4
5
6
7
console.log(boolV.constructor === Boolean) // true
console.log(numV.constructor === Number) // true
console.log(strV.constructor === String) // true
console.log(symbolV.constructor === Symbol) // true
console.log(arrV.constructor === Array) // true
console.log(objV.constructor === Object) // true
console.log(funcV.constructor === Function) // true
  • undefinednull 没有 constructor 属性,因此不能用这个方法判断他俩。
  • constructor 指向可以被改变,因此这个方法不安全。

toString

准确来说是 Object.prototype.toString.call(variable)

1
2
3
4
5
6
7
8
9
10
11
console.log(Object.prototype.toString.call(undefinedV)) // [object Undefined]
console.log(Object.prototype.toString.call(boolV)) // [object Boolean]
console.log(Object.prototype.toString.call(numV)) // [object Number]
console.log(Object.prototype.toString.call(strV)) // [object String]
console.log(Object.prototype.toString.call(symbolV)) // [object Symbol]
console.log(Object.prototype.toString.call(nullV)) // [object Null]
console.log(Object.prototype.toString.call(arrV)) // [object Array]
console.log(Object.prototype.toString.call(objV)) // [object Object]
console.log(Object.prototype.toString.call(funcV)) // [object Function]

console.log(Object.prototype.toString.call(child)) // [object Object]
  • toString 输出类的 [[Class]] 属性,即构造函数名,但它无法检测非原生构造函数的构造函数名。

总结

  • typeof 适合判断原始变量类型,不适合判断引用变量类型和 null
  • instanceof 适合判断引用变量的具体类型,不适合判断原始变量类型和 undefinednull
  • constructor 能够判断原始变量类型和引用变量类型,但不能用于 undefinednull,且不够安全。
  • toString 能够判断所有原始变量类型和引用变量类型,比较全面,但不能判断非原生引用变量类型。
  • 判断 undefined 可以用 typeoftoString;判断 null 可以用 toString;判断原生引用变量类型可以用 instanceofconstructortoString;判断非原生引用变量类型可以用 instanceof,但需注意其对于变量原型链上所有对象均会返回 true