这是如何证明JavaScript数组相等性的问题?

8
这个答案中,有一个简单的函数,用于返回包含原始值的数组的数组相等性。
然而,我不确定它为什么有效。下面是该函数:
function arrays_equal(a,b) { return !!a && !!b && !(a<b || b<a); }

我主要关注后半部分,即这一部分:

!(a<b || b<a)

为什么在比较数组时使用<>能够生效,但使用==却不行?

JavaScript中的小于和大于方法是如何工作的?

3个回答

11

使用</>,数组会先转换为字符串,因此不能提供一种可靠的检查相等的方法。

==不起作用,因为对象是按引用检查的:

[] == []; // false, two separate objects

var a = [];
a == a; // true, refer to the same object

使用</>技巧是有缺陷的:

var a = [1, [2, 3]],
    b = [[1, 2], 3];

!(a<b || b<a); // true

这会被评估为true,因为在检查它们之前它们都被转换为字符串"1,2,3"</> 不能直接用于对象)。

因此,基本上你正在比较字符串的相等性。对于字符串,a == b 确实与 !(a<b || b<a) 相同 - 字符串的</> 检查字符代码,因此两个相等的字符串既不是“小于”也不是“大于”,因为这不适用于字符串中的任何字符代码。


1
一个更可靠的替代方案可能是 JSON.stringify(a) == JSON.stringify(b) - gilly3
1
@gilly: 没错,除非数组本身包含对象。 - pimvdb
1
@gilly3:还会有其他问题。JSON.stringify([function(){}]) == JSON.stringify([,]) // true - user1106925
1
@Heera:啊,我错过了那个 - 我不知道那些代码是什么 :) 是的,你是正确的,但请注意逗号也在字符串中。无论如何,考虑一个更简单的例子:"1">"2"是假的,因为49>50是假的。同样,反之亦然。 - pimvdb
2
大多数这些争论的重点基本上是,你不能将像这样简单的东西用作通用的实用函数。但是,从更实际的角度来看,如果你的数组是以已知格式存在的(例如,比较两个简单的字符串数组),那么像这样的函数肯定是足够的。 - gilly3
显示剩余9条评论

5
然而,我不确定它为什么有效。它并不起作用。考虑以下内容:
arrays_equal(["1,2"], [1,2])

即使按照基于逐个元素比较的数组等式的任何定义,它们都不同,但仍会产生true。
arrays_equal([[]], [])

并且

arrays_equal([""], [])

也有虚假的正面结果。

仅仅添加length检查是不够的,就像这个例子演示的那样。

arrays_equal(["1,2",3], [1,"2,3"])

arrays_equal(
    ["",","],
    [",",""])

编辑:

如果您想要一种简洁的测试结构相似性的方法,我建议:

function structurallyEquivalent(a, b) {
  return JSON.stringify(a) === JSON.stringify(b);
}

它不会在明显不同的输入上提前停止——它将遍历两个对象图,无论它们有多不同,但是OP中的函数也是如此。

一个注意点:当您使用非本地JSON.stringify时,它可能会对循环输入产生奇怪的影响,例如:

var input = [];
input[0] = input;

1
即使对于基本类型,JSON.stringify 也可能不是完全可靠的。考虑 [,][null] - pimvdb
@pimvdb,当然可以。它混淆了nullundefined/省略号,但JavaScript的==也是如此。OP中没有表达对===优于==的偏好。 - Mike Samuel
谢谢,你的回答进一步帮助了我理解,还有 @pimvdb 的。 - Bill Rawlinson

4

您可以使用 == 比较任意两个对象。但是由于 > 和 < 未定义为对象,它们会被转换为字符串。因此,[1,2,3]>[2,1,3] 实际上是在做 "1,2,3">"2,1,3"


1
这不是正确的。转换并不总是转为字符串。11.8.5 规定对象转换时使用类型提示 "number",因此 arrays_equal(new Date(1), 1)true - Mike Samuel
感谢Mike在评论中的澄清! - Bill Rawlinson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接