类型检测的 4 种武器与避坑指南:动态类型带来灵活,也暗藏风险。typeof
适合原始类型,instanceof
用于对象族谱,toString
破解所有伪装,Array.isArray
专治数组迷局。一文掌握核心原理与实战技巧,写出无懈可击的类型判断代码。
一、JavaScript 数据类型分类
在深入检测方法之前,先回顾 JavaScript 的数据类型:
1. 原始类型(Primitive Types)
number
:数字(包含NaN
和Infinity
)string
:字符串boolean
:布尔值undefined
:未定义null
:空值symbol
:符号(ES6+)bigint
:大整数(ES11+)
2. 对象类型(Object Types)
Object
:普通对象Array
:数组Function
:函数Date
:日期RegExp
:正则表达式- ...等特殊对象
二、四大检测方法详解
1. typeof
操作符
语法:
javascript
typeof variable
特点:
- 返回类型名称字符串
- 对原始类型判断友好
- 无法区分对象子类型
返回值表:
表达式 | 返回值 | 说明 |
---|---|---|
typeof 42 |
"number" | 包含 NaN 和 Infinity |
typeof "hello" |
"string" | |
typeof true |
"boolean" | |
typeof undefined |
"undefined" | |
typeof null |
"object" | 历史遗留问题 |
typeof Symbol() |
"symbol" | |
typeof 10n |
"bigint" | |
typeof {} |
"object" | |
typeof [] |
"object" | 无法区分数组和普通对象 |
typeof function(){} |
"function" | 特殊处理 |
示例:
javascript
console.log(typeof null); // "object" (经典陷阱)
console.log(typeof []); // "object"
console.log(typeof new Date()); // "object"
2. instanceof
操作符
语法:
javascript
variable instanceof Constructor
特点:
- 检测构造函数的
prototype
是否在对象的原型链上 - 适用于对象类型检测
- 无法检测原始类型
示例:
javascript
console.log([] instanceof Array); // true
console.log({} instanceof Object); // true
console.log("" instanceof String); // false (原始类型不生效)
function Car() {}
const myCar = new Car();
console.log(myCar instanceof Car); // true
局限性:
javascript
// 跨 frame 检测失效
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[0].Array;
const arr = new xArray();
console.log(arr instanceof Array); // false
3. Object.prototype.toString.call()
语法:
javascript
Object.prototype.toString.call(value)
特点:
- 最精准的检测方式
- 返回
[object Type]
格式字符串 - 可识别所有内置对象类型
返回值示例:
javascript
console.log(Object.prototype.toString.call(42)); // [object Number]
console.log(Object.prototype.toString.call(null)); // [object Null]
console.log(Object.prototype.toString.call([])); // [object Array]
console.log(Object.prototype.toString.call(/regex/));// [object RegExp]
封装工具函数:
javascript
function getType(obj) {
return Object.prototype.toString.call(obj)
.slice(8, -1)
.toLowerCase();
}
console.log(getType([])); // "array"
console.log(getType(null)); // "null"
4. Array.isArray()
语法:
javascript
Array.isArray(value)
特点:
- ES5 新增方法
- 专门用于检测数组
- 解决
instanceof
的跨 frame 问题
示例:
javascript
console.log(Array.isArray([])); // true
console.log(Array.isArray({})); // false
// 跨 frame 场景
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[0].Array;
const arr = new xArray();
console.log(Array.isArray(arr)); // true
Polyfill(兼容旧浏览器):
javascript
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
"震惊!只有10%的开发者知道最准确的类型检测方法..."
三、方法对比与选择指南
四、最佳实践建议
1. 组合方案
javascript
function checkType(value) {
// 处理 null
if (value === null) return 'null';
// 处理原始类型(除 null)
const type = typeof value;
if (type !== 'object') return type;
// 处理对象类型
return Object.prototype.toString.call(value)
.slice(8, -1)
.toLowerCase();
}
2. 类型检测对照表
检测目标 | 推荐方法 | 示例代码 |
---|---|---|
原始类型 | typeof |
typeof variable === 'string' |
null |
全等判断 | variable === null |
数组 | Array.isArray() |
Array.isArray(variable) |
自定义对象 | instanceof |
variable instanceof MyClass |
通用对象类型 | Object.prototype.toString |
toString.call(var) === '[object Date]' |
3. 现代开发建议
- 使用 TypeScript 获得编译时类型检查
- 结合 ESLint 规则限制危险的类型转换
- 单元测试中增加类型断言
五、总结
JavaScript 的类型系统看似简单,实则暗藏玄机。合理选择检测方法:
- 简单场景 :优先使用
typeof
和Array.isArray()
- 精准判断 :选择
Object.prototype.toString
- 面向对象 :使用
instanceof
检测构造函数关系
记住:没有一种方法能解决所有问题,理解原理才能灵活应对不同场景!