ezraspectre
ezraspectre

Reputation: 3298

What is the most efficient way for checking if an object parameter has all require properties?

In javascript using an object parameter is my preferred way of working with functions. To check that a function has the required parameters I either (Solution 1) loop through all the object parameters properties and throw an error or (Solution 2) wait until a required property is needed and throw an error. Solution two seems efficient but I have to throws in multiple places in the function. Solution 1 seems pragmatic but should probably be a reusable piece of code. Is there another solution I should be looking at?

Upvotes: 0

Views: 87

Answers (5)

Edu Mazarrasa
Edu Mazarrasa

Reputation: 1

If you want to know if object has at least some properties you can use this function without third parameter:

function hasRequiredProperties(propsNeeded, obj, strict) {

  if (strict) return Object.keys(obj).sort().join() == propsNeeded.sort().join();

  for (var i in propsNeeded ) {
    if (!obj.hasOwnProperty(propsNeeded[i])) return false;
  }
  return true;
};

Example:

 options = {url: {
        protocol: 'https:',
        hostname: 'encrypted.google.com',
        port: '80'
      }
    };

    propsNeeded = ['protocol', 'hostname'];

    hasRequiredProperties(propsNeeded, options.url); // true

    hasRequiredProperties(propsNeeded, options.url, true); // false

Upvotes: 0

Amit Joki
Amit Joki

Reputation: 59262

You can actually do this

var propsNeeded = ["prop1", "prop2", "blah", "blah", "blah"], 
obj = {
  prop1: "Hi"
}
function hasRequiredProperties(props, obj){
   return Object.keys(obj).sort().join() == propsNeeded.sort().join();
}
console.log(hasRequiredProperties(propsNeeded, obj)); // false

You can check for single properties like

function hasProperty(propName, obj){
  return obj.hasOwnProperty(propName);
}

Upvotes: 1

user663031
user663031

Reputation:

This is just a general case of checking for presence of keys on a object, which can be done easily enough with

requiredParams.every(function(prop) { return prop in paramObj; })

It almost reads like natural language. "Taking the required parameters, is EVERY one of them IN the parameter object?".

Just wrap this in function checkParams(paramObj, requiredParams) for easy re-use.

More generally, this is the problem of asking if one list (in this case the list of required parameters) is included in another list (the keys on the params object). So we can write a general routine for list inclusion:

function listIncluded(list1, list2) {
    return list1.every(function(e) { return list2.indexOf(e) !== -1; });
}

Then our parameter-checking becomes

function checkParams(paramObj, requiredParams) {
    return listIncluded(requiredParams, Object.keys(paramObj));
}

Upvotes: 0

artm
artm

Reputation: 8584

Using @Amit's answer I'd probably add a method to Object itself:

Object.prototype.hasAllProperties = function(props, fire){
    var result = Object.keys(this).sort().join() == propsNeeded.sort().join();

    if (fire && !result){
        throw new Error('Object does not define all properties');
    }

    return result;
}

and in your function:

function someFunction(myObject){
    var objComplete = myObject.hasAllProperties(["prop1", "prop2", "prop3"], false);
}

Update:

After noticing the problem with @Amit's original answer, here's what I suggest:

Object.prototype.hasAllProperties = function(props, fire){
    var result = true;

    $(props).each(function(i, e){
        if (!this.hasOwnProperty(e) ) {
             result = false;
             return false;
        }
    });

    if (fire && !result){
        throw new Error('Object does not define all properties');
    }

    return result;
}

Upvotes: 0

Matti Mehtonen
Matti Mehtonen

Reputation: 1705

For consistency I would create require method and use it always when some property is required.

var require = function (key, object) {

    if (typeof object[key] === 'undefined') {
        throw new Error('Required property ' + key + ' is undefined');
    }
};

I would test if required property exists as soon as I'm certain that property is needed. Like this:

var example = function (args) {

    require('alwaysRequired', args);

    // some code here which uses property alwaysRequired

    if (args.something) {
        require('sometimesRequired', args);

        // some code here which uses property sometimesRequired
    }
};

Upvotes: 1

Related Questions