前言
假如有一个场景,需要判断A与B是否相等,那么我们可以用 == 或者 === 来判断,而在两者之中 == 格外有趣。
有趣的区别对待
Boolean([]); //true
[] == false; //true
[] == ![]; //true
'' == []; //true
Boolean({}); //true
{} == true; //true
'' == {}; //false
'[object Object]' == {}; //true
有趣的隐性转换
首先,! 操作符将强制触发类型转换,所以 Boolean([])为true,而![]自然就成了false。
但在发生类型转换时 [] 却等于了false;
有趣的等于他来了。
而之所以出现这种有趣的结果根本原因还是在于标准的定制,在es5的标准规范中的11.9.3有着对
抽象相等比较算法的规则说明。我取和举例有关的进行说明,完整版可自行查阅文档。
假设 x == y。
- 当x,y二者其一的类型为Boolean时,将布尔值转变为数字。
- 当x,y二者的类型分别是对象和字符串或数字时,将调用对象的ToPrimitive()方法再比较。
ToPrimitive() 规范文档 9.1节(使用方式参考MDN),对于对象的处理方式为:返回该对象的默认值。对象的默认值由把
期望类型传入作为hint参数调用对象的内部方法 [[DefaultValue]] 得到,[[DefaultValue]]这个内部方法由 8.12.8定义。
[[DefaultValue]] 在文档中说明了会调用valueOf()和toString()方法,在引用数据类型向基本数据类型转化时会优先调用valueOf(),但由于数组和对象的valueOf()方法会返回自己本身,所以最终会调用toString()方法。
toString()
当数组调用toString()方法时,会返回数组元素的拼接字符串
[1,2,3].toString() // '1,2,3'
所以当数组为空时返回的自然是空字符串,而Boolean('')返回的布尔值就是为false。
'' == [] //true 这样的结果也顺理成章了。
当对象调用toString()时,返回的永远是'[object Object]',不是一个空字符串,自然也就是true了。
over