2

I have two JS objects, I want to check if the first Object has all the second Object's keys and do something, otherwise, throw an exception. What's the best way to do it?

function(obj1, obj2){
    if(obj1.HasAllKeys(obj2)) {
         //do something
    }
    else{
         throw new Error(...);
    } 
};

For example in below example since FirstObject has all the SecondObject's key it should run the code :

FirstObject
{
    a : '....',
    b : '...',
    c : '...',
    d : '...'
}
SecondObject
{    
    b : '...',    
    d : '...'
}

But in below example I want to throw an exception since XXX doesnt exist in FirstObject:

FirstObject
{
    a : '....',
    b : '...',
    c : '...',
    d : '...'
}
SecondObject
{    
    b : '...',    
    XXX : '...'
}
Am1rr3zA
  • 7,115
  • 18
  • 83
  • 125

4 Answers4

5

You can use:

var hasAll = Object.keys(obj1).every(function(key) {
  return Object.prototype.hasOwnProperty.call(obj2, key);
});
console.log(hasAll); // true if obj2 has all - but maybe more - keys that obj1 have.

As a "one-liner":

var hasAll = Object.keys(obj1).every(Object.prototype.hasOwnProperty.bind(obj2));
Andreas Louv
  • 46,145
  • 13
  • 104
  • 123
  • Any reason to use `.call` instead of just `obj.hasOwnProperty(key)`? – Barmar Nov 19 '15 at 21:32
  • @Barmar See: See: https://stackoverflow.com/questions/12017693/why-use-object-prototype-hasownproperty-callmyobj-prop-instead-of-myobj-hasow – Andreas Louv Nov 19 '15 at 21:33
  • Hmm, it seems like creating an object that doesn't inherit from `Object` is a recipe for disaster.... – Barmar Nov 19 '15 at 21:34
  • Yes my friend, or if you override `hasOwnProperty` yourself. – Andreas Louv Nov 19 '15 at 21:35
  • Although in the latter case, maybe the caller should respect the programmer's replacement. He wanted his object to have custom semantics. – Barmar Nov 19 '15 at 21:36
  • `var hasOwn = object.hasOwnProperty || Object.prototype.hasOwnProperty;` – Barmar Nov 19 '15 at 21:37
  • @Barmar I'm thinking more about JSON here, consider this: `JSON.parse('{"hasOwnProperty": true, "more_data": 1234}')` – Andreas Louv Nov 19 '15 at 21:39
  • @dev-null based on http://stackoverflow.com/a/22074727/140903 doest it really matter how we check the key? or your way Object.prototype.hasOwnProperty is the best way? – Am1rr3zA Nov 19 '15 at 21:40
  • @Am1rr3zA The main thing to consider is whether to use `key in obj` or (`obj.hasOwnProperty(key)`/`Object.prototype.hasOwnProperty.call(obj, key)`), See: https://stackoverflow.com/questions/13632999/if-key-in-object-or-ifobject-hasownpropertykey – Andreas Louv Nov 19 '15 at 21:41
  • my secondObject is Object{startDate: '2400-12-01T03:45:00.000Z'} and my firstObject is Object{startDate: Object{dependencies: [], builder: function () { ... }}, endDate: Object{dependencies: [], builder: function () { ... }}, count: Object{dependencies: [], builder: function () { ... }}, baseline: Object{dependencies: [], builder: function () { ... }}, baselines: Object{dependencies: [], builder: function () { ... }}} but your solution is still return false – Am1rr3zA Nov 19 '15 at 21:47
  • it's weird then , I just copied your code and pasted it in my code and it's always return false so my code always throw an exception. The purpose of code is to use second object to replace some of the values of firstObject. but I don't want to add new key that's why I want to check whether all the keys exist in first object or not. – Am1rr3zA Nov 19 '15 at 21:55
5

You can write a function to iterate and check:

function hasAllKeys(requiredObj, secondObj) {
    for (var key in requiredObj) {
        if (!secondObj.hasOwnProperty(key)) {
            return false;
        }
    }

    return true;
}

hasAllKeys(SecondObject, FirstObject);
tymeJV
  • 103,943
  • 14
  • 161
  • 157
  • I want something to be in one line like python :), can we avoid for loop and checking one by one? – Am1rr3zA Nov 19 '15 at 21:32
  • Javascript doesn't have list comprehensions, it's harder to make one-liners for things like this. – Barmar Nov 19 '15 at 21:32
  • @Am1rr3zA Even if you don't see the iterations they are still happening, if anything the solution that tymeJV have provided is the fastest. – Andreas Louv Nov 19 '15 at 21:37
1

You can use jQuery's $.map method as follows:
$.map(a,function(value, key) {return b[key];}).length != b.length

Valerio
  • 110
  • 4
  • Using a framework when the original question is clearly looking for plain JavaScript is generally frowned upon (particularly for something as trivial as this), plus, given the typos, you clearly haven't tested it. Answers should either be tested or at least you should mention that you haven't tested it and why. – blm Nov 19 '15 at 22:12
-1

Another way to do this, that seems to work fine as well.

   const o1 = {
              a : '....',
              b : '...',
              c : '...',
              d : '...'
            },

         o2 = {
             b : '...',
             d : '...',
          };

///////////////////////
///// I. IN ONE LINE
///////////////////////
/**/
/**/  if(Object.keys(o2).every(key =>
/**/       key in o1
/**/       // Object.keys(o1).includes(key)
/**/       // Object.keys(o1).filter(x => x==key).length
/**/  ))
/**/  console.log(true);
/**/  else throw new Error("...");
/**/
///////////////////////


///////////////////////
///// II. IN A FUNCTION
///////////////////////
/**/
/**/    var hasAll = (o1 , o2) => {
/**/      let r = Object.keys(o2).every(key =>
/**/        // Object.keys(o1).includes(key)
/**/        // key in o1
/**/        // Object.keys(o1).filter(x => x==key).length
/**/
/**/         Object.keys(o1)
/**/         .reduce((acc,act,arr) =>
/**/            acc && (key in o1) // , true
/**/         )
/**/
/**/      );
/**/      return r;
/**/    }
/**/
/**/ let cond = hasAll(o1 , o2);
/**/
/**/ console.log(cond);
/**/
/**/ if (cond) console.log(true)
//   /**/ else throw new Error("At least, one key doesn'e exist");
/**/
/**/ ////////
/**/
/**/ cond = hasAll(o2 , o1);
/**/
/**/ console.log(cond);
/**/
/**/ if (cond) console.log(true)
/**/ else throw new Error("At least, one key doesn'e exist");
/**/
///////////////////////