Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/421.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何检查两个对象是否具有相同的属性名称集?_Javascript_Node.js_Mocha.js_Chai - Fatal编程技术网

Javascript 如何检查两个对象是否具有相同的属性名称集?

Javascript 如何检查两个对象是否具有相同的属性名称集?,javascript,node.js,mocha.js,chai,Javascript,Node.js,Mocha.js,Chai,我在应用程序中使用node、mocha和chai。我想测试返回的结果数据属性是否与一个模型对象的“对象类型”相同(非常类似于chai的实例)。我只想确认这两个对象具有相同的属性名称集我对房产的实际价值不感兴趣。 假设我有下面这样的模范人物。我想检查results.data是否具有与预期模型相同的所有属性。所以在这个例子中,有名字和姓氏的人 因此,如果results.data.lastName和results.data.firstName都存在,那么它应该返回true。如果其中一个不存在,则应返回

我在应用程序中使用node、mocha和chai。我想测试返回的结果数据属性是否与一个模型对象的“对象类型”相同(非常类似于chai的实例)。我只想确认这两个对象具有相同的属性名称集我对房产的实际价值不感兴趣。

假设我有下面这样的模范人物。我想检查results.data是否具有与预期模型相同的所有属性。所以在这个例子中,有名字和姓氏的人

因此,如果
results.data.lastName
results.data.firstName
都存在,那么它应该返回true。如果其中一个不存在,则应返回false。如果results.data具有results.data.姓氏等任何附加属性,那么它将返回false,因为姓氏不存在于个人中

此型号

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 compare(a, b) {
  return JSON.stringify(a) === JSON.stringify(b);
}
compare(data1, data2);
编辑 如果你像你说的那样使用chai,请查看

编辑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));
通过这种方式,您可以确保只检查这两个对象的iterable和accessible属性

编辑-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),然后,如果数量匹配,我们将检查它们是否具有相同的属性

奖金


一个可能的增强可能是引入类型检查,以强制每个属性上的匹配。

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);
}
性能测试(MacBook Pro-2,8 GHz Intel Core i7,Node 5.5.0):


下面是我验证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;

}
//比较json2和json1
函数isValidJson(json1、json2、showincole){
如果(!showincole)
showincole=false;
var aKeys=Object.keys(json1.sort();
var bKeys=Object.keys(json2.sort();
对于(变量i=0;i
如果你想要像@specules这样的深度验证,这里有一个使用
深度键的答案(披露:我是这个小软件包的维护者)

或使用
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));

如果您使用的是下划线,那么您可以简单地使用u.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。

要比较两个对象及其所有属性,我遵循了这段代码,它不需要tostring()或json compare

if(user1.equals(user2))
{
console.log(“两者相等”);

}
我不想检查属性的实际值,只想检查属性名称。抱歉,这正是我想要的…JS新手,不知道如何进行属性反射。谢谢!+对于idea,请注意陷阱-参数的顺序在方法中很重要:
JSON.stringify({b:1,a:1})
不同于
JSON.stringify({a:1,b:1})
它现在可以工作,因为大多数浏览器对对象键保持某种顺序,但ecma规范不需要它,因此,这段代码可能会失败。如果您需要深入检查/嵌套对象,我认为这也可以。和凯西的非常相似。感谢您这不是唯一检查
obj2
是否具有
obj1
的属性,反之亦然?此函数检查
obj1
的所有属性是否都存在于
obj2
中,因此它们具有相同的属性。但反之亦然。如果您想跳过对具有不同属性数的对象的迭代,那么必须对这两个对象中的属性数进行检查,如果它们不匹配,则返回一个逻辑false。看起来它只检查第一级属性,对吗?@Mirko yes。请注意,检查是通过在对象中查找相同的键来完成的。这不是基于他们的有效价值观。(例如,我可以将两个
name
键分配给一个字符串,一个分配给一个数字,并且检查仍然会返回真实性)。但是,您可以通过在对象键的情况下实现某种恢复性来调整它,但是它需要扩展对数据类型的检查。这里的问题是只检查两个对象的键。这些值是不相关的。您的解决方案检查键和值。OP的问题是比较键和仅键。在某些情况下,您的代码将报告不平等
// 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);
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));
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