从 [] + [],[] + {},{} + [] , {} + {} 深入至对象隐式转换
二元操作符 + 规则
- 如果操作数是对象,则对象会转换为原始值
- 如果操作数是字符串,则另一个操作数也会变成字符串,进行字符串拼接
- 否则,两个操作数都将转换为数字或 NaN,进行加法操作
对象数据转为原始数据类型值的方法
Symbol.ToPrimitive
Object.prototype.valueOf
Object.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));
打印结果:
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