为啥 [1,2,3] 在 Javascript 中不等于自身? [复制]
Posted
技术标签:
【中文标题】为啥 [1,2,3] 在 Javascript 中不等于自身? [复制]【英文标题】:Why isn't [1,2,3] equal to itself in Javascript? [duplicate]为什么 [1,2,3] 在 Javascript 中不等于自身? [复制] 【发布时间】:2011-11-10 23:50:46 【问题描述】:我今天在玩 javascript 中的数组时发现了这个小宝石:
alert([1, 2, 3] == [1, 2, 3]); //alerts false
数组不等于自身,这让我觉得很奇怪。
但后来我注意到了这一点,这更奇怪:
alert([1, 2, 3] == "1,2,3"); //alerts true
?!?!?!?!!!?
为什么[1, 2, 3]
不是==
本身,而是==
到字符串?
我意识到 ==
是 not the same 和 ===
。即便如此,到底是什么邪恶的事情能让Javascript先生做出如此诡异的事情呢?
【问题讨论】:
当一种语言按照它的规范要求做它应该做的事情时,这并不是邪恶的。鉴于您已经知道==
和 ===
做的事情不同,这不是回答您关于该数组和字符串之间比较的问题吗?
Why doesn't equality check work with arrays的可能重复
【参考方案1】:
好的,首先您需要了解 javascript 如何处理程序中的值。您创建的所有变量都将只是引用到内存中存储该对象的位置。因此,当您这样做时:
alert( [1,2,3] == [1,2,3] );
...它做了三件事:
-
将数组 ([1,2,3]) 放入堆中
将另一个数组 ([1,2,3]) 放到堆上(注意它会有不同的内存位置)
比较两个参考。它们指向内存中不同位置的不同对象,因此被认为不相等。
您可以通过运行以下代码来检查一些正常的行为:
var a = [1,2,3];
var b = a;
alert (a == b) // Result is true. Both point to the same object.
现在关于字符串的问题
当您使用==
运算符时,会尝试将两个操作数转换为相同的类型(邪恶行为...我知道...)
当它执行此操作时,它决定在进行比较之前将两者都转换为字符串(因此结果实际上是 "1,2,3" === "1,2,3"
,其计算结果为 true。
我无法为您提供完整的图片,因为很少有人了解 JavaScript 疯狂的每一个细微差别,但希望这能消除一些迷雾。
【讨论】:
==
没有邪恶的行为,它有明确定义的行为,在这种情况下,你从===
得到的帮助要小得多。或者也许它更多有帮助:这真的取决于你想要做什么。
@nnnnnn,它具有反直觉行为,因此它是邪恶的。上面的例子揭示了==
的一些邪恶本质,但不是全部。例如,false == undefined
为假,false==null
为假,但null==undefined
为真。它定义明确,但完全违反直觉(如果传递性是“正确”的基础,那么结果完全是错误的。)
@nnnnnn,等等,复制了错误的示例(深夜)。打破传递性的例子是:'0'==0
为真,'' == 0
为真,但'0'==''
为假。惊人的反直觉。
==
在数组方面的行为,不过,并不是那么违反直觉,是吗?它们是不同的数组,恰好包含相同的元素。
@Dave,当然,从编写解释器的角度来看,这可能是有道理的,但是检查两个数组是否存储在记忆?换句话说,与比较数组中的元素相比,您多久需要一次当前行为? JavaScript 认为前者更有可能。 Python 认为后者更有可能。我同意 Python。【参考方案2】:
==
运营商[..] 如果任一操作数是字符串,则如果可能,另一个操作数将转换为字符串。 [..] 如果两个操作数都是对象,那么当操作数引用内存中的同一个对象时,JavaScript 会比较相等的内部引用。
https://developer.mozilla.org/en/JavaScript/Reference/Operators/Comparison_Operators
也就是说[1, 2, 3]
转换成字符串等于"1,2,3"
。但是,一个数组对象不等于另一个数组对象。
【讨论】:
【参考方案3】:对于第一部分,您将创建两个不同的对象,因为数组只是对象,并且由于您创建了其中两个,它们都是唯一的。
【讨论】:
【参考方案4】:因为==
仅强制如果必须获得相同的类型(例如,仅当操作数的类型不同时)。做的时候
alert([1, 2, 3] == [1, 2, 3]); //alerts false
...不需要强制;两者都是对象。它们不是相同的对象,所以它是false
。人们认为==
是“强制”相等运算符,确实如此,但关键是它只有必须强制。
但是做
alert([1, 2, 3] == "1,2,3"); //alerts true
...涉及不同类型的操作数:字符串和对象。这样强制就完成了。在这种情况下,对象被强制转换为字符串,就像使用 String(obj)
一样,这会调用其默认的 toString
行为,对于数组来说是 .join()
。 join
默认使用","
作为分隔符,因此结果字符串匹配"1,2,3"
。 (您可以找到对象被强制转换为字符串 in the specification 的完整逻辑。)
【讨论】:
【参考方案5】:第一次比较失败,因为两个对象的基本比较将检查它们是否是字面上相同的引用对象,而不是两个对象是否具有相同的值。如果你想比较两个数组,你必须遍历这些值。
function arrayCompare(arr1, arr2)
if (arr1.length !== arr2.length) return false;
for (var i = 0, len = arr1.length; i < len; i++)
if (arr1[i] !== arr2[i]) return false;
return true;
请记住,这不是递归比较,因此它仅适用于原始值数组。
第二个比较有效,因为 == 将尝试强制参数的类型,并且当您将数组转换为字符串时,这就是结果。
[1,2,3].toString() === '1,2,3'
【讨论】:
【参考方案6】:两个Array
对象是不同的,因此在使用==
比较时不相等。要比较它们,您需要循环,检查两者中的索引是否相同(如果元素也是 Array
s 或 Object
s,则递归)。
第二个是因为Array
隐式调用了它的toString()
,它返回了'1,2,3'
(试试看)。
这是因为根据 ECMAScript 中的 ==
(非严格)比较规则,左侧运算符被强制转换为 String
(==
进行类型转换)。
【讨论】:
以上是关于为啥 [1,2,3] 在 Javascript 中不等于自身? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
为啥 [1,2,3] 在 Javascript 中不等于自身? [复制]