skip to content
月与羽

JavaScript Object

/ 3 min read

Primitive → Object

核心机制:自动装箱 (Auto-boxing)

当对一个原始值(string, number, boolean, symbol, bigint)尝试访问其属性或调用其方法时,JavaScript 会在后台进行如下操作:

  1. 创建一个临时的包装器对象(Wrapper Object)。
    • string -> new String()
    • number -> new Number()
    • boolean -> new Boolean()
    • 等等…
  2. 在该临时对象上执行属性/方法的访问或调用。
  3. 销毁这个临时对象。

这个过程是隐式的,使得原始值可以像对象一样使用。

// 示例
let name = "chat-gpt"; // 原始值 string
let upperName = name.toUpperCase(); // .toUpperCase() 触发了自动装箱
// 后台大致流程:
// 1. let temp = new String(name);
// 2. let upperName = temp.toUpperCase();
// 3. temp = null; // 销毁临时对象

不可转换的原始值

  • nullundefined 没有对应的包装器对象。
  • 对它们进行属性访问会直接抛出 TypeError
null.prop; // TypeError: Cannot read properties of null
undefined.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”

调用机制细节

  1. valueOf()

    • 设计目标:返回对象的数值表示

    • 如果返回原始值(number、string、boolean、symbol、bigint、null、undefined),则直接使用。

    • 否则忽略结果继续。

  2. toString()

    • 设计目标:返回对象的字符串表示

    • 如果返回原始值,则直接使用。

    • 否则继续。

  3. 自定义 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); // 123
console.log(obj + ""); // "default"

优先级

  1. 如果对象定义了 Symbol.toPrimitive (hint) ,这个方法优先。

  2. 否则走上面表格里的顺序。

  3. 如果都不能返回原始值 → 抛 TypeError。