从 [] + [],[] + {},{} + [] , {} + {} 深入至对象隐式转换
二元操作符 + 规则
- 如果操作数是对象,则对象会转换为原始值
- 如果操作数是字符串,则另一个操作数也会变成字符串,进行字符串拼接
- 否则,两个操作数都将转换为数字或 NaN,进行加法操作
对象数据转为原始数据类型值的方法
Symbol.ToPrimitiveObject.prototype.valueOfObject.prototype.toString
优先级
- 如果
[Symbol.toPrimitive](hint)方法存在,优先调用,无视valueOf和toSting方法 - 否则,如果期望是
"string"—— 先调用obj.toString()如果返回不是原始值,继续调用obj.valueOf() - 否则,如果期望是
"number"或"default"先调用obj.valueOf()如果返回不是原始值,继续调用obj.toString() - 如果未定义
[Symbol.toPrimitive](hint),期望string,此时toString()和valueOf()都没有返回原始值会抛出异常
const obj = {
value: 10,
valueOf() {
return this;
},
toString() {
return this;
}
};
console.log("hello" + obj); // 报错
[] 的原始值
typeof [][Symbol.ToPrimitive] // undefined
[].valueOf // []
[].toString() // ""
{} 的原始值
typeof {}[Symbol.ToPrimitive] // undefined
{}.valueOf() or ({}).valueof() // {}
({}).to String() // '[object Object]'
[] + []
转换步骤:
- [].toString() + [].toString()
- "" + ""
- ""
[] + {}
- [].toStrin() + ({}).toString()
- "" + "[object Object]"
- "[object Object]"
{} + []
- {}; + []
- +[]
- +""
- 0
{} + {}
- {}; + {}
- +'[object Object]'
- NaN
注意之前 chrome 内核浏览器会将其分组后变成 ({} + {}) 转换为变为 '[object Object][object Object]'
Symbol.toPrimitive(hint)
hint(暗示期望)-"string"hint"number"hint"default"
hint "string"
window.alert(obj)- 模板字符串
`${obj} test[obj] = 123
const obj = {
[Symbol.toPrimitive](hint) {
if (hint === "number") {
return 10;
}
if (hint === "string") {
return "hello";
}
return true;
}
};
window.alert(obj); // "hello"
console.log(`${obj}`); // "hello"
obj[obj] = 123;
console.log(obj); // {hello: 123, Symbol(Symbol.toPrimitive): ƒ}
console.log(Object.keys(obj)); // [ "hello" ]
hint "number"
- 一元+ ,位移
-、*、/等算数运算符Math.pow、String、prototype.slice等很多内部方法
const obj = {
[Symbol.toPrimitive](hint) {
if (hint === "number") {
return 10;
}
if (hint === "string") {
return "hello";
}
return true;
}
};
console.log("一元+", +obj);
console.log("位移运算符", obj >> 0);
console.log("加法", obj + 5); // 注意加法的 hint 是 default
console.log("减法", obj - 5);
console.log("乘法", obj * 5);
console.log("除法", obj / 5);
console.log("大于:", obj > 5);
console.log("大于:", obj < 5);
console.log("大于等于:", obj >= 5);
console.log("大于等于:", obj <= 5);
console.log("大于等于:", obj !== 5);
// 其他期望是整数的方法
console.log("Math.pow", Math.pow(2, obj));
打印结果:
![从 [] + [],[] + {},{} + [] , {} + {} 深入至对象隐式转换](https://static.blogweb.cn/article/ce3c4eade6bb42a6a6a7833238995ecb.webp)
hint - "default"
- 二元+
==、!=
const obj = {
[Symbol.toPrimitive](hint) {
if (hint === "number") {
return 10;
}
if (hint === "string") {
return "hello";
}
return true;
}
};
console.log("相加", obj + 5); // 相加 6
console.log("等等与", obj == 5); // 等等与 false
console.log("不等于", obj != 5); // 不等于 true
转载自:https://juejin.cn/post/7202224342753902652