Skip to content

JavaScript 数据类型判断

方案一:typeof 结合 instanceof

  1. typeof 判断数据的基础类型 typeof 只能判断除了 null 以外的基础类型和函数数据类型,如果用来判断 null 返回结果是 object(常见解释:null 被当作空对象指针)
js
// typeof 判断基础数据类型
console.log(typeof "123"); // string
console.log(typeof 123); // number
console.log(typeof true); // boolean
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(typeof Symbol(123)); // symbol

// typeof 判断引用数据类型
console.log(typeof function () {}); // function
console.log(typeof {}); // object
console.log(typeof []); // object
console.log(typeof new Date()); //object
console.log(typeof new RegExp("hello world")); // object
  1. instanceof 判断数据是否某个构造函数的实例 instanceof 判断除了 null 以外的引用类型;注意:null 不是 Object 的实例。
ts
// instanceof 判断引用数据类型
console.log({} instanceof Object); // true
console.log([] instanceof Array); // true
console.log(function () {} instanceof Function); // true
console.log(null instanceof Object); // false
console.log(new Date() instanceof Date); // true
console.log(new RegExp("hello world") instanceof RegExp); // true
console.log(new Date() instanceof Object); // true
console.log(new RegExp("hello world") instanceof Object); // true

方案二:精准判断

Object.prototype.toString.call(data) 精准判断

js
console.log(Object.prototype.toString.call("123")); // [object String]
console.log(Object.prototype.toString.call(123)); // [object Number]
console.log(Object.prototype.toString.call(true)); // [object Boolean]
console.log(Object.prototype.toString.call(undefined)); // [object Undefined]
console.log(Object.prototype.toString.call(null)); // [object Null]
console.log(Object.prototype.toString.call(Symbol())); // [object Symbol]
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(new Date())); // [object Date]
console.log(Object.prototype.toString.call(new RegExp("hello world"))); // [object RegExp]

// function getDataType(data) {
//    return Object.prototype.toString.call(data).slice(7, -1).toLowerCase();
// }

要点速览

shell
JS 判断数据类型有三种方式:typeof、instanceof、Object.prototype.toString.call。
第一种方式(只能判断基础类型):typeof 变量,可以判断除了 null 以外的基础类型,和引用类型中的函数类型
第二种方式(跨窗口失效,不能判断基础类型):变量 instanceof 构造函数,可以判断引用类型,不能判断基础类型,
第三种方式(最完美、最准确):对象原型上的方法,Object.prototype.toString.call(变量) 

# 所以封装 Object.prototype.toString.call(变量) 来判断数据类型最稳妥

# 常见判断
判断是否是数组:Array.isArray()、Object.prototype.toString.call(变量) 
判断是否是函数:typeof fn === 'function'、Object.prototype.toString.call(变量) 
判断是否是普通对象:Object.prototype.toString.call(变量)

拓展

shell
# 方式一: typeof 运算符
判断除了 null 以外的基础类型数据
typeof null === 'object'(历史 bug,永远不会修复)
数组、日期、正则、对象都返回 object,无法细分引用类型

# 方式二: instanceof 原型链判断
不能判断基本数据类型
原型可以手动修改,结果不稳定
跨窗口 / iframe 失效(Array 构造函数不是同一个)
所有对象都 instanceof Object true

# 方式三:Object.prototype.toString.call()(最完美、最准确)
Object.prototype.toString.call(变量)
Object.prototype.toString.call(data).slice(7, -1).toLowerCase();

# instanceof 原理
A instanceof B,沿着 A 的原型链 proto 逐层向上查找,判断B.prototype 是否在 A 的原型链上。
不是判断类型,是原型链关系检测。比较的是内存地址,不是字符串名字。
A.__proto__.__proto__... 直到 找到 B.prototype true 否则 false,B 是构造函数

# 为何instanceof 跨窗口 / 跨 iframe 失效(Array 构造函数不是同一个)
父Array.prototype !== iframeArray.prototype,原型链对上不同内存地址,instanceof 直接 false
也就是虽然都是 Array,但是地址不同,得到的结果是 false ,自然判断不准确