繁体   English   中英

为什么[1,2,3]在Javascript中不等于自身?

[英]Why isn't [1,2,3] equal to itself in Javascript?

我今天在玩Java数组,注意到了这个小瑰宝:

alert([1, 2, 3] == [1, 2, 3]); //alerts false

数组不等于自身,这让我感到很奇怪。

但是后来我注意到了,这甚至更奇怪:

alert([1, 2, 3] == "1,2,3");  //alerts true

?!?!!?!?!!!?

为什么世界上[1, 2, 3]不是==本身而是==字符串?

我意识到== === 即便如此,什么邪恶可能导致Javascript先生做这种奇怪的事情?

好的,所以首先您需要了解javascript如何处理程序中的值。 您创建的所有变量将仅是内存中该对象存储位置的引用 因此,当您执行此操作时:

alert( [1,2,3] == [1,2,3] );

...它做三件事:

  1. 将一个数组([1,2,3])放在堆上
  2. 将另一个数组([1,2,3])放在堆上(注意它将具有不同的内存位置)
  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的疯狂之处,但希望这可以消除一些迷雾。

对于第一部分,您将创建两个不同的对象,因为数组只是对象,并且由于创建了两个对象,因此它们都是唯一的。

==运算子

[..]如果一个操作数是一个字符串,则另一个操作数将尽可能转换为字符串。 [..]如果两个操作数都是对象,则JavaScript将比较内部引用,当操作数引用内存中的同一对象时,内部引用相等。

https://developer.mozilla.org/zh-CN/JavaScript/Reference/Operators/Comparison_Operators

也就是说, [1, 2, 3] "1,2,3" [1, 2, 3]转换为等于"1,2,3"的字符串。 但是,一个数组对象不等于另一个数组对象。

第一次比较失败是因为两个对象的基本比较将检查它们在字面上是否是相同的引用对象,而不是两个对象是否具有相同的值。 如果要比较两个数组,则必须遍历这些值。

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'

因为==必须获得相同类型时才强制转换(例如,仅当操作数的类型不同时)。 做的时候

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" (您可以在规范中找到为什么将对象强制转换为字符串的完整逻辑。)

两个Array对象是不同的,因此在使用==比较时不相等。 为了比较它们,您需要循环执行,检查两者中的索引是否相同(如果元素也是ArrayObject ,则要递归)。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM