JavaScript 中的对象比较 [英] Object comparison in JavaScript
问题描述
在 JavaScript 中比较对象的最佳方法是什么?
What is the best way to compare objects in JavaScript?
示例:
var user1 = {name : "nerd", org: "dev"};
var user2 = {name : "nerd", org: "dev"};
var eq = user1 == user2;
alert(eq); // gives false
我知道如果两个对象引用完全相同的对象,则它们是相等的,但是有没有办法检查它们是否具有相同的属性值?
I know that two objects are equal if they refer to the exact same object, but is there a way to check if they have the same attributes' values?
以下方式对我有用,但这是唯一的可能性吗?
The following way works for me, but is it the only possibility?
var eq = Object.toJSON(user1) == Object.toJSON(user2);
alert(eq); // gives true
推荐答案
不幸的是,没有完美的方法,除非您递归使用 _proto_
并访问所有不可枚举的属性,但这仅适用于 Firefox.
Unfortunately there is no perfect way, unless you use _proto_
recursively and access all non-enumerable properties, but this works in Firefox only.
所以我能做的最好的事情就是猜测使用场景.
So the best I can do is to guess usage scenarios.
当你有简单的 JSON 风格的对象而没有方法和 DOM 节点时工作:
Works when you have simple JSON-style objects without methods and DOM nodes inside:
JSON.stringify(obj1) === JSON.stringify(obj2)
属性的顺序很重要,所以这个方法会为以下对象返回false:
The ORDER of the properties IS IMPORTANT, so this method will return false for following objects:
x = {a: 1, b: 2};
y = {b: 2, a: 1};
<小时>
2) 缓慢且更通用.
比较对象而不深入研究原型,然后递归比较属性的投影,并比较构造函数.
2) Slow and more generic.
Compares objects without digging into prototypes, then compares properties' projections recursively, and also compares constructors.
这几乎是正确的算法:
function deepCompare () {
var i, l, leftChain, rightChain;
function compare2Objects (x, y) {
var p;
// remember that NaN === NaN returns false
// and isNaN(undefined) returns true
if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {
return true;
}
// Compare primitives and functions.
// Check if both arguments link to the same object.
// Especially useful on the step where we compare prototypes
if (x === y) {
return true;
}
// Works in case when functions are created in constructor.
// Comparing dates is a common scenario. Another built-ins?
// We can even handle functions passed across iframes
if ((typeof x === 'function' && typeof y === 'function') ||
(x instanceof Date && y instanceof Date) ||
(x instanceof RegExp && y instanceof RegExp) ||
(x instanceof String && y instanceof String) ||
(x instanceof Number && y instanceof Number)) {
return x.toString() === y.toString();
}
// At last checking prototypes as good as we can
if (!(x instanceof Object && y instanceof Object)) {
return false;
}
if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {
return false;
}
if (x.constructor !== y.constructor) {
return false;
}
if (x.prototype !== y.prototype) {
return false;
}
// Check for infinitive linking loops
if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {
return false;
}
// Quick checking of one object being a subset of another.
// todo: cache the structure of arguments[0] for performance
for (p in y) {
if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
return false;
}
else if (typeof y[p] !== typeof x[p]) {
return false;
}
}
for (p in x) {
if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
return false;
}
else if (typeof y[p] !== typeof x[p]) {
return false;
}
switch (typeof (x[p])) {
case 'object':
case 'function':
leftChain.push(x);
rightChain.push(y);
if (!compare2Objects (x[p], y[p])) {
return false;
}
leftChain.pop();
rightChain.pop();
break;
default:
if (x[p] !== y[p]) {
return false;
}
break;
}
}
return true;
}
if (arguments.length < 1) {
return true; //Die silently? Don't know how to handle such case, please help...
// throw "Need two or more arguments to compare";
}
for (i = 1, l = arguments.length; i < l; i++) {
leftChain = []; //Todo: this can be cached
rightChain = [];
if (!compare2Objects(arguments[0], arguments[i])) {
return false;
}
}
return true;
}
已知问题(好吧,它们的优先级很低,可能您永远不会注意到它们):
Known issues (well, they have very low priority, probably you'll never notice them):
- 具有不同原型结构但相同投影的对象
- 函数可能有相同的文本,但引用不同的闭包
测试:通过测试来自如何确定两个 JavaScript 对象的相等性?.
Tests: passes tests are from How to determine equality for two JavaScript objects?.
这篇关于JavaScript 中的对象比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!