简体   繁体   中英

What is the best way to check that multiple variables are set?

This is more of a general practices question.

The language I am working with is Javascript. I have a function that is getting an object with many variables (okay, just 10 variables). What is the best way to make sure this function is getting all the required variables and that they are all set?

I know, I know, why not just use a if statement. That's a big chunk of if statements! As I grow as a programmer, I know that may not be the best method for this. I'm looking for a shortcut actually. How would you check a large sum of variables for existence and non-blank values?

This is a pretty neat way of handling validation, I usually use this when checking for required fields in form inputs.

var theObj = { /* object loaded from server */ }

function checkTheObj(testObj)
{
  var requiredKeys = ['key1', 'key2', 'key3'];
  for(var keyPos = 0; keyPos < requiredKeys.length; keyPos++)
  {
    if(typeof(testObj[requiredKeys[keyPos]]) == 'undefined')
    {
      return false;
    }
  }
  return true;
}

if(checkTheObj(theObj))
{
  //do stuff
}

You can of course tweak this to return or throw an exception telling the first missing field (or use an internal array to return a list of all missing fields).

function objectHas(obj, properties) {
    var len = properties.length
    for (var i=0; i<len; i++) {
        if (i in properties) {
            if((!obj.hasOwnProperty(properties[i])) || (!obj.propertyIsEnumerable(properties[i]))) {
                return false;
            }
        }
    }
    return true;
}

Usage:

if(objectHas(user, ["email", "password", "phone"])) {
    console.log("awesome");
}

It's simple, but does the job.

Edit: On an ideal world you could extend the Object prototype for an even neater syntax such as if(object.has(["a", "b", "c"])) , but apparently extending the Object prototype is the incarnation of evil so a function will have to do :)

First of all, you need to improve your understanding of these languages and learn the correct terminology.

  1. There is no (single) language named "Javascript" at all. You are implicitly using several languages here (depending on the runtime environment), all of which are ECMAScript implementations, and one of which is Netscape/Mozilla JavaScript (in Mozilla-based software like Firefox) .
  2. An object does not have variables, it has properties ( not : keys). Global code, function code, and eval code can have variables; that is a different (but similar) concept.
  3. The function is not getting an object, it is being passed a reference to an object as argument .

As a programmer, you should already know that you can do repetitive tasks in a loop; the associated statements in ECMAScript implementations are for , for - in , while and do . So you do not have to write several if statements.

You can access the properties of an object in two ways, where property is the property name :

  1. Dot notation: obj.property
  2. Bracket notation: obj["property"]

The second one is equivalent to the first if the property name is an identifier, ie if it follows certain naming rules. If the property name is not an identifier or if it is variable, you have to use the second one. This also shows that all property names are string values. So you can store the name of a property as value of a variable or another property, and then access the variable or property in the property accessor. In the following, a property name ( property ) is stored in and used from a variable:

var propertyName = "property";
obj[propertyName]

Combining that with a loop allows you to iterate over certain properties of an object. Unfortunately, the solutions presented so far are flawed in two respects: A for - in statement iterates only over the enumerable properties of an object, and it does so in arbitrary order. In addition, it also iterates over the enumerable inherited properties (which is why one solution requires the hasOwnProperty() call).

A simple, sure and efficient way to iterate only over certain properties of an object in a defined order looks as follows:

var propertyNames = ['name1', 'name2', 'name3'];
for (var i = 0, len = propertyNames.length; i < len; ++i)
{
  /* … */ myObject[propertyNames[i]] /* … */
}

This works because propertyNames refers to an Array instance, which encapsulates an array data structure. The elements of an array are the properties of the Array instance that have integer indexes from 0 to 65535 (2 32 −1). Because indexes are not identifiers (they start with a decimal digit), you have to use the bracket property accessor syntax (some people misunderstand this and refer to all ECMAScript objects as "arrays", even call them "associative arrays" and […] the "Array operator"). Therefore, propertyNames[i] evaluates to the values of the elements of the array in each iteration as i is increased by 1 each time. As a result, myObject[propertyNames[i]] accesses the property with that name in each loop.

Now, to find out whether the property is set, you need to define what that means. Accessing a property that does not exist results in the undefined value (not in an error). However an existing property may also have the undefined value as its value.

If "not set" means that the object does not have the property (but may inherit it), then you should use hasOwnProperty() as used in Mahn's solution.

If "not set" means that the object does not have the property and does not inherit it, then you should use the in operator, provided that the object is not a host object (because the in operator is not specified for them ):

if (propertyNames[i] in obj)

If "not set" means that the object either has or inherits the property, but the property has the undefined value, or the object neither has nor inherits the property, then you should use the typeof operator as used in Bob Davies' and aetaur's solutions (but the latter approach using Array.prototype.every() is less compatible as-is; that method was not specified before ECMAScript Edition 5, and is not available in IE/JScript < 9).

There is a third option with ECMAScript Edition 5.x, the Object.keys() method which (despite its name) returns a reference to an Array instance that holds the names of all not-inherited properties of the argument:

var propertyNames = Object.keys(obj);

/* continue as described above */

It is a good idea to emulate Object.keys() if it is not built-in, as this algorithm is frequently useful.

This expression returns true, if all variables from variableNameList (list of required variable names) set in object o :

variableNameList.every(function(varName){ return typeof o[varName] !== 'undefined'; });

You can use underscore _.all function instead of native every , and underscore _.isUndefined instead of typeof ... .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM