Primitive → Object
核心机制:自动装箱 (Auto-boxing)
当对一个原始值(string, number, boolean, symbol, bigint)尝试访问其属性或调用其方法时,JavaScript 会在后台进行如下操作:
- 创建一个临时的包装器对象(Wrapper Object)。
string->new String()number->new Number()boolean->new Boolean()- 等等…
- 在该临时对象上执行属性/方法的访问或调用。
- 销毁这个临时对象。
这个过程是隐式的,使得原始值可以像对象一样使用。
// 示例let name = "chat-gpt"; // 原始值 stringlet upperName = name.toUpperCase(); // .toUpperCase() 触发了自动装箱
// 后台大致流程:// 1. let temp = new String(name);// 2. let upperName = temp.toUpperCase();// 3. temp = null; // 销毁临时对象不可转换的原始值
null和undefined没有对应的包装器对象。- 对它们进行属性访问会直接抛出
TypeError。
null.prop; // TypeError: Cannot read properties of nullundefined.prop; // TypeError: Cannot read properties of undefined显式创建包装器对象
你也可以手动使用构造函数创建包装器对象。但这通常是不推荐的做法,因为它会创建一个对象而不是原始值,可能导致混淆。
let numPrimitive = 123;let numObject = new Number(123);
typeof numPrimitive; // "number"typeof numObject; // "object"
numPrimitive === numObject; // false
if (new Boolean(false)) { console.log("This runs"); // 会运行,因为对象总是 "truthy"}Object → Primitive
转换简表
| 上下文 | hint | 调用顺序 | 说明 |
|---|---|---|---|
| 转字符串 | ”string” | toString() → valueOf() | 常见于 String(obj)、模板字符串 ${obj} |
| 转数字 | ”number” | valueOf() → toString() | 常见于 Number(obj)、+obj、数学运算 |
| 默认情况 | ”default” | 通常按 “number” 规则;Date 特例 按 “string” 规则 | 常见于 obj == “foo”、obj + “bar” |
调用机制细节
-
valueOf()
-
设计目标:返回对象的数值表示。
-
如果返回原始值(number、string、boolean、symbol、bigint、null、undefined),则直接使用。
-
否则忽略结果继续。
-
-
toString()
-
设计目标:返回对象的字符串表示。
-
如果返回原始值,则直接使用。
-
否则继续。
-
-
自定义 Symbol.toPrimitive(hint)
-
优先级最高。
-
如果对象定义了 obj[Symbol.toPrimitive],那么不管 hint 是 “string” / “number” / “default”,都会直接调用这个方法。
-
返回必须是原始值,否则抛 TypeError。
-
let obj = { [Symbol.toPrimitive](hint) { if (hint === "string") return "str"; if (hint === "number") return 123; return "default"; }};console.log(String(obj)); // "str"console.log(+obj); // 123console.log(obj + ""); // "default"优先级
-
如果对象定义了 Symbol.toPrimitive (hint) ,这个方法优先。
-
否则走上面表格里的顺序。
-
如果都不能返回原始值 → 抛 TypeError。