在JavaScript中,为什么[1,2]== [1,2]或({a:1})==({a:1})是错误的?

7
以下是在Firebug中完成的操作:
>>> [1, 2] == [1, 2]
false

>>> ({a : 1}) == ({a : 1})
false

我认为Javascript有一个规则,即如果一个对象或数组具有相同的引用指向相同的元素,则它们是相等的?

但是,即使我这样说:

>>> foo = {a : 1}
Object { a=1}

>>> [foo] == [foo]
false

>>> ({a: foo}) == ({a: foo})
false

有没有办法让它进行元素比较并返回true

12
对象字面量创建新实例,定义两个实例不会使它们共享相同的引用。 - zzzzBov
需要相等的不是“内部元素”吗? - nonopolarity
4个回答

6

{ }[ ] 相当于 new Objectnew Array

而且 new Object != new ObjectArray 同理)因为它们是新的和不同的对象。

如果你想知道两个任意对象的内容是否相同,对于某些相同值,一个快速(但慢)的解决方案是:

JSON.parse(o) === JSON.parse(o)

更优雅的解决方案是定义一个相等的函数(未经测试)。

var equal = function _equal(a, b) {
  // if `===` or `==` pass then short-circuit
  if (a === b || a == b) { 
    return true;
  }
  // get own properties and prototypes
  var protoA = Object.getPrototypeOf(a), 
      protoB = Object.getPrototypeOf(b),
      keysA = Object.keys(a), 
      keysB = Object.keys(b);

  // if protos not same or number of properties not same then false
  if (keysA.length !== keysB.length || protoA !== protoB) {
    return false;
  }
  // recurse equal check on all values for properties of objects
  return keysA.every(function (key) {
    return _equal(a[key], b[key]);
  });
};

equals 示例

警告:编写一个“适用于所有输入”的相等函数很困难,一些常见的陷阱包括(null == undefined) === true(NaN === NaN) === false。在我的函数中,我没有考虑到这些情况。

我也没有解决任何跨浏览器问题,我只假设ES5存在。


你需要修补那个函数的很多问题。例如,equal({},{}) === false。另外,我认为你想要使用 _equal 进行递归。 - davin
@davin _equal只是一种约定,我不知道如何优雅地处理{}[]。这也引发了一个问题,即equal(Object.create(foo), Object.create(bar))应该是true还是false。 - Raynos
@Raynos,约定俗成,那又怎样?如果我决定将该函数更改为myEqual,它将会出错,因为你需要两次更改。 - davin
@davin 当然会出问题。如果你将其更改为 myEqual,则需要更改所有引用 equal 的地方,包括在 equal 内部的任何引用。 - Raynos
@Raynos,如果你使用函数的名称属性进行递归,那就不一样了。这就是我试图告诉你的。将递归更改为引用“_equal”,你就解决了这个问题! - davin
@davin 我想我修复了你提到的问题。 - Raynos

2

正如“_”和“QUnit”的来源所指出的那样,深度相等是一件非常棘手的事情。 - Raynos
正如你在回答中很快发现的那样 ;) - Domenic
我认为我的 ES5 尝试很优雅,涵盖了 99% 的用例! - Raynos

0

这是因为JavaScript对象字面量不共享相同的指针。相反,每个对象都会创建一个新的指针。请考虑以下示例:

>>> ({a : 1}) == ({a : 1})
false

...但是...

>>> obj = ({a : 1});
Object

>>> obj == obj
true

obj 是指向字面对象 { a : 1 } 的指针。所以这个比较有效是因为它们指向相同的指针。


0

您正在比较不同的对象。

>>> var a = [1,2] var b = [1,2]
>>> a == b
false
>>> a == a
true

如果你想测试数组的相等性,你可以使用一些库或者自己编写测试。

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