Search code examples
javascriptjavascript-objects

Javascript - Object State


I may be approaching this incorrectly...

I'm trying to keep track of an objects state internally and use it to call modified methods:

createObject = function() {
  this.a = 1

  this.method1 = function() {
  if (this.a == 1 ) {
    //do stuff
    this.a = 0
  }
}

var x = new createObject()

Unfortunately, state isn't being internally tracked. If I change the properties of another object it works perfectly however:

otherObj = { a:1 }

createObject = function() {

  this.method1 = function() {
  if (this.a == 1 ) {
    //do stuff
    otherObject.a = 0
  }

}

var x = new createObject()

Is this the correct way to approach this?


Solution

  • You have problem, because this in method1() is different from this in outer function. That's because in JS functions create scope.

    First approach

    So you might want a to be a variable, not a property of this:

    createObject = function() {
      // 'a' is now available here...
      var a = 1
    
      this.method1 = function() {
        // ... and here as well.
        if (a == 1 ) {
          a = 0
        }
      }
    }
    

    Second approach

    Alternatively, you might want to hold a reference to the outer this in a helper variable (called self in this example):

    createObject = function() {
      // 'self' is a regular varialbe, referencing 'this'
      var self = this;
      this.a = 1
    
      this.method1 = function() {
        // Here, self !== this, because 'this' in method1() 
        // is different from 'this' in outer function.
        // So we can access 'self.a':
        if (self.a == 1 ) {
          //do stuff
          self.a = 0
        }
      }
    }
    

    Third approach

    Finally, you can also use bind() to tie outer this to your method1():

    var createObject = function () {
        this.a = 1
    
        this.method1 = function () {
            console.log(this.a);
            if (this.a == 1) {
                this.a = 0
            }
        }.bind(this);
        // ^ note `bind(this)` above. Now, 'this' inside 'method1'
        // is same as 'this' in outer function.
    }
    

    Here is a doc for bind(). Note that it's not available in IE < 9.