Javascript 如何检查两个对象是否具有相同的属性名称集?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14368596/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I check that two objects have the same set of property names?
提问by dan27
I am using node, mocha, and chai for my application. I want to test that my returned results data property is the same "type of object" as one of my model objects (Very similar to chai's instance). I just want to confirm that the two objects have the same sets of property names. I am specifically not interested in the actual values of the properties.
我正在为我的应用程序使用 node、mocha 和 chai。我想测试我返回的结果数据属性是否与我的模型对象之一具有相同的“对象类型”(非常类似于 chai 的实例)。我只想确认这两个对象具有相同的属性名称集。我对属性的实际值特别不感兴趣。
Let's say I have the model Person like below. I want to check that my results.data has all the same properties as the expected model does. So in this case, Person which has a firstName and lastName.
假设我有像下面这样的模型 Person 。我想检查我的 results.data 是否具有与预期模型相同的所有属性。所以在这种情况下,Person 有一个 firstName 和 lastName。
So if results.data.lastNameand results.data.firstNameboth exist, then it should return true. If either one doesn't exist, it should return false. A bonus would be if results.data has any additional properties like results.data.surname, then it would return false because surname doesn't exist in Person.
所以如果results.data.lastName和results.data.firstName两者都存在,那么它应该返回true。如果其中一个不存在,则应返回 false。如果results.data 有任何额外的属性,如results.data.surname,那么它会返回false,因为surname 在Person 中不存在。
This model
这个型号
function Person(data) {
var self = this;
self.firstName = "unknown";
self.lastName = "unknown";
if (typeof data != "undefined") {
self.firstName = data.firstName;
self.lastName = data.lastName;
}
}
回答by Casey Foster
You can serialize simple data to check for equality:
您可以序列化简单数据以检查相等性:
data1 = {firstName: 'John', lastName: 'Smith'};
data2 = {firstName: 'Jane', lastName: 'Smith'};
JSON.stringify(data1) === JSON.stringify(data2)
This will give you something like
这会给你类似的东西
'{firstName:"John",lastName:"Smith"}' === '{firstName:"Jane",lastName:"Smith"}'
As a function...
作为函数...
function compare(a, b) {
return JSON.stringify(a) === JSON.stringify(b);
}
compare(data1, data2);
EDIT
编辑
If you're using chai like you say, check out http://chaijs.com/api/bdd/#equal-section
如果您像您说的那样使用 chai,请查看http://chaijs.com/api/bdd/#equal-section
EDIT 2
编辑 2
If you just want to check keys...
如果您只想检查密钥...
function compareKeys(a, b) {
var aKeys = Object.keys(a).sort();
var bKeys = Object.keys(b).sort();
return JSON.stringify(aKeys) === JSON.stringify(bKeys);
}
should do it.
应该这样做。
回答by schirrmacher
2 Here a short ES6variadic version:
2 这是一个简短的ES6可变参数版本:
function objectsHaveSameKeys(...objects) {
const allKeys = objects.reduce((keys, object) => keys.concat(Object.keys(object)), []);
const union = new Set(allKeys);
return objects.every(object => union.size === Object.keys(object).length);
}
A little performance test(MacBook Pro - 2,8 GHz Intel Core i7, Node 5.5.0):
一点性能测试(MacBook Pro - 2,8 GHz Intel Core i7, Node 5.5.0):
var x = {};
var y = {};
for (var i = 0; i < 5000000; ++i) {
x[i] = i;
y[i] = i;
}
Results:
结果:
objectsHaveSameKeys(x, y) // took 4996 milliseconds
compareKeys(x, y) // took 14880 milliseconds
hasSameProps(x,y) // after 10 minutes I stopped execution
回答by Ragnarokkr
If you want to check if both objects have the same properties name, you can do this:
如果要检查两个对象是否具有相同的属性名称,可以执行以下操作:
function hasSameProps( obj1, obj2 ) {
return Object.keys( obj1 ).every( function( prop ) {
return obj2.hasOwnProperty( prop );
});
}
var obj1 = { prop1: 'hello', prop2: 'world', prop3: [1,2,3,4,5] },
obj2 = { prop1: 'hello', prop2: 'world', prop3: [1,2,3,4,5] };
console.log(hasSameProps(obj1, obj2));
In this way you are sure to check only iterable and accessible properties of both the objects.
通过这种方式,您可以确保只检查两个对象的可迭代和可访问属性。
EDIT - 2013.04.26:
编辑 - 2013.04.26:
The previous function can be rewritten in the following way:
前面的函数可以用以下方式重写:
function hasSameProps( obj1, obj2 ) {
var obj1Props = Object.keys( obj1 ),
obj2Props = Object.keys( obj2 );
if ( obj1Props.length == obj2Props.length ) {
return obj1Props.every( function( prop ) {
return obj2Props.indexOf( prop ) >= 0;
});
}
return false;
}
In this way we check that both the objects have the same number of properties (otherwise the objects haven't the same properties, and we must return a logical false) then, if the number matches, we go to check if they have the same properties.
这样我们检查两个对象是否具有相同数量的属性(否则对象没有相同的属性,我们必须返回一个逻辑假)然后,如果数量匹配,我们去检查它们是否具有相同的属性特性。
Bonus
奖金
A possible enhancement could be to introduce also a type checking to enforce the match on every property.
一个可能的增强可能是引入类型检查来强制匹配每个属性。
回答by Philip Garrison
If you want deep validation like @speculees, here's an answer using deep-keys(disclosure: I'm sort of a maintainer of this small package)
如果你想要像@speculees 这样的深度验证,这里有一个使用的答案deep-keys(披露:我是这个小包的维护者)
// obj1 should have all of obj2's properties
var deepKeys = require('deep-keys');
var _ = require('underscore');
assert(0 === _.difference(deepKeys(obj2), deepKeys(obj1)).length);
// obj1 should have exactly obj2's properties
var deepKeys = require('deep-keys');
var _ = require('lodash');
assert(0 === _.xor(deepKeys(obj2), deepKeys(obj1)).length);
or with chai:
或与chai:
var expect = require('chai').expect;
var deepKeys = require('deep-keys');
// obj1 should have all of obj2's properties
expect(deepKeys(obj1)).to.include.members(deepKeys(obj2));
// obj1 should have exactly obj2's properties
expect(deepKeys(obj1)).to.have.members(deepKeys(obj2));
回答by Mahima Agrawal
If you are using underscoreJs then you can simply use _.isEqual function and it compares all keys and values at each and every level of hierarchy like below example.
如果您使用 underscoreJs,那么您可以简单地使用 _.isEqual 函数,它会比较每个层次结构级别的所有键和值,如下例所示。
var object = {"status":"inserted","id":"5799acb792b0525e05ba074c","data":{"workout":[{"set":[{"setNo":1,"exercises":[{"name":"hjkh","type":"Reps","category":"Cardio","set":{"reps":5}}],"isLastSet":false,"index":0,"isStart":true,"startDuration":1469689001989,"isEnd":true,"endDuration":1469689003323,"speed":"00:00:01"}],"setType":"Set","isSuper":false,"index":0}],"time":"2016-07-28T06:56:52.800Z"}};
var object1 = {"status":"inserted","id":"5799acb792b0525e05ba074c","data":{"workout":[{"set":[{"setNo":1,"exercises":[{"name":"hjkh","type":"Reps","category":"Cardio","set":{"reps":5}}],"isLastSet":false,"index":0,"isStart":true,"startDuration":1469689001989,"isEnd":true,"endDuration":1469689003323,"speed":"00:00:01"}],"setType":"Set","isSuper":false,"index":0}],"time":"2016-07-28T06:56:52.800Z"}};
console.log(_.isEqual(object, object1));//return true
If all the keys and values for those keys are same in both the objects then it will return true, otherwise return false.
如果这些键的所有键和值在两个对象中都相同,则返回 true,否则返回 false。
回答by speculees
Here is my attempt at validating JSON properties. I used @casey-foster 's approach, but added recursion for deeper validation. The third parameter in function is optional and only used for testing.
这是我验证 JSON 属性的尝试。我使用了 @casey-foster 的方法,但添加了递归以进行更深入的验证。函数中的第三个参数是可选的,仅用于测试。
//compare json2 to json1
function isValidJson(json1, json2, showInConsole) {
if (!showInConsole)
showInConsole = false;
var aKeys = Object.keys(json1).sort();
var bKeys = Object.keys(json2).sort();
for (var i = 0; i < aKeys.length; i++) {
if (showInConsole)
console.log("---------" + JSON.stringify(aKeys[i]) + " " + JSON.stringify(bKeys[i]))
if (JSON.stringify(aKeys[i]) === JSON.stringify(bKeys[i])) {
if (typeof json1[aKeys[i]] === 'object'){ // contains another obj
if (showInConsole)
console.log("Entering " + JSON.stringify(aKeys[i]))
if (!isValidJson(json1[aKeys[i]], json2[bKeys[i]], showInConsole))
return false; // if recursive validation fails
if (showInConsole)
console.log("Leaving " + JSON.stringify(aKeys[i]))
}
} else {
console.warn("validation failed at " + aKeys[i]);
return false; // if attribute names dont mactch
}
}
return true;
}

