0

I've have a JS class that has some default properties. I want to be able to pass in an options object to override the defaults plus some additional ones that aren't defaulted. I'm using lodash's extend method in my constructor to accomplish this.

One of the default properties is an array. If I instantiate the first instance and push a new value into the array, when I instantiate the second object, the default array contains the object I pushed into the first instance.

Take this code for example...

MyClass = (function() {
  var defaults = {
    myArr: [],
    myProp: 'I\'m a default value'
  };

  function MyClass(options) {
    // console.log(defaults)
    if(typeof options === 'object') {
      return _.extend(this, defaults, options);
    }
    else {
      return _.extend(this, defaults);
    }
  }

  return MyClass;
})();

var myObj = new MyClass({foo: 'bar'})
myObj.myArr.push('baz')
var mySecondObj = new MyClass();
console.log(mySecondObj) // MyClass {myArr: Array[1]}

I expect mySecondObj.myArr to be an empty array.

How is it that when I push a value into myObj.myArr, defaults.myArr somehow gets changed and is used for subsequent instances of the class?

Barmar
  • 741,623
  • 53
  • 500
  • 612

2 Answers2

3

When you merge the object properties from defaults to this with _.extend you're merely creating a reference to the array. So when the array reference in one instance is updated, all the the references reflect that change.

You could clone the object to get around this:

_.cloneDeep(defaults)

DEMO

Or use a simpler constructor:

function MyClass(options) {
  var defaults = {
    myArr: [],
    myProp: 'I\'m a default value'
  }
  if (typeof options === 'object') {
    _.extend(this, defaults, options);
  } else {
    _.extend(this, defaults);
  }
}

DEMO

Barmar
  • 741,623
  • 53
  • 500
  • 612
Andy
  • 61,948
  • 13
  • 68
  • 95
1

Simple put: You created a closure.

Inside your self-executing function you create another function, the function you created inherit defaults from it's parent-self-executing function, when you return the function to MyClass any object creation will have the same reference for those defaults(the defaults object), there is no defaults object created each time you create a class and that is why it's always the same one.

Community
  • 1
  • 1
Aviel Fedida
  • 4,004
  • 9
  • 54
  • 88