一、JavaScript 数据类型分类
首先明确 JS 的 7 种基本数据类型和 1 种引用数据类型:
- 基本类型:
Number、String、Boolean、Null、Undefined、Symbol(ES6+)、BigInt(ES10+)。 - 引用类型:
Object(包括Array、Function、Date、RegExp等,本质都是对象的子类型)。
二、常用判断方法及适用场景
不同方法有各自的优缺点,需根据场景选择:
1. typeof 运算符(基础但有局限)
- 语法:
typeof 变量 - 返回值:字符串(如
'number'、'string'、'object'等)。 - 适用场景:判断基本类型(除
Null外)和Function。
typeof 123; // 'number'(正确)
typeof 'abc'; // 'string'(正确)
typeof true; // 'boolean'(正确)
typeof undefined; // 'undefined'(正确)
typeof Symbol(); // 'symbol'(正确)
typeof 123n; // 'bigint'(正确)
typeof function(){};// 'function'(正确,特殊处理)
// 局限性
typeof null; // 'object'(历史bug,错误)
typeof []; // 'object'(引用类型均返回'object')
typeof {}; // 'object'
2. instanceof 运算符(判断引用类型)
- 原理:检测构造函数的
prototype是否在实例对象的原型链上。 - 适用场景:判断具体的引用类型(如
Array、Date)。
[] instanceof Array; // true(正确)
{} instanceof Object; // true(正确)
new Date() instanceof Date; // true(正确)
function(){} instanceof Function; // true(正确)
// 局限性
[] instanceof Object; // true(数组也是对象,可能误判)
'abc' instanceof String; // false(基本类型字符串不适用)
// 跨iframe场景失效(原型链不同)
3. Object.prototype.toString.call()(最准确的通用方法)
- 原理:调用对象的
toString方法,返回[object 类型]格式的字符串,不受原型链影响。 - 适用场景:所有数据类型(包括
Null、Array等特殊类型)。
Object.prototype.toString.call(123); // '[object Number]'
Object.prototype.toString.call('abc'); // '[object String]'
Object.prototype.toString.call(true); // '[object Boolean]'
Object.prototype.toString.call(null); // '[object Null]'(正确)
Object.prototype.toString.call(undefined); // '[object Undefined]'(正确)
Object.prototype.toString.call([]); // '[object Array]'(正确)
Object.prototype.toString.call({}); // '[object Object]'
Object.prototype.toString.call(Symbol()); // '[object Symbol]'
Object.prototype.toString.call(123n); // '[object BigInt]'
Object.prototype.toString.call(new Date()); // '[object Date]'
4. 特殊类型的针对性判断
-
Array:除了instanceof和toString,还可用Array.isArray()(ES5+,最推荐):Array.isArray([]); // true Array.isArray({}); // false -
Null:需单独判断(因typeof null有 bug):const a = null; a === null; // true(唯一可靠方法) -
NaN:NaN是唯一不等于自身的值,需用Number.isNaN():Number.isNaN(NaN); // true Number.isNaN('abc' / 1); // true(运算结果为NaN)
1. 问:typeof null 为什么返回 'object'?
- 答:这是 JS 最初实现的历史遗留 bug。早期 JS 用 32 位标记值表示数据类型,
null的标记位与对象相同(均为 0),导致typeof误判。该 bug 因兼容性问题未修复,需用a === null单独判断null。
2. 问:如何准确判断一个变量是数组还是对象?
- 答:
- 用
Array.isArray()直接判断数组:Array.isArray(arr)→ 简洁可靠; - 或用
Object.prototype.toString.call():function isArrayOrObject(value) { const type = Object.prototype.toString.call(value); if (type === '[object Array]') return 'array'; if (type === '[object Object]') return 'object'; return 'other'; }
- 用
3. 问:instanceof 和 typeof 的核心区别是什么?
- 答:
typeof基于数据类型的底层标记判断,适合基本类型,但无法区分引用类型;instanceof基于原型链判断,适合区分具体的引用类型(如Date、Array),但不适合基本类型,且受原型链修改影响。
四、总结
“判断 JS 数据类型需根据场景选择方法:
- 基本类型(除
null)用typeof; - 引用类型(如
Array、Date)用Object.prototype.toString.call()或instanceof; - 数组优先用
Array.isArray(),null必须用=== null判断。
实际开发中,Object.prototype.toString.call() 是最通用的方法,能覆盖所有类型;而针对数组、NaN 等特殊类型,有更简洁的专用 API(如 Array.isArray、Number.isNaN)。”