转Boolean
在条件判断(if、!)
时,除了undefined
,null
,false
,NaN
,''
,0
,-0
,其他所有值都转为true
,包括所有对象。
对象转基本类型
对象在转换基本类型时,首先会调用 valueOf 然后调用 toString。并且这两个方法你是可以重写的。
let a = {
valueOf() {
return 0
}
}
当然你也可以重写 Symbol.toPrimitive
,该方法在转基本类型时调用优先级最高。
let a = {
valueOf() {
return 0;
},
toString() {
return '1';
},
[Symbol.toPrimitive]() {
return 2;
}
}
1 + a // => 3
'1' + a // => '12'
对象的Symbol.toPrimitive
属性,指向一个方法。
该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。
Symbol.toPrimitive
被调用时,会接受一个字符串参数,表示当前运算的模式,一共有三种模式。
(1).Number
:该场合需要转成数值。
(2).String
:该场合需要转成字符串。
(3).Default
:该场合可以转成数值,也可以转成字符串。
下面的例子展示了, Symbol.toPrimitive
属性是如何干扰一个对象转换为原始值时输出的结果的。
// 一个没有提供 Symbol.toPrimitive 属性的对象,参与运算时的输出结果
var obj1 = {};
console.log(+obj1); // NaN
console.log(`${obj1}`); // "[object Object]"
console.log(obj1 + ""); // "[object Object]"
// 接下面声明一个对象,手动赋予了 Symbol.toPrimitive 属性,再来查看输出结果
var obj2 = {
[Symbol.toPrimitive](hint) {
if (hint == "number") {
return 10;
}
if (hint == "string") {
return "hello";
}
return true;
}
};
console.log(+obj2); // 10 -- hint 参数值是 "number"
console.log(`${obj2}`); // "hello" -- hint 参数值是 "string"
console.log(obj2 + ""); // "true" -- hint 参数值是 "default"
四则运算符
只有当加法运算时,其中一方是字符串类型,就会把另一个也转为字符串类型。其他运算只要其中一方是数字,那么另一方就转为数字。并且加法运算会触发三种类型转换:将值转换为原始值,转换为数字,转换为字符串。
1 + '1' // '11'
2 * '2' // 4
[1, 2] + [2, 1] // '1,22,1'
// [1, 2].toString() -> '1,2'
// [2, 1].toString() -> '2,1'
// '1,2' + '2,1' = '1,22,1'
对于加号需要注意这个表达式'a' + + 'b'
'a' + + 'b' // -> "aNaN"
// 因为 + 'b' -> NaN
// 你也许在一些代码中看到过 + '1' -> 1
==
操作符
上图中的toPrimitive
就是对象转基本类型。
这里来解析一道题目[] == ![] // -> true
,下面是这个表达式为何为true
的步骤
// [] 转成 true,然后取反变成 false
[] == false
// 根据第 8 条得出
[] == ToNumber(false)
[] == 0
// 根据第 10 条得出
ToPrimitive([]) == 0
// [].toString() -> ''
'' == 0
// 根据第 6 条得出
0 == 0 // -> true
比较运算符
- 如果是对象,就通过
toPrimitive
转换对象 - 如果是字符串,就通过
unicode
字符索引来比较,从首个字母开始比较
'abc' > 'bcd' // false
'abc' > 'acc' // false