我怎样才能检查两个对象具有相同的一组属性名称?

我正在使用节点,摩卡和柴为我的应用程序。 我想testing我返回的结果数据属性是与我的模型对象之一相同的“对象types”。 (非常类似于柴的实例)。 我只想确认这两个对象具有相同的一组属性名称。 我特别对这些房产的实际价值不感兴趣。

比方说,我有像下面的模型人。 我想检查我的results.data具有与预期模型相同的属性。 所以在这种情况下,Person有一个firstName和lastName。

所以如果results.data.lastNameresults.data.firstName都存在,那么它应该返回true。 如果任何一个不存在,它应该返回false。 如果results.data具有诸如results.data.surname之类的任何其他属性,则奖励将会是,那么它将返回false,因为在Person中不存在姓氏。

该模型

 function Person(data) { var self = this; self.firstName = "unknown"; self.lastName = "unknown"; if (typeof data != "undefined") { self.firstName = data.firstName; self.lastName = data.lastName; } } 

你可以序列化简单的数据来检查是否相等:

 data1 = {firstName: 'John', lastName: 'Smith'}; data2 = {firstName: 'Jane', lastName: 'Smith'}; JSON.stringify(data1) === JSON.stringify(data2) 

这会给你类似的东西

 '{firstName:"John",lastName:"Smith"}' === '{firstName:"Jane",lastName:"Smith"}' 

作为一个function…

 function compare(a, b) { return JSON.stringify(a) === JSON.stringify(b); } compare(data1, data2); 

编辑

如果你像你说的那样使用chai,请查看http://chaijs.com/api/bdd/#equal-section

编辑2

如果你只是想检查键…

 function compareKeys(a, b) { var aKeys = Object.keys(a).sort(); var bKeys = Object.keys(b).sort(); return JSON.stringify(aKeys) === JSON.stringify(bKeys); } 

应该这样做。

如果你想检查两个对象是否有相同的属性名称,你可以这样做:

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

这样,你一定要检查两个对象的迭代和可访问的属性。

编辑 – 2013.04.26:

前面的函数可以用下面的方法重写:

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

通过这种方式,我们检查两个对象具有相同数量的属性(否则对象不具有相同的属性,我们必须返回一个逻辑false),那么,如果数字匹配,我们去检查它们是否相同属性。

奖金

一个可能的增强可能是引入一个types检查来强制匹配每个属性。

这里有一个简短的ES6 variadic版本:

 function objectsHaveSameKeys(...objects):boolean { 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); } 

一点性能testing (MacBook Pro – 2,8 GHz Intel Core i7,节点5.5.0):

 var x = {}; var y = {}; for (var i = 0; i < 5000000; ++i) { x[i] = i; y[i] = i; } 

结果:

 objectsHaveSameKeys(x, y) // took 4996 milliseconds compareKeys(x, y) // took 14880 milliseconds hasSameProps(x,y) // after 10 minutes I stopped execution 

如果你想像@ specpeces这样的深度validation,这里是一个使用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); 

或与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)); 

这是我在validationJSON属性的尝试。 我使用@ casey-foster的方法,但增加了recursion进行更深入的validation。 函数中的第三个参数是可选的,仅用于testing。

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

如果你正在使用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 

如果这两个键的所有键和值在两个对象中都是相同的,那么它将返回true,否则返回false。