adamdport adamdport - 3 months ago 7
Javascript Question

How can I set a default property for an object that's passed into a constructor?

I'm trying to make a change in one spot to affect the config object passed into all instantiations of an object. The object is made available globally as follows:

function Crayons(){
return {
foo: ThirdPartyFoo
}
}


The object is initialized in my project with
var myFoo = new Crayons().foo({color: "red"});


I'd like to make
{color: "blue"}
the default, so that if someone doesn't pass in a color, blue is set.


I tried doing

function Crayons(){
var fooWithDefaults = function(){
this = new ThirdPartyFoo(arguments); //this is invalid
this.color = "blue"; //and this would overwrite color if it was set
}

return {
foo: fooWithDefaults
}
}


But the
new
keyword is throwing me off, as I don't know how to create a javascript constructor that essentially says
this = new 3rdPartyFoo
.

What am I missing?

Answer

You can either decorate the constructor:

function Crayons(){
  function fooWithDefaults() {
    3rdPartyFoo.apply(this, arguments); // this is what you're looking for
    if (!this.color) // or whatever to detect "not set"
      this.color = "blue";
  }
  fooWithDefaults.prototype = 3rdPartyFoo.prototype; // to make `new` work

  return {
    foo: fooWithDefaults
  }
}

Or you just make it a factory that returns an instance:

function Crayons(){
  function fooWithDefaults(arg) {
    var that = new 3rdPartyFoo(arg); // you should know how many arguments it takes
    if (!that.color) // or whatever to detect "not set"
      that.color = "blue";
    return that;
  }

  return {
    foo: fooWithDefaults
  }
}

Here you can also drop the new when calling var myFoo = Crayons.foo({color: "red"});

An alternative to modifying the instance after its creation would be to decorate the options that are passed in, which is in general the better solution:

function Crayons(){
  function fooWithDefaults(arg) {
    if (!arg.color) // or whatever to detect "not set"
      arg.color = "blue";
    return new 3rdPartyFoo(arg);
  }

  return {
    foo: fooWithDefaults
  }
}