web-dev-qa-db-ja.com

2つのオブジェクトが同じプロパティ名のセットを持っていることを確認するにはどうすればよいですか?

Node、mocha、chaiをアプリケーションに使用しています。返された結果データプロパティが、モデルオブジェクトの1つと同じ「オブジェクトのタイプ」であることをテストします。 (chaiのinstanceofと非常に似ています)。 2つのオブジェクトが同じプロパティ名のセットを持っていることを確認したいだけです。 プロパティの実際の値には特に興味がありません。

次のようなモデルPersonがあるとします。 results.dataに、期待されるモデルと同じプロパティがすべてあることを確認します。したがって、この場合、firstNameとlastNameを持つPerson。

したがって、results.data.lastNameおよびresults.data.firstName両方が存在する場合、trueを返す必要があります。どちらかが存在しない場合、falseを返す必要があります。ボーナスは、results.dataにresults.data.surnameのような追加のプロパティがある場合、姓がPersonに存在しないため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;
  }
}
49
dan27

単純なデータをシリアル化して、同等性を確認できます。

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

編集

あなたが言うようにチャイを使用している場合は、チェックアウト 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);
}

それを行う必要があります。

84
Casey Foster

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

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
22
schirrmacher

両方のオブジェクトが同じプロパティ名を持っているかどうかを確認したい場合、これを行うことができます:

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を返す必要があります)。プロパティ。

ボーナス

可能な拡張機能は、すべてのプロパティで一致を強制する型チェックも導入することです。

9
Ragnarokkr

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

または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));
7
Philip Garrison