1

I am currently converting an Object constructor from the form of

function Obj(arg1, arg2, arg3, arg4, ..., argN-1, argN) {
  this.name = arg1;
  this.field = arg2;
  this.etc = arg3;
  ...
} //Obj

to the form of

function Obj() {
  var args = Array.prototype.slice.call(arguments);

  var defaultArgs = {
      'field'  :  default
      ...
  };

 ... check args, etc

 } //Obj

Here is my code so far:

function DSObj () {
  var args = Array.prototype.slice.call(arguments);

  var defaultArgs = {
  'fields' : values or functions returning values
  ...
  };

  var options = {};

  for (var i in defaultArgs) {

    if (typeof(args[i] == 'undefined')) { 
      options[i] = defaultArgs[i]; 
    } else { 
      options[i] = args[i]; 
    } //check if the user supplied this argument
  } //for each possible argument

  for (var name in options) {
    this.name = options[name]; //trying to make fields - obviously wrong
  } //for each final parameter
} //constructor for DSObj

So, what I need help with is the last part of the above constructor. I just started programming JavaScript around a week ago, and my education goes about as far as reading a beginners syntax book. So, if there is a better way to do this other than the stupid and direct way, please let me know. The reason that I can't just reference the options array above is that all of the methods written for this object in some way use the "this.method" paradigm. Please. Guise. Help.

RobG
  • 142,382
  • 31
  • 172
  • 209
Illumin8s
  • 121
  • 1
  • 8
  • Try `this[name] = options[name]`. With Javascript objects, you can treat indexes like object properties. – Kodlee Yin Jun 26 '14 at 00:40
  • This cant work, as `args` is an array with integer keys and `defaultArgs` is an object with non-numeric keys. You wouldn't find any `i` in both. – Bergi Jun 26 '14 at 00:45
  • `if (typeof(args[i] == 'undefined'))` will always return `true`, since `(args[i] == 'undefined')` will return a boolean, which `typeof` will convert to the string 'boolean', and any string evaluates to true. You probably want `if (typeof args[i] == 'undefined')`. – RobG Jun 26 '14 at 01:23
  • @KodleeYin—that's because indexes **are** object properties. :-) – RobG Jun 26 '14 at 01:24
  • Thanks Guys! All very good feedback. I will try out your suggestions. – Illumin8s Jun 26 '14 at 14:58

1 Answers1

2

I think you need bracket notation instead of dot one:

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

Be aware that for...in loops iterate inherited properties, you may want to check options.hasOwnProperty(name) to avoid that.

Also note that when you iterate defaultArgs, i is each property. But args is indexed with numbers, not you custom keys.

You can use something like

function DSObj () {
  var argNames = ['fields', /*...*/],
      defaultArgs = [ /* ..., ... */];
  for (var i=0, l=arguments.length; i<l; ++i) {
      this[argNames[i]] = arguments[i] || defaultArgs[i];
  }
}

Or if arguments[i] can be falsy, then

this[argNames[i]] = arguments[i] !== void 0 ? arguments[i] : defaultArgs[i];
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • `defaultArgs` was initialised with an object literal, there are no custom prototypes. We can safely assume that there are no inherited enumerable properties, a `hasOwnProperty()` test is unnecessary. – Bergi Jun 26 '14 at 01:42
  • @Bergi Maybe another script modified `Object.prototype`. But yeah, it can be unnecessary, it was just a warning. – Oriol Jun 26 '14 at 02:41
  • Then it would be that script's fault [if it's not done correctly](http://stackoverflow.com/q/13296340/1048572). You shouldn't need to care. – Bergi Jun 26 '14 at 10:24
  • Thanks, the first part worked exactly how I thought it should. It's amazing how flexible JavaScript can be. As for the code suggestions -- I was given code that originally had something similar, so the modificiations you suggested make my life easier. – Illumin8s Jun 26 '14 at 14:59