Question

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?

Was it helpful?

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.

OTHER TIPS

This result can by achieved this days by using something like this:

const obj = {};

obj.state = {
  isLoaded: false,
  isOpen: false,
};

obj.setState = (newState) => {
  // Before using obj.setState => result Object { isLoaded: false, isOpen: false }
  console.log(obj.state); 
  obj.state = { ...obj.state, ...newState };
  // After using obj.setState ex. obj.setState({new:''}) => result Object { isLoaded: false, isOpen: false, new: "" }
  console.log(obj.state); 
};

That approach is more or less how it would work in ReactJS, you have source object in this example obj.state and setter obj.setState

What the obj.setState does is it gets values from current obj.state and new obj then combines them into new updated obj saved instead of current obj.state

You don't have to put both in one object like I did but seems like a good way to organize things

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top