在JavaScript或lodash中,有没有一种可以进行浅层比较的方法,不会进入并比较对象内部的对象内容?请注意,我确实检查了lodash,但它似乎执行深度比较,而我不想这样做。
var a = { x: 1, y: 2}
var b = { x: 1, y: 3}
例如,有没有一种方法可以比较a
和b
?
在JavaScript或lodash中,有没有一种可以进行浅层比较的方法,不会进入并比较对象内部的对象内容?请注意,我确实检查了lodash,但它似乎执行深度比较,而我不想这样做。
var a = { x: 1, y: 2}
var b = { x: 1, y: 3}
例如,有没有一种方法可以比较a
和b
?
ES6的简单方法:
const shallowCompare = (obj1, obj2) =>
Object.keys(obj1).length === Object.keys(obj2).length &&
Object.keys(obj1).every(key => obj1[key] === obj2[key]);
在此,我添加了对象键的数量相等检查,以便以下比较失败(通常不被考虑的重要情况):
shallowCompare({ x: 1, y: 3}, { x: 1, y: 3, a: 1}); // false
2019 更新。根据 Andrew Rasmussen 的评论,我们还需要考虑 undefined
情况。之前的方法存在问题,因为以下比较返回 true
:
({ foo: undefined })['foo'] === ({ bar: undefined })['foo'] // true
所以需要进行显式键存在性检查。可以使用hasOwnProperty
来完成:
const shallowCompare = (obj1, obj2) =>
Object.keys(obj1).length === Object.keys(obj2).length &&
Object.keys(obj1).every(key =>
obj2.hasOwnProperty(key) && obj1[key] === obj2[key]
);
shallowCompare({ foo: undefined, }, { bar: undefined, }); // 返回 true
- Andrew RasmussenObject.prototype.hasOwnProperty.call(obj2, key)
以通过 ESLint 检查:https://eslint.org/docs/rules/no-prototype-builtins - theicfirefunction areEqualShallow(a, b) {
for(var key in a) {
if(!(key in b) || a[key] !== b[key]) {
return false;
}
}
for(var key in b) {
if(!(key in a) || a[key] !== b[key]) {
return false;
}
}
return true;
}
注意:
由于这是浅层比较,areEqualShallow({a:{}}, {a:{}})
返回 false。
areEqualShallow({a:undefined}, {})
返回 false。
包括原型链上的任何属性。
这使用 ===
进行比较。我假设这是您想要的。 NaN === NaN
是一个可能会产生意外结果的情况。如果 ===
不是您想要的,请用您想要的比较方法替换。
编辑:如果每个对象中都有相同的键,则
function areEqualShallow(a, b) {
for(var key in a) {
if(a[key] !== b[key]) {
return false;
}
}
return true;
}
typeof
吗?如果 a[key]
和 b[key]
是子对象? - sabithpocker===
有一些边缘情况。特别是,NaN不等于自身,而+0和-0彼此相等(尽管在某些情况下行为不同)。 - ruakhfunction equals(obj1, obj2) {
return Object.keys(obj1)
.concat(Object.keys(obj2))
.every(key => {
return obj1[key] === obj2[key];
});
}
equals({ foo: undefined, }, { bar: undefined, }); // 返回true
- Andrew Rasmussen{ foo: undefined }
和{ bar: undefined }
与描述{}
一样,只是多了一些步骤。 - Stevenfunction areEqualShallow(a, b) {
for (let key in a) {
if (!(key in b) || a[key] !== b[key]) {
return false;
}
}
for (let key in b) {
if (!(key in a)) {
return false;
}
}
return true;
}
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*
*/
/*eslint-disable no-self-compare */
'use strict';
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* inlined Object.is polyfill to avoid requiring consumers ship their own
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
*/
function is(x, y) {
// SameValue algorithm
if (x === y) {
// Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return x !== 0 || 1 / x === 1 / y;
} else {
// Step 6.a: NaN == NaN
return x !== x && y !== y;
}
}
/**
* Performs equality by iterating through keys on an object and returning false
* when any key has values which are not strictly equal between the arguments.
* Returns true when the values of all keys are strictly equal.
*/
function shallowEqual(objA, objB) {
if (is(objA, objB)) {
return true;
}
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
return false;
}
var keysA = Object.keys(objA);
var keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
// Test for A's keys different from B.
for (var i = 0; i < keysA.length; i++) {
if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
return false;
}
}
return true;
}
module.exports = shallowEqual;
如果您需要使用它,我建议将其复制到您自己的项目中。因为他们的README清楚地说明,他们可能会在没有警告的情况下删除或修改lib中的此代码和其他任何代码。
NaN
应等于NaN
,以下代码可实现此功能。它检查每个对象是否具有相同的自有属性,并且值为===
或两者都为NaN
:function checkProperties(a, b) {
var equal = true;
// For each property of a
for (var p in a) {
// Check that it's an own property
if (a.hasOwnProperty(p)) {
// Check that b has a same named own property and that the values
// are === or both are NaN
if (!b.hasOwnProperty(p) ||
(b[p] !== a[p] && !(typeof b[p] == 'number' && typeof a[p] == 'number' && isNaN(b[p] && isNaN(a[p]))))) {
// If not, set equal to false
equal = false;
}
}
// If equal is false, stop processing properties
if (!equal) break;
}
return equal;
}
function checkProperties(a, b) {
return Object.keys(a).every(function(p) {
return b.hasOwnProperty(p) &&
(b[p] == a[p] || (typeof a[p] == 'number' && typeof b[p] == 'number' && isNaN(b[p]) && isNaN(a[p])));
});
}
// Compare a to b and b to a
function areEqualShallow(a, b) {
return checkProperties(a, b) && checkProperties(b, a);
}
// Minimal testing
var a = {foo:'a', bar:2};
var b = {foo:'a', bar:2};
var c = {foo:'c', bar:2};
var d = {foo:'a', bar:2, fum:0};
console.log('a equal to b? ' + areEqualShallow(a,b)); // true
console.log('a equal to c? ' + areEqualShallow(a,c)); // false
console.log('a equal to d? ' + areEqualShallow(a,d)); // false
随着新功能的加入,checkProperties函数可以在一定程度上得到简化:
isNaN(someNonNumber)
总是返回 true,所以不匹配的值会通过。;-) - RobG===
而不是 ==
。双等号容易出错。 - Georgeconst shallowEq = (a, b) =>
[...Object.keys(a), ...Object.keys(b)].every((k) => b[k] === a[k]);
const shallowEq2 = (a, b) =>
[...Object.keys(a), ...Object.keys(b)].every(k => b[k] === a[k] && a.hasOwnProperty(k) && b.hasOwnProperty(k));
在大多数情况下,您实际上并不需要进行所有检查,您只想看到 b 是否包含 a 的所有内容。然后,以 a 为中心的检查将非常简洁:
const shallowEq3 = (a, b) => Object.keys(a).every(k => b[k] === a[k]);
true
,如果 a = { x: 1 }, b = { x: 1, y: 2 }
。 - apostl3polvar a = { x: 1, y: 2}
var b = { x: 1, y: 3}
function shalComp (obj1, obj2) {
var verdict = true;
for (var key in obj1) {
if (obj2[key] != obj1[key]) {
verdict = false;
}
}
return verdict;
}
const isEqual = (a, b) => {
// compare keys
const xKeys = Object.keys(a);
const bKeys = Object.keys(b);
if (xKeys.length !== bKeys.length) {
return false;
}
// compare values
for (let objKeys in xKeys) {
if (xKeys[objKeys !== bKeys[objKeys]]) {
return false;
}
}
return true;
};
var a = {
x: 1,
y: 2,
};
var b = {
x: 1,
y: 2,
};
console.log(isEqual(a, b)); // true
你可以看到这个视频对你的问题非常有帮助:JS教程:查找两个对象值是否相等
JSON.stringify(a) === JSON.stringify(b)
。 - thefourtheyeJSON.stringify
中没有关于顺序的保证。 - Paul Draper