JS 的数据类型检测是一道经典的八股文面试题。相信大家都能条件反射的回答出 4 种办法:typeof、constructor、instanceof 和 Object.prototype.toString,而且对它们各自的优缺点也是张口就来。

本文对这些办法做了简单归纳,一同又弥补了其他 5 种和数据类型检测有关的办法,供诸君食用。

typeof:检测基础数据类型和函数很好用

typeof 应该是我学习到的第一个 JS 的办法,也是运用频率最高的一个用来检测数据类型的办法。

它能精确判别出的数据类型有:Number,String,Boolean,Undefined,Symbol,BigInt,Function。

它的缺点便是不能精确判别 null 的类型,而是回来 “object”。对于数组,日期,一般目标等数据,统一回来 “object”。

所以在判别基本数据类型(除了 null)和函数类型时,都会运用它。

constructor:回来实例目标的结构函数

学习 JS 到面向目标的阶段时,会学到 JS 的原型链和原型目标,会学到经过 new 一个结构函数,来创建实例目标。

结构函数的原型目标上会有一个 constructor 特点,指向了结构函数自身,所以实例目标经过原型链访问 constructor 特点,就能找到自己的结构函数,也便是自己的类型了。

它的本意是用来标识自己的结构函数,却临时拉来当壮丁,用来判别数据类型,当然也存在一定的危险:

  • null,undefined 没有结构函数,自然也就访问不到该特点,因而不能运用此特点来判别
  • constructor 能够被改写,所以不一定精确

来看几个比方:

console.log((1).constructor === Number) // trueconsole.log([1, 2, 3].constructor === Array) // trueconsole.log(undefined.constructor === Array) // 报错

在平时写代码时,基本上不会用它来做数据类型的检测。

instanceof:沿着原型链去找

它和 constructor 一样,也是临时拉来当壮丁。它的作用是检测实例目标是不是归于某个结构函数,能够用来做数据类型的检测。

术业有专攻,所以它也有缺点:

  • 不能检测基本数据类型
  • 原型链或许被修改,导致检测结果不精确
  • 只需能在原型链上找到结构函数,就回来 true,所以类型或许不精确

来看几个比方:

console.log(1 instanceof Number) // falseconsole.log([] instanceof Array) // trueconsole.log([] instanceof Object) // true

实践中 instanceof 也很少用。

Object.prototype.toString:是个大拿

看姓名它是用来将一个值转为字符串的,但其实并不是,它是一个专门检测数据类型的办法。

它回来的值是一个形如 [object Object] 的字符串,比方:

console.log(toString.call('123'))    // [object String]
console.log(toString.call(null))     // [object Null]
console.log(toString.call(true))     // [object Boolean]
console.log(toString.call({}))      // [object Object]
console.log(toString.call([]))      // [object Array]
console.log(toString.call(function(){})) // [object Function]
console.log(toString.call(new Map))   // [object Map]
console.log(toString.call(new WeakSet)) // [object WeakSet]

通常会编写一个函数,对回来的字符串从第8位做一个截取,截取到倒数第一位,再去做类型比较。

Symbol.toStringTag:自定义类型

上面的 Object.prototype.toString 办法,之所以对不同的数据类型,回来不同的标识字符串,便是因为 Symbol.toStringTag

Symbol.toStringTag 是一个内置符号特点,它的值是一个字符串,用于表示一个目标的默认描述,也便是调用 Object.prototype.toString 会回来的内容,比方:

let obj = {}
obj[Symbol.toStringTag] = 'ABC'
console.log(Object.prototype.toString.call(obj)) // [object ABC]

对于自定义目标,调用上面的办法,都只会回来 [object Object]。此刻就能够运用 Symbol.toStringTag 来指定一个确认的类型了,比方:

class Person{
  get[Symbol.toStringTag](){
    return 'Person'
   }
}
let person = new Person()
​
console.log(Object.prototype.toString.call(person)) // [object Person]

Object.prototype.isPrototypeOf:和 instanceof 相似

isPrototypeOf 和 instanceof 相似,都是根据原型链和原型目标去做判别的。它用来检查一个目标是否存在于另一个目标的原型链上。

function Person() {
  
}
​
let person = new Person()
​
console.log(Person.prototype.isPrototypeOf(person))

Array.isArray:专业检测数组三十年

起初以为它是 ES6 供给的新办法,后来得知其实归于 ES 5.1 规范。

看姓名就知道,它是专门用于检测数组类型的,该办法的命名实在要言不烦。

Array.isArray([]) // true

Number.isNaN

这个办法便是真的归于 ES6 规范了。

咱们知道,JS 中有一个特殊的“数字” NaN,表示 not a number,不是一个数字,但它却归归于数字类型:

console.log(typeof NaN) // 'number'

NaN 用于表示不是一个数字,它不等于任何值,包括它本身。在 ES6 之前,windows 目标供给了一个大局办法 isNaN,用于判别一个数字是不是 NaN:

isNaN(10) // false
isNaN('abc') // true
isNaN(NaN) // true

能够发现,isNaN 对于字符串的检测结果也是 NaN。但这其实并不谨慎,它对要判别的数据做了一个隐式类型转换,先转为数字再进行判别。而NaN 的检测应该仅限于数字类型,所以 ES6 供给了 Number.isNaN 办法:

Number.isNaN(NaN) // true
Number.isNaN('123') // false

它能判别一个值是否严厉等于NaN。

等比较:与固定值进行比较

直接经过与一个特定的值进行比较,然后判别数据的类型,比方:

let value = null
console.log(value === null) // true// 一同判别一个值是 undefined 或者 null
let value
console.log(value == null) // true

总结

本文整理了 JS 中常用的判别数据类型的办法,其中 typeof 和 Object.prototype.toString 运用场景是最多的,对一些特殊的数据类型,比方 null,NaN,自定义类型,能够挑选其他的方法去进行判别,做到灵活运用。

关于数据类型的检测, 假如你还有其他的方法,欢迎谈论弥补,一同学习。

本文正在参与「金石计划 . 瓜分6万现金大奖」