在 JavaScript 中,当对象需要被转换为原始值(字符串、数字或布尔值)时,会遵循特定的转换规则。这种转换通常发生在以下情况:
alert(obj) 输出对象obj1 + obj2 进行对象相加Number(obj) 或 +obj 将对象转换为数字String(obj) 或将对象作为属性键时JavaScript 对象到原始值的转换遵循以下步骤:
Symbol.toPrimitive 方法(ES6新增)Symbol.toPrimitive,则检查 valueOf() 方法valueOf() 不存在或返回非原始值,则检查 toString() 方法alert(obj);
// 等价于
alert(String(obj));
转换顺序:
obj[Symbol.toPrimitive]('string')(如果存在)obj.toString()(如果存在)obj.valueOf()(如果存在)Number(obj);
// 或数学运算(除了加法)
+obj;
转换顺序:
obj[Symbol.toPrimitive]('number')(如果存在)obj.valueOf()(如果存在)obj.toString()(如果存在)加法运算 + 或 == 比较时:
obj1 + obj2;
obj == primitive;
转换顺序与数字转换相同(默认 hint 会被视为 number)
ES6 引入了 Symbol.toPrimitive 方法,可以更精确地控制转换行为:
let user = {
name: "John",
money: 1000,
[Symbol.toPrimitive](hint) {
console.log(`hint: ${hint}`);
return hint == "string" ? `{name: "${this.name}"}` : this.money;
}
};
// 转换演示:
alert(user); // hint: string -> {name: "John"}
console.log(+user); // hint: number -> 1000
console.log(user + 500); // hint: default -> 1500
如果没有 Symbol.toPrimitive,JavaScript 会尝试 valueOf 和 toString:
let user = {
name: "John",
money: 1000,
// 对于 hint="string"
toString() {
return `{name: "${this.name}"}`;
},
// 对于 hint="number" 或 "default"
valueOf() {
return this.money;
}
};
alert(user); // toString -> {name: "John"}
console.log(+user); // valueOf -> 1000
console.log(user + 500); // valueOf -> 1500
所有对象都从 Object.prototype 继承了默认的 toString 和 valueOf 方法:
toString 默认返回 "[object Object]"valueOf 默认返回对象本身(不是原始值,因此通常会被忽略)对象到布尔值的转换很简单:所有对象(包括空对象)在布尔上下文中都是 true。
if ({} || new Date()) {
// 这里的代码总会执行
}
| 场景 | 转换 hint | 方法调用顺序 |
|---|---|---|
String(obj) |
"string" | Symbol.toPrimitive → toString → valueOf |
Number(obj) 或 +obj |
"number" | Symbol.toPrimitive → valueOf → toString |
obj + obj 或 obj == value |
"default" | Symbol.toPrimitive → valueOf → toString |
| 布尔上下文 | 无 | 总是 true |
理解这些转换规则对于避免 JavaScript 中的意外行为非常重要,特别是在进行对象操作和比较时。
热门推荐:
0