1

I have a class like this:

 function Foo() {
   this._current = -1;
 }
 Foo.prototype.history = {};
 Foo.prototype.history.back = function () {
   if (this._current === undefined) {
     return alert("this._current is undefined");
   }
   --this._current; // `this` is the history object
 };

How can I access the Foo instance in the back method?

I solution I see is to do something like this:

var f = new Foo();
f.history.back = f.history.back.bind(f);

Is there a better solution? Doing that for every Foo instance does not sound good for me.


Here is an example:

function Foo() {
  this._current = -1;
}
Foo.prototype.history = {};
Foo.prototype.history.back = function() {
  if (this._current === undefined) {
    return alert("this._current is undefined");
  }
  --this._current; // `this` is the history object
};

var f = new Foo();
f.history.back();

I know it's supposed to be so, but what's the correct way to solve this type of problem?

Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474
  • Your `.bind()` solution won't really work - every `Foo` instance *shares* the same `history` object. – Pointy Jun 26 '15 at 13:17
  • Maybe dumb question .. but why isn't `history` a property of the instance instead of the prototype? – yas Jun 26 '15 at 13:18
  • possible duplicate of https://stackoverflow.com/questions/15884096/organize-prototype-javascript-while-perserving-object-reference-and-inheritance or https://stackoverflow.com/questions/16502467/prototype-deep-scope-of-this-to-access-instances-scope – Bergi Jun 26 '15 at 13:25

1 Answers1

5

The fundamental problem in your code is that you have only one history object shared between all instances of Foo. You must make it one history per instance. A solution would be this:

function FooHistory(foo){
 this._foo = foo;
}
FooHistory.prototype.back = function() {
  if (this._foo._current === undefined) {
    return alert("this._foo._current is undefined");
  }
  this._foo._current--; 
};

function Foo() {
 this._current = -1;
 this.history = new FooHistory(this);
}
var f = new Foo();
f.history.back();

(you probably want to have _current in the FooHistory instance instead of the Foo instance, I tried to change as little code as possible)

Note that other solutions are possible, depending on the larger view. If you don't have any state to store in the history object then you could also have Foo.prototype.history() return an object with a property linking back to the Foo instance. Then you would call f.history().back().

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758