views:

3104

answers:

4

I've seen many javascript objects that have a 'init' method that you pass in values to in order to setup the object.

How do they internally handle the initializations of their private variables when passed in a array of name/value pairs like:

myObject.init( {prop1: "blah", prop2: "asdf", ..., propn: "n"} );

Specifically, some of these values can be optional, so how would you setup defaults and then override them if the name/value pair was passed in during the init.

A: 

You could use a ternary operator to check whether an element of the initialisation array is set, and use it if it is, or use a default if not. For example, assuming the initialization data is passed as an object called init....

var myObject = {
  init: function(opts) {
     this.foo=(typeof(opts.foo)!="undefined")?opts.foo:'default value';
  }
}

Alternatively, you could just copy init array overriding previously set values

var myObject = {
  init: function(opts) {
      this.foo='default value';

      for (name in opts)
      {
         this[name]=opts[name];
      }
  }

Note that an idiom like

this.foo = opts.foo || 'some default';

Fails if opts.foo is set to a value which evaluates to false, e.g. 0

Paul Dixon
+1  A: 

oh lets see

edit: updated, this actually works

 
function myObject(){}

myObject.prototype.init = function (argObj)
{
    if (!argObj)
    {
     argObj = new Object();
    }

    var abc = (argObj['abc'] != undefined) ? argObj['abc'] : "default value 1";
    var defg = (argObj['defg'] != undefined) ? argObj['defg'] : "default value 2";
}
Allen
fails if args['abc'] evaluates as false
Paul Dixon
right, fixed, thanks :)
Allen
still broken, what if I pass {abc:0}? I get the default value instead.
Paul Dixon
heh, good catch Paul, I wonder how many occurrences of that I have in old code! Anyway, I fixed it, its not pretty but it works.
Allen
Use the identity comparator !== for comparison with undefined.
bobince
+4  A: 
var myObject = {
  init: function(options) {
    this.foo = options.foo || 'some default';
    this.bar = options.requiredArg;

    if (!this.bar) raiseSomeError();
  }
}
Squeegy
this also fails if options.foo evaluates as false
Paul Dixon
I suppose if you really need to support that case:this.foo = options.foo == null ? 'some default' : options.foo;
Squeegy
+2  A: 

The cleanest way I can think of would be to use a defaults object that contains all of the default properties as follows:

function init( args ) {
    this.value = 'value' in args ? args.value : defaults.value;
}

You could even iterate over the default object using a for loop so that you don't have to keep track of which properties you want the object to contain.

You should use the "in" operator since it is possible to actually set the value of a property to undefined. It is valid to set a property to undefined and in that case it is actually considered set, the only way to ensure that a value was not set is to check that it isn't in the object at all.

Michael Roberts