29

有没有一种方法可以进行浅比较,不会向下比较 Javascript 或 lodash 中对象内部的对象内容?请注意,我确实检查了 lodash,但它似乎执行了我不想做的深度比较。

var a = { x: 1, y: 2}
var b = { x: 1, y: 3}

有什么方法可以比较ab吗?

4

9 回答 9

58

简单的 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]
  );
于 2018-09-14T00:27:02.823 回答
29
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;
}
于 2014-03-08T08:16:59.327 回答
5

这是从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 中的此代码和任何其他代码,而不会发出警告。

于 2016-06-05T01:57:07.403 回答
5

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;
}

于 2016-08-19T14:22:07.793 回答
5

请记住,它仅适用于浅层且仅适用于字符串和数字

function equals(obj1, obj2) {
  return Object.keys(obj1)
    .concat(Object.keys(obj2))
    .every(key => {
      return obj1[key] === obj2[key];
    });
}
于 2017-11-28T13:29:18.330 回答
1

要进行“浅”比较,继承的属性应该被忽略并且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函数可以稍微简化:

于 2014-03-08T10:10:30.540 回答
1
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]);
于 2020-08-02T03:06:41.417 回答
0
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;
}
于 2017-09-23T05:19:05.030 回答
0

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 教程:查找两个对象值是否相等

于 2021-03-09T07:10:15.917 回答