为什么JavaScript中的“== == true?
我知道JavaScript有许多types之间的比较疯狂的结果,但我不完全明白为什么。 今天来到这一个。
为什么
"" == [null]
在JavaScript中评估为true
?
更多的Javascript平等娱乐,感谢@ Qantas:
- 为什么JavaScript 2中的2 == [2]?
- 为什么在JavaScript中为0 ==“”为true
- 为什么如果([])在javascript中validation[] == false?
- 为什么在JavaScript中将{} [true]评估为true?
“抽象平等比较algorithm”有很多部分,但重要的是:
如果Type( x )是String或Number,Type( y )是Object,则返回比较结果x == ToPrimitive( y )。
(这里也有一个镜像。)所以,因为""
是一个string, [null]
是一个对象,我们必须先调用ToPrimitive([null])
将[null]
转换为一个string。 当要求将Object实例转换为原始值时,这是一个内部操作,如下所述:
返回对象的默认值。 通过调用对象的[[DefaultValue]]内部方法来检索对象的默认值,并传递可选的提示PreferredType 。 本规范针对8.12.8中的所有本地ECMAScript对象定义了[[DefaultValue]]内部方法的行为。
现在,[[DefaultValue]]内部操作将在对象上调用.toString()
并返回该值。 在浏览器控制台中尝试[null].toString()
:
> [null].toString() ""
在那里,你有它。
编辑:为什么是[null].toString()
一个空string? 因为Array实例上的.toString()
操作总是调用.join()
,并且对于null
和undefined
值总是会产生一个空string。 因此,一个null
的数组最终只是一个空string。
这是根据JavaScript的神秘的types转换规则。 规则#8:
如果Type(x)是String或Number而Type(y)是Object,则返回比较结果x == ToPrimitive(y)。
因此,使用ToPrimitive
x = ""
和y = [null]
之间的比较转换为string。 用一个空元素转换数组会导致一个空string(因为Array.toString()
返回一个以逗号分隔的值列表),因此它们的计算结果是相等的。
为什么
"" == [null]
评估为真?
因为你正在比较一个数组与string,使用非严格的相等运算符==
– 所以它会尝试在比较之前将值转换为相同的types。
具体发生的是:
- 您将一个string与一个对象进行比较,以便将该对象转换为string:
- 当一个数组被转换为原始值时,调用
.toString()
方法(如其他答案所详细解释的),这相当于调用.join()
: - 在仅包含
undefined
或null
值的单元素数组的情况下, 返回空string - 最后相当于空string
这第三步是意想不到的( [null]+"" != null+""
),如果它实际上把它转换成string,结果将是"null"
并且你的等号是false。
让我们看看规范,并按照每一步
通过抽象平等比较algorithm(§11.9.3) :
-
typeof ""; // string
typeof ""; // string
和typeof [null]; // object
typeof [null]; // object
不适用 - 既不是
null
也不是undefined
所以不适用 - 与2相同
- 既不是一个数字,也不适用
- 和4一样
- 既不是一个布尔,也不适用
- 再次不适用
- 最后,适用的东西,现在我们需要知道
ToPrimitive([null])
§9.1ToPrimitive 对象说我们需要制定[[DefaultValue]]
(§8.12.8) ,其中的第一点和第二点说如果你可以做.toString
,它给出一个string,返回这个
[null].toString(); // ""
所以我们现在正在执行比较"" == ""
这是true
的抽象相等比较algorithm的第1点。
如果
Type(x)
是String ,则返回true
如果x
和y
是完全相同的字符序列(相同长度和相同位置的相同字符)。 否则,返回false
。
JavaScript是弱types的; 您可以使用以下来获得一个错误的结果:
"" === [null]
null值是表示null或“空”值的JavaScript文字,即没有对象值存在。 这是JavaScript的原始值之一。
null值是一个文字(不是像undefined这样的全局对象的属性)。 在API中,通常会在可以预期对象的位置检索null,但是没有对象是相关的。 当检查null或undefined时,要小心等号(==)和身份(===)运算符(types转换与前者执行)之间的差异。
typeof null // object (bug in ECMAScript, should be null) typeof undefined // undefined null === undefined // false null == undefined // true