所属板块:1. 数据类型与内存机制
记录日期:2026-03-xx
更新:根据实际使用补充
1. 四种常见类型检测方式对比
| 方法 | 适用场景 | 主要优点 | 主要缺陷 / 注意点 | 推荐指数 |
|---|---|---|---|---|
| typeof | 判断基本类型(除 null 外) | 简单、速度快 | typeof null === 'object'(历史遗留 Bug);无法区分 Object / Array / null 等 | ★★☆☆☆ |
| instanceof | 判断引用类型是否属于某个构造函数 | 直观,结合原型链 | 跨 iframe / 不同上下文失效;基本类型直接报错;可被原型链篡改 | ★★★☆☆ |
| constructor | 判断对象的构造函数 | 直接访问 constructor 属性 | 容易被修改(obj.constructor = xxx);null/undefined 无此属性 | ★☆☆☆☆ |
| Object.prototype.toString.call() | 几乎所有内置类型的精确判断(终极方案) | 最可靠、防篡改、区分所有内置对象 | 写法稍长;自定义类型返回 [object Object] | ★★★★★ |
记住:日常开发中,优先用 Object.prototype.toString.call() 处理不确定来源的数据。
2. typeof 的常见表现(包含坑)
js
console.log(typeof 123); // "number"
console.log(typeof "abc"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof Symbol()); // "symbol"
console.log(typeof 123n); // "bigint"
console.log(typeof {}); // "object"
console.log(typeof []); // "object" ← 无法区分数组
console.log(typeof null); // "object" ← 经典历史 Bug
console.log(typeof function(){}); // "function" ← 唯一能区分函数的
注意:typeof 无法区分 null 和对象,也分不清普通对象与数组/Date/RegExp 等。
3. instanceof 的原理与局限
原理:顺着对象的 __proto__ 链向上找,直到找到指定构造函数的 prototype。
js
[] instanceof Array; // true
{} instanceof Object; // true
new Date() instanceof Date; // true
// 但有坑:
[] instanceof Object; // true(因为 Array.prototype.__proto__ 指向 Object.prototype)
"str" instanceof String; // false(基本类型不是对象实例)
跨上下文问题示例(iframe 中常见):
js
// 主页面
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const iframeArray = iframe.contentWindow.Array;
console.log([] instanceof iframeArray); // false,即使看起来是数组
4. Object.prototype.toString.call() 用法(最推荐)
这是最可靠的方式,返回格式统一为 [object XXX]。
js
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(undefined); // "[object Undefined]"
Object.prototype.toString.call(null); // "[object Null]" ← 正确区分 null
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]" ← 能区分数组
Object.prototype.toString.call(new Date()); // "[object Date]"
Object.prototype.toString.call(/abc/); // "[object RegExp]"
Object.prototype.toString.call(new Map()); // "[object Map]"
Object.prototype.toString.call(function(){}); // "[object Function]"
封装一个常用工具函数(自己项目里可以直接复制):
js
function getType(value) {
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
}
console.log(getType(null)); // "null"
console.log(getType([])); // "array"
console.log(getType(new Map())); // "map"
5. 小结 & 实际使用建议
- 只需要区分基本类型 → 用 typeof 够了(但记得 null 的坑)
- 需要精确区分内置对象(如 Array/Date/RegExp/Map 等)→ 必须用 Object.prototype.toString.call()
- instanceof 适合判断"是否是某个类的实例"(如自定义类、Error),但不适合通用类型检测
- 永远不要依赖 constructor(太容易被改)
下一篇文章会记录隐式类型转换的规则和经典例子([] == ![] 之类)。
返回总目录:戳这里