严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
当前回答
对于那些使用Node的人来说,在本地util库中有一个叫做isDeepStrictEqual的方便方法可以实现这一点。
const util = require('util');
const obj1 = {
foo: "bar",
baz: [1, 2]
};
const obj2 = {
foo: "bar",
baz: [1, 2]
};
obj1 == obj2 // false
util.isDeepStrictEqual(obj1, obj2) // true
https://nodejs.org/api/util.html#util_util_isdeepstrictequal_val1_val2
其他回答
我使用这个可比函数来生成JSON可比的对象副本:
Var可比= o => (typeof o != '对象' || !o)?o: 种(o) .sort()。减少((c键)= > (c[主要]=可比(o(例子)),c), {}); / /演示: var = {1, c: 4 b:[2、3],d: {e:“5”,f:零}}; var b = {b:[2、3],c: 4 d: {f: null, e:“5”},答:1}; console.log (JSON.stringify(可比(a))); console.log (JSON.stringify(可比(b))); console.log(JSON.stringify(comparable(a)) == JSON.stringify(comparable(b))); < div id = " div " > < / div >
在测试中很方便(大多数测试框架都有一个is函数)。如。
is(JSON.stringify(comparable(x)), JSON.stringify(comparable(y)), 'x must match y');
如果捕捉到差异,则记录字符串,使差异可见:
x must match y
got {"a":1,"b":{"0":2,"1":3},"c":7,"d":{"e":"5","f":null}},
expected {"a":1,"b":{"0":2,"1":3},"c":4,"d":{"e":"5","f":null}}.
我建议不要使用散列或序列化(正如JSON解决方案所建议的那样)。如果需要测试两个对象是否相等,则需要定义相等的含义。这可能是两个对象中的所有数据成员都匹配,也可能是内存位置必须匹配(意味着两个变量在内存中引用同一个对象),或者每个对象中只有一个数据成员必须匹配。
最近我开发了一个对象,它的构造函数在每次创建实例时都会创建一个新的id(从1开始,加1)。该对象有一个isEqual函数,用于将该id值与另一个对象的id值进行比较,如果匹配则返回true。
在这种情况下,我定义“相等”的意思是id值匹配。假设每个实例都有一个唯一的id,这可以用来加强匹配对象也占用相同内存位置的想法。尽管这是不必要的。
只是想利用一些es6的特性来贡献我的对象比较版本。它不考虑订单。在将所有if/else转换为三元后,我带来了以下内容:
function areEqual(obj1, obj2) {
return Object.keys(obj1).every(key => {
return obj2.hasOwnProperty(key) ?
typeof obj1[key] === 'object' ?
areEqual(obj1[key], obj2[key]) :
obj1[key] === obj2[key] :
false;
}
)
}
这是一个非常干净的CoffeeScript版本,你可以这样做:
Object::equals = (other) ->
typeOf = Object::toString
return false if typeOf.call(this) isnt typeOf.call(other)
return `this == other` unless typeOf.call(other) is '[object Object]' or
typeOf.call(other) is '[object Array]'
(return false unless this[key].equals other[key]) for key, value of this
(return false if typeof this[key] is 'undefined') for key of other
true
下面是测试:
describe "equals", ->
it "should consider two numbers to be equal", ->
assert 5.equals(5)
it "should consider two empty objects to be equal", ->
assert {}.equals({})
it "should consider two objects with one key to be equal", ->
assert {a: "banana"}.equals {a: "banana"}
it "should consider two objects with keys in different orders to be equal", ->
assert {a: "banana", kendall: "garrus"}.equals {kendall: "garrus", a: "banana"}
it "should consider two objects with nested objects to be equal", ->
assert {a: {fruit: "banana"}}.equals {a: {fruit: "banana"}}
it "should consider two objects with nested objects that are jumbled to be equal", ->
assert {a: {a: "banana", kendall: "garrus"}}.equals {a: {kendall: "garrus", a: "banana"}}
it "should consider two objects with arrays as values to be equal", ->
assert {a: ["apple", "banana"]}.equals {a: ["apple", "banana"]}
it "should not consider an object to be equal to null", ->
assert !({a: "banana"}.equals null)
it "should not consider two objects with different keys to be equal", ->
assert !({a: "banana"}.equals {})
it "should not consider two objects with different values to be equal", ->
assert !({a: "banana"}.equals {a: "grapefruit"})
如果您有一个方便的深度复制函数,您可以使用下面的技巧来使用JSON。Stringify同时匹配属性的顺序:
function equals(obj1, obj2) {
function _equals(obj1, obj2) {
return JSON.stringify(obj1)
=== JSON.stringify($.extend(true, {}, obj1, obj2));
}
return _equals(obj1, obj2) && _equals(obj2, obj1);
}
演示:http://jsfiddle.net/CU3vb/3/
理由是:
由于obj1的属性被逐个复制到克隆中,因此它们在克隆中的顺序将被保留。当obj2的属性被复制到克隆对象时,因为obj1中已经存在的属性将被简单地覆盖,它们在克隆对象中的顺序将被保留。