【问题标题】:In Javascript, why is [1, 2] == [1, 2] or ({a : 1}) == ({a : 1}) false? [duplicate]在 Javascript 中,为什么 [1, 2] == [1, 2] 或 ({a : 1}) == ({a : 1}) 为假? [复制]
【发布时间】:2011-12-04 13:19:17
【问题描述】:

以下是在 Firebug 中完成的:

>>> [1, 2] == [1, 2]
false

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

我认为 Javscript 有一些规则说,如果 Object 或 Array 对相同元素具有相同的引用,那么它们是相等的?

但即使我说

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

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

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

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

【问题讨论】:

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

标签: javascript


【解决方案1】:

{ }[ ]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 example

警告:编写一个对所有输入都“有效”的等式函数很难,一些常见的陷阱是(null == undefined) === true(NaN === NaN) === false,我在我的函数中都不注意这两个问题。

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

【讨论】:

  • 你有很多需要修补这个功能。例如。 equal({},{}) === false。另外,我认为您的意思是使用_equal 递归。
  • @davin _equal 只是一个约定,我不知道如何优雅地处理{}[]。这也提出了equal(Object.create(foo), Object.create(bar))应该是真还是假的问题。
  • @Raynos,约定,那又怎样?如果我决定将该函数更改为myEqual,它将中断,因为您需要更改两次。
  • @davin 当然会坏掉。如果将其更改为myEqual,则需要将所有引用更改为equal,包括equal 中的任何引用
  • @Raynos,如果您使用函数的 name 属性进行递归,则不会。这就是我想告诉你的。将递归更改为引用 _equal 即可解决该问题!
【解决方案2】:

这是因为 javascript 对象字面量不共享相同的指针。而是为每个指针创建一个新指针。考虑以下示例:

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

...但是...

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

>>> obj == obj
true

obj 是一个指向 litteral 对象 { a : 1 } 的指针。所以这是有效的,因为当你比较它们时指针是相同的

【讨论】:

    【解决方案3】:

    您正在比较不同的对象。

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

    如果您想测试数组是否相等,您可能需要使用一些库或自己编写测试。

    【讨论】:

      【解决方案4】:

      要了解执行您所说的深度相等需要什么样的代码,请查看Underscore.js's _.isEqual functionQUnit's deepEqual implementation

      【讨论】:

      • 正如_QUnit 的来源所指出的,deepEquality 是一件非常重要的事情。
      • 正如您在答案中很快发现的那样;)
      • 我认为我的 ES5 尝试很优雅,涵盖了 99% 的用例!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-13
      • 2017-01-30
      • 1970-01-01
      相关资源
      最近更新 更多