如何在javascript中断言部分深度相等/比较对象?
我有一个API,我想断言至少返回了预期的数据。我不在乎是否返回更多数据 因此,我想比较两个对象(如何在javascript中断言部分深度相等/比较对象?,javascript,Javascript,我有一个API,我想断言至少返回了预期的数据。我不在乎是否返回更多数据 因此,我想比较两个对象(expected和actual),其中expected的所有属性必须等于actual,但actual可能包含更多属性: var expected = { foo: 1, bar: { x1: 42, a1: [ 1, 2, { x: 7
expected
和actual
),其中expected
的所有属性必须等于actual
,但actual
可能包含更多属性:
var expected = {
foo: 1,
bar: {
x1: 42,
a1: [
1,
2,
{
x: 7
}
]
}
}
var actual = {
foo: 1,
whatever: 55, // to be ignored
additional: { // to be ignored
ignore: 1
},
bar: {
x1: 42,
a1: [
1,
2,
{
x: 7,
y: 8 // to be ignored
}
]
}
}
partiallyEqual(expected, actual) // returns true
还有一些例子:
如果actual
包含额外的元素,则阵列可能(可选)受到部分等效的影响
partiallyEqual([1, 3], [1, 2, 3]) // return true
partiallyEqual([3, 1], [1, 2, 3]) // return false (different order)
我使用这个递归函数,这是我不久前写的:
Object.prototype.equals = function(to) {
for (var prop in to) {
if (this.hasOwnProperty(prop) && to.hasOwnProperty(prop)) {
if (to[prop] && typeof this[prop] == "object" && typeof to[prop] == "object") {
if (!this[prop].equals(to[prop])) {
return false
}
} else if (this[prop] != to[prop]) {
return false
}
}
}
return true;
};
({ x: { a: 1, b: 2 } }).equals({ x: { a: 1, b: 2 } }) => true
({ x: { a: 1, b: 2 } }).equals({ x: { a: 1, b: 1 } }) => false
({ x: [1,2] }).equals({ x: { 1:1,2:2 } }) => true (doesn't differentiate between array and/or object)
此函数在发现旧对象与新对象之间存在差异时,将立即返回false。如果新对象具有旧对象的所有属性,则它可以包含任何内容。对于不同的情况,深度相等可能很棘手,例如
NaN!==NaN
并且可能存在循环引用。最近我编写了一个简单的带有递归和循环引用检查的deep equal check util函数,它应该非常简单。您可以忽略一些长度检查来完成部分相等
github上的源代码:您是否尝试过Chai的
deepEqual
?是的,但它是严格相等的,id不会忽略任何属性,因为您的用例是deepEqual
的一个小变化,我建议看一下这里:根据您的需要调整一下。一个可能的解决方案可能是创建一个actual
副本,在比较之前剥离预期的中不包含的所有属性。对于可能正确的小对象,但如果对象很大,则可能不是最佳解决方案。请查看并执行您的Object.prototype
扩展正确。我使用名为prop的函数来实现它:function prop(to,name,func){Object.defineProperty(to.prototype,name,{value:func,writable:true,configurable:true});return func;}
它用作休耕prop(Object,'equals',function(to){…})
这些可以链接:prop(Object,'equals',function(to){prop(Array,'equals',function(to){…})
,顺便说一句,扩展Object也扩展了Array,因为它扩展了一切
Object.prototype.equals = function(to) {
for (var prop in to) {
if (this.hasOwnProperty(prop) && to.hasOwnProperty(prop)) {
if (to[prop] && typeof this[prop] == "object" && typeof to[prop] == "object") {
if (!this[prop].equals(to[prop])) {
return false
}
} else if (this[prop] != to[prop]) {
return false
}
}
}
return true;
};
({ x: { a: 1, b: 2 } }).equals({ x: { a: 1, b: 2 } }) => true
({ x: { a: 1, b: 2 } }).equals({ x: { a: 1, b: 1 } }) => false
({ x: [1,2] }).equals({ x: { 1:1,2:2 } }) => true (doesn't differentiate between array and/or object)