0

I'm trying to make two instances (constructorOne and constructorTwo) of a function variable called myObjectConstructor. For some reason I get the same result back for both instances when I call getProperty.

//this is one other way of creating a Constructor function
var myObjectConstructor = function(){
    this.myProperty = '';

    init = function(str) {
       this.myProperty = str;
    },

    getProperty = function() {
       return this.myProperty;
    }     

    return {
        init: function () {
            return init.apply(self, arguments);
        },
        getProperty: function () {
            return getProperty.apply(self, arguments);
        }
    }
}

//instantiate our Constructor
var constructorOne = new myObjectConstructor();

//change myProperty of the first instance
constructorOne.init('this is property one');

//instantiate a second instance of our Constructor
var constructorTwo = new myObjectConstructor();

constructorTwo.init('this is property two');

Both constructorOne.getProperty() and constructorTwo.getProperty() will alert "this is property two":

alert(constructorOne.getProperty()); //this will alert 'this is property two'
alert(constructorTwo.getProperty()); //this will still alert 'this is property two'

Here is a demo.

Question is, why does constructorOne.getProperty() not return 'this is property one'?

brinch
  • 2,544
  • 7
  • 33
  • 55
  • Because you are referencing `this` in both objects which has been overwritten in the moment the second object has been initialised. – SaschaM78 Dec 22 '14 at 13:24
  • Because `self` is not defined, and therefore `getProperty` is called in the context of `window` both times. – t.niese Dec 22 '14 at 13:25
  • how to use constructor functions and prototype is explained here: http://stackoverflow.com/a/16063711/1641941 hope it helps. – HMR Dec 22 '14 at 15:19

2 Answers2

6

self is undefined so inside the init function, this is window, so you are always modifying properties of the same object.

You seem to be doing some weird hybrid of the module pattern and standard JavaScript constructor functions. I strongly suggest picking one of the two approaches and sticking to it.

function MyObjectConstructor(){
    this.myProperty = '';
}

MyObjectConstructor.prototype.init = function(str) {
       this.myProperty = str;
};
MyObjectConstructor.prototype.getProperty = function() {
       return this.myProperty;
};
 
//instantiate our Constructor
var constructorOne = new MyObjectConstructor();
 
//change myProperty of the first instance
constructorOne.init('this is property one');
 
//instantiate a second instance of our Constructor
var constructorTwo = new MyObjectConstructor();
 
constructorTwo.init('this is property two');

//alert current myProperty of constructorOne instance
alert(constructorOne.getProperty()); 

 //alert current myProperty of constructorTwo instance
alert(constructorTwo.getProperty()); 

or

function myModule (){
  var myProperty = '';
  return {
    init: function (str) {
       myProperty = str;
    },
    getProperty: function () {
      return myProperty;
    }
  };  
}

//instantiate our Constructor
var constructorOne = myModule();
 
//change myProperty of the first instance
constructorOne.init('this is property one');
 
//instantiate a second instance of our Constructor
var constructorTwo = myModule();
 
constructorTwo.init('this is property two');

//alert current myProperty of constructorOne instance
alert(constructorOne.getProperty()); 

 //alert current myProperty of constructorTwo instance
alert(constructorTwo.getProperty());
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • If I use your first option (with prototype), and have functions in my object that need to call each other, how would I do this? Let's say I have these two functions: MyObjectConstructor.prototype.func1 = function(str) { } MyObjectConstructor.prototype.func2 = function(str) { how to call func1 from here? } – brinch Dec 22 '14 at 13:56
  • You continue to get a reference to the object with `this`: `this.func1()` – Quentin Dec 22 '14 at 13:57
1

A better way of doing this would be using proper prototypes:

function MyObjectConstructor() {
    this.property = '';
}

MyObjectConstructor.prototype.init = function(newProperty) {
    this.property = newProperty;
};

MyObjectConstructor.prototype.getProperty = function() {
    return this.property;
};
Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308