- 前言:
在同类型变量的比较中,"==="会直接返回true,而非同类型中,"=="直接会先将两个比较值转换为同一类型,再进行比较。
这里的转换就是"隐式转换",例如,以下几种:
"1" == 1; // true 1 == "1"; // true 0 == false; // true
那下面这个怎么解释?
![] == []
//还有下面 a = [] a == !a && a == a //true
大部分教程和书中,都建议使用"===",而不建议使用"==",因为"==="可以比年不同类型变量之间的比较,而且速度会更快。但是,我们还是应该搞清楚"=="存在的原理,并进行合理的使用。
- "=="作用规则
当要比较的值类型相同,值为true,不同即为false。
来看下,值类型不相同的。
MDN文档中,有几条规则:
1、 当数字与字符串进行比较时,会尝试将字符串转换为数字值;
2、如果操作数之一是Boolean,则将布尔操作数转化为1 或 0;
3、 如果操作数之一是对象,另一个数字后字符串,会尝试使用对象的valueOf()和toString()方法讲对象转换为数字或字符串;
4、 null == undefined 为true,此外通常情况下null和undefined与其他对象都不相等。
"![] == []",就相当于"false == []",然后由Boolean操作数,还可以转换为"0 == []" ,而"[]"转换为数字是0,所以返回true。
- 对象中的valueOf和toString,转换的时候那个优先级高
对象在隐式转换的时候,会尝试调用valueOf 和 toString函数,向字符串或者数字转换。那优先会采用哪一个函数的值?
实验:
const a = {} a.valueOf = () => 1 a.toString = () => 2 console.log(a == 1, a == 2) // true, false const b = {} b.valueOf = () => null // 优先级高于toString,比较直接返回false b.toString = () => '1' console.log(b == 'null', b == 1, b == '1') // false, false, false const c = {} c.valueOf = () => ([]) // 返回非基本值,将尝试取toString比较 c.toString = () => '1' console.log(c == 'undefined', c == '1') // false, true const d = {} d.valueOf = () => ([]) // 返回非基本值 d.toString = () => ([]) console.log(d == 'undefined', d == '1') // 比较报错:不能转为原始值
经过以上测试,valueOf 的优先级高于toString的优先级,而且valueOf和toString都会返回原始值(“String”,“Number”,“Boolean”,“null”,“undefined”),如果返回的是“null”或者是“undefined”,比较返回false,否则根据另一个比较值转为字符串或者数字进行比较;如果都不返回原始值,则比较操作将会报错。
- 显式转换
objA == 'abc' 的比较并不同于简单地将objA显式转换为字符串进行比较,即:objA == 'abc' 与 String(objeA) == 'abc' 结果并不一定相同(显式转换直接走toString):
const e = {} e.valueOf = () => 1 e.toString = () => '2' console.log(e == 1, e == '1', String(e) == '1', String(e) == '2') // true, true, false, true
- ES6中更高优先级的转换函数:Symbol.toPrimitive属性
Symbol.toPrimitive是一个内置的 Symbol 值,它是作为对象的函数值属性存在的,当一个对象转换为对应的原始值时,会调用此函数。该函数被调用时,会被传递一个字符串参数 hint
,表示要转换到的原始值的预期类型。 hint
参数的取值是 "number"
、"string"
和 "default"
中的任意一个。对于”==“操作符,hint传递的值是”default“。
const a = {} a[Symbol.toPrimitive] = (hint) => { if (hint == 'number') return 1 if (hint == 'string') return 2 return 3 } a.valueOf = () => 4 a.toString = () => 5 console.log(a == 1, a == 2, a == 3, a == 4, a == 5) // false, false, true, false, false
如果使用Number或者String强制转换a,则传入的”hint“会是”number“或者”string“。