有没有一种方法可以进行浅比较,不会向下比较 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]
);
function 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:{}})
是错误的。
areEqualShallow({a:undefined}, {})
是假的。
这包括原型中的任何属性。
这使用===
了比较。我认为这就是你想要的。NaN === NaN
是一种可能会产生意想不到的结果的情况。如果===
不是您想要的,请替换为您想要的比较。
编辑:如果每个对象中都有相同的键,那么
function areEqualShallow(a, b) {
for(var key in a) {
if(a[key] !== b[key]) {
return false;
}
}
return true;
}
这是从fbjs提升的:
/**
* 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 中的此代码和任何其他代码,而不会发出警告。
Paul Draper 的解决方案可以通过删除第二遍中的比较来优化。
function 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;
}
请记住,它仅适用于浅层且仅适用于字符串和数字
function equals(obj1, obj2) {
return Object.keys(obj1)
.concat(Object.keys(obj2))
.every(key => {
return obj1[key] === obj2[key];
});
}
要进行“浅”比较,继承的属性应该被忽略并且NaN
应该 equal 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;
}
使用诸如Object.keys 之类的最新功能来获取自己的属性,然后
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函数可以稍微简化:
const shallowEq = (a, b) =>
[...Object.keys(a), ...Object.keys(b)].every((k) => b[k] === a[k]);
如果你真的需要检查未定义的值,那么这个扩展应该满足@AndrewRasmussen:
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]);
var 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 教程:查找两个对象值是否相等