JavaScript中原始值存栈、直接存储数据,引用值存堆、变量存地址;typeof可初筛但null误报"object",Object.prototype.toString.call()最精准识别所有类型。

直接看变量的底层行为和类型标识,而不是只凭外观或经验判断。原始值是固定大小、直接存栈里的简单数据;引用值是存堆里的对象,变量里只放地址。
用 typeof 快速初筛,但必须处理 null
typeof 对大多数原始类型返回准确字符串:"string"、"number"、"boolean"、"undefined"、"symbol"、"bigint",这些全是原始值。
遇到 "function" 是引用类型(函数本质是 Function 对象);
遇到 "object" 不能直接认定——它可能是 {}、[]、new Date(),也可能是 null(这是历史 bug)。
所以安全写法是:
-
typeof val === 'object' && val !== null→ 大概率是引用类型(含数组、对象、日期等) -
typeof val === 'function'→ 明确是引用类型 -
typeof val === 'object' && val === null→ 原始值(null 是唯一被 typeof 误判为 "object" 的原始值)
用 Object.prototype.toString.call() 精准识别所有类型
这是最可靠的方法,能区分所有内置类型,包括容易混淆的 Array、Date、RegExp、Map 等:
-
Object.prototype.toString.call([])→ "[object Array]" -
Object.prototype.toString.call(new Date())→ "[object Date]" -
Object.prototype.toString.call(null)→ "[object Null]" -
Object.prototype.toString.call(undefined)→ "[object Undefined]" -
Object.prototype.toString.call(42)→ "[object Number]"(注意:包装对象才走这里,字面量 42 的 typeof 才是 "number")
只要结果不是 "[object String]"、"[object Number]"、"[object Boolean]"、"[object Undefined]"、"[object Null]"、"[object Symbol]"、"[object BigInt]",就属于引用类型。
按行为特征辅助验证
原始值赋值是复制值本身,修改不影响原变量;引用值赋值是复制地址,修改会影响所有指向同一堆内存的变量:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
-
let a = {x: 1}; let b = a; b.x = 2;→a.x也会变成 2 -
let x = 10; let y = x; y = 20;→x仍是 10
这个特性不能用于自动判断类型,但可帮助你理解为什么某些“看起来像对象”的值(比如字符串字面量)仍是原始值——它们没有引用共享行为。
别依赖 instanceof 或 constructor
instanceof 在跨 iframe 或不同全局环境时会失效(因为构造函数不一致);constructor 可被篡改,不可靠。例如:
-
[] instanceof Array在当前窗口为 true,但在另一个 iframe 中可能为 false -
(function(){}).constructor = String; (function(){}).constructor === String→ true,但显然不是字符串
除非你明确知道运行上下文且只检查已知构造器(如自定义类),否则不建议作为类型判断主手段。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










