JavaScript 中常见的几种数据类型:
基本数据类型:String, Number, Boolean, null, undefined, Symbol、BigInt
引用数据类型:Obejct、Function
1. typeof
console.log(typeof('')) // string
console.log(typeof(1)) // number
console.log(typeof(true)) // boolean
console.log(typeof(undefined)) // undefined
console.log(typeof(null)) // object
console.log(typeof([])) // object
console.log(typeof(new Function())) // function
console.log(typeof(new Date())) // object
console.log(typeof(new RegExp())) //object
在 JavaScript 里 使用 typeof 来判断数据类型,只能区分这些类型,即 “ number ” , “ string ” , “ undefined ” , “ boolean ” , “ object ”, “function”。
没法准确区分数组、函数、对象
2. instanceof
console.log(1 instanceof Number) // false
console.log(true instanceof Boolean) // false
console.log('str' instanceof String) // false
console.log([] instanceof Array) // true
console.log(function(){} instanceof Function) // true
console.log({} instanceof Object) // true
// 比较特殊
console.log(undefined instanceof Undefined) // 会报错,说未定义
console.log(null instanceof Null) // 会报错,说未定义
从上述结果可以看出:只有引用数据类型(Array,Function,Object)被精准判断,其他(数值Number,布尔值Boolean,字符串String)字面值不能被instanceof精准判断。
让我们看看MDN上的解释:instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。其意思就是判断对象是否是某一数据类型(如Array)的实例,重点关注一下是判断一个对象是否是数据类型的实例。在这里字面量值,1, true ,'str’不是实例,所以判断值为false。
console.log(new Number(1) instanceof Number) // true
console.log(new Boolean(true) instanceof Boolean) // true
console.log(new String('str') instanceof String) // true
3. constructor
console.log((1).constructor === Number) // ture
console.log((true).constructor === Boolean) // ture
console.log(('str').constructor === String) // ture
console.log(([]).constructor === Array) // ture
console.log((function(){}).constructor === Function) // ture
console.log(({}.constructor === Object)) // ture
用costructor来判断类型看起来是完美的,但是,如果我创建一个对象,更改它的原型,这种方式就变得不可靠了。
function Fn(){}
Fn.prototype = new Array()
var f = new Fn()
console.log(f.constructor === Fn) // false
console.log(f.constructor === Array) // true
4. Object.prototype.toString
// 可以是call,也可以是apply,这里以call
console.log(Object.prototype.toString.call(10)) // [object Number]
console.log(Object.prototype.toString.call('90')) // [object String]
console.log(Object.prototype.toString.call(undefined)) // [object Undefined]
console.log(Object.prototype.toString.call(true)) // [object Boolean]
console.log(Object.prototype.toString.call({})) // [object Object]
console.log(Object.prototype.toString.call([])) // [object Array]
console.log(Object.prototype.toString.call(function(){})) // [object Function]
console.log(Object.prototype.toString.call(this)) // [object Window]
在 Object.prototype.toString 方法被调用时,会执行下面的操作步骤(了解):
- 获取this对象的 [[Class]] 属性的值。
- 计算出三个字符串 "[object " , 第一步的操作结果 Result(1) , 以及 “]” 连接后的新字符串。
- 返回第二步的操作结果Result(2)。
[[Class]] 是一个内部属性,所有的对象(原生对象和宿主对象)都拥有该属性。
在规范中,[[Class]]是这么定义的:一个字符串值,表明了该对象的类型(重点)
总结
typeof 可以用来简单判断数据类型
Object.prototype.toString.call() 可以用于准确判断数据类型