Skip to content

检测数据类型

在 JavaScript 中常见的类型检查手段主要有:typeof、instanceof、constructor 和 toString 几种

1、typeof 检测

只能检测除 null 外的基本数据类型和是否是函数类型("function")

5 种基本类型 + 1(ES6 添加的基本类型) + 1 种复杂类型
  • Undefined、Null、String、Boolean、Number 、 Symbol
  • Object
js
console.log(typeof undefined === "undefined") //true
console.log(typeof null === "object") //永远的bug  null的类型为object
console.log(typeof "str" === "string") //true
console.log(typeof true === "boolean") //true
console.log(typeof 1 === "number") //true
console.log(typeof Symbol() === "symbol") //true
console.log(typeof function () {} === "function") //true
console.log(typeof [] === "object") //true
console.log(typeof new Date() === "object") //true
console.log(typeof new RegExp() === "object") //true

2、instanceof

检测引用数据类型,通过判断某个对象的原型链是否包含某个构造函数的 prototype 属性

js
function Fun1() {}
var fun1 = new Fun1()
console.log(fun1 instanceof Fun1) // true

console.log([] instanceof Array) //true
console.log(new Date() instanceof Date) //true
console.log(/\d+/ instanceof RegExp) //true
console.log({} instanceof Object) //true

var num1 = 1
var num2 = new Number(1)
console.log(num1 instanceof Number) //false
console.log(num2 instanceof Number) //true
console.log(num1)
console.log(num2) //Number {  __proto__ : Number}

问题:

  1. 不能检测基本数据类型
  2. 跨 iframe 检测会出现问题
ts
var iframe = document.createElement("iframe")

document.body.appendChild(iframe)
// 在获取iframe中的Array
IfameArray = window.frames[window.frames.length - 1].Array

var ifarr = new IfameArray(1, 2, 3) // [1,2,3]
Array.isArray(ifarr) // true
ifarr instanceof Array // false

instanceof 是通过遍历对象原型链上是否存在对应的构造函数。 但是 iframe 是创建一个独立的环境 所以 IfameArray !== ParentIframeArray

3、constructor

可以检测除了 null 和 undefined 外的数据类型

js
function Fun1() {}
var fun1 = new Fun1()
console.log(fun1.constructor === Fun1) // true

console.log("str".constructor === String) //true
console.log(new String("123").constructor === String) //true
console.log(true.constructor === Boolean) //true
// console.log(1.constructor === Number)  //报错  1没有constructor
// console.log(undefined.constructor === Undefined)  // 报错  undefined没有constructor
// console.log(null.constructor === Null)  // 报错  null没有constructor
console.log([].constructor === Array) //true
console.log(new Date().constructor === Date) //true
console.log(/\d+/.constructor === RegExp) //true
  1. 不能检测 null 和 undefined
  2. 跨 iframe 检测会出现问题

4、toString

js
function Fun1() {}
var fun1 = new Fun1()
console.log(Object.prototype.toString.call(1)) //[object Number]
console.log(Object.prototype.toString.call("string")) //[object String]
console.log(Object.prototype.toString.call(true)) //[object Boolean]
console.log(Object.prototype.toString.call(null)) //[object Null]
console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
console.log(Object.prototype.toString.call(Symbol())) //[object Symbol]
console.log(Object.prototype.toString.call([])) //[object Array]
console.log(Object.prototype.toString.call(new Date())) //[object Date]
console.log(Object.prototype.toString.call(/\d+/)) //[object RegExp]
console.log(Object.prototype.toString.call(fun1)) //[object Object]
console.log(Object.prototype.toString.call(function () {})) //[object Function]

比较常用的检查方法

js
// 自定义数据类型检测方法
;(function (golbal) {
  var utils = golbal.utils || {}
  var DATE_TYPE = [
    "Undefined",
    "Null",
    "String",
    "Boolean",
    "Number",
    "Symbol",
    "Object",
    "Function",
    "Array",
    "Date",
    "RegExp",
  ]

  function getDateType(date) {
    return Object.prototype.toString.call(date).slice(8, -1)
  }

  for (var i = DATE_TYPE.length - 1; i >= 0; i--) {
    var type = DATE_TYPE[i]
    utils["is" + type] = (function (type) {
      return function (date) {
        return getDateType(date) === type
      }
    })(type)
  }
  golbal.utils = utils
})(window)

console.log(utils.isArray([]))