如何区分 typeof 数组与普通对象,准确判断数据类型?
- 内容介绍
- 相关推荐
本文共计668个文字,预计阅读时间需要3分钟。
`typeof` 对数组和普通对象都返回 `object`,这不是 bug,而是 JavaScript 语言设计的底层事实:
为什么 typeof 不能用于识别数组
因为 typeof 只能识别基本类型("string"、"number"、"boolean"、"undefined"、"symbol"、"bigint"、"function")和统一的 "object"(含 null、数组、正则、日期等)。它不检查构造方式或内部结构。
typeof [] === "object"typeof {} === "object"-
typeof null === "object"(历史遗留错误,但已成标准)
推荐的精准识别方式
优先使用语义明确、跨环境稳定、不可伪造的方法:
- Array.isArray(value) —— 最佳实践。ES5+ 原生方法,不依赖原型链,iframe 安全,返回布尔值,无副作用。
-
Object.prototype.toString.call(value) === "[object Array]" —— 通用性强,适用于所有内置类型(如
"[object Date]"、"[object RegExp]"),且不受constructor或__proto__修改影响。
慎用或需注意的方法
这些方法在特定场景下可能失效:
-
value instanceof Array:在多 iframe 环境中会失败,因不同上下文的Array构造函数不相等。 -
value.constructor === Array:constructor属性可被显式覆盖,不可信。 -
value.__proto__ === Array.prototype或Object.getPrototypeOf(value) === Array.prototype:原型可被Object.setPrototypeOf()修改,失去判断依据。 -
Array.prototype.isPrototypeOf(value):虽比instanceof更底层,但仍受原型篡改影响,且对稀疏数组或 Proxy 包裹数组可能行为异常。
对象的识别建议
若需确认一个值是“纯粹的普通对象”(即非数组、非 null、非函数、非 Date 等),可组合判断:
- 先排除数组:
!Array.isArray(value) - 再确认是对象且非 null:
value !== null && typeof value === "object" - 最后验证构造来源(较稳妥):
Object.prototype.toString.call(value) === "[object Object]"
注意:{}、new Object()、Object.create({}) 都满足上述条件;而 Object.create(null) 虽无原型,但 toString.call 仍返回 "[object Object]",属于预期行为。
本文共计668个文字,预计阅读时间需要3分钟。
`typeof` 对数组和普通对象都返回 `object`,这不是 bug,而是 JavaScript 语言设计的底层事实:
为什么 typeof 不能用于识别数组
因为 typeof 只能识别基本类型("string"、"number"、"boolean"、"undefined"、"symbol"、"bigint"、"function")和统一的 "object"(含 null、数组、正则、日期等)。它不检查构造方式或内部结构。
typeof [] === "object"typeof {} === "object"-
typeof null === "object"(历史遗留错误,但已成标准)
推荐的精准识别方式
优先使用语义明确、跨环境稳定、不可伪造的方法:
- Array.isArray(value) —— 最佳实践。ES5+ 原生方法,不依赖原型链,iframe 安全,返回布尔值,无副作用。
-
Object.prototype.toString.call(value) === "[object Array]" —— 通用性强,适用于所有内置类型(如
"[object Date]"、"[object RegExp]"),且不受constructor或__proto__修改影响。
慎用或需注意的方法
这些方法在特定场景下可能失效:
-
value instanceof Array:在多 iframe 环境中会失败,因不同上下文的Array构造函数不相等。 -
value.constructor === Array:constructor属性可被显式覆盖,不可信。 -
value.__proto__ === Array.prototype或Object.getPrototypeOf(value) === Array.prototype:原型可被Object.setPrototypeOf()修改,失去判断依据。 -
Array.prototype.isPrototypeOf(value):虽比instanceof更底层,但仍受原型篡改影响,且对稀疏数组或 Proxy 包裹数组可能行为异常。
对象的识别建议
若需确认一个值是“纯粹的普通对象”(即非数组、非 null、非函数、非 Date 等),可组合判断:
- 先排除数组:
!Array.isArray(value) - 再确认是对象且非 null:
value !== null && typeof value === "object" - 最后验证构造来源(较稳妥):
Object.prototype.toString.call(value) === "[object Object]"
注意:{}、new Object()、Object.create({}) 都满足上述条件;而 Object.create(null) 虽无原型,但 toString.call 仍返回 "[object Object]",属于预期行为。

