为啥 [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 对象是不同的,因此在使用== 比较时不相等。要比较它们,您需要循环,检查两者中的索引是否相同(如果元素也是 Arrays 或 Objects,则递归)。

第二个是因为Array 隐式调用了它的toString(),它返回了'1,2,3'(试试看)。

这是因为根据 ECMAScript 中的 ==(非严格)比较规则,左侧运算符被强制转换为 String== 进行类型转换)。

【讨论】:

以上是关于为啥 [1,2,3] 在 Javascript 中不等于自身? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 [1,2,3] 在 Javascript 中不等于自身? [复制]

为啥 2 == [2] 在 JavaScript 中?

为啥 2 && 3 结果为 3 (javascript)? [复制]

JavaScript为啥浮点数会丢失精度

为啥 -1**2 在 JavaScript 中是语法错误?

在javascript中,为啥这个数组的reduce方法在下面的代码中给出了这个输出?