1

Suppose you have

function Thing () {
  this.val = 1;
}

Thing.prototype.some = function () {
  console.log('thing');
};

Thing.prototype.foo = {
  bar: function () {
    console.log(root.val);
  }
};

How would you be able to get a reference to this as in the Thing instance, while still sticking to a prototypal model?

2 Answers 2

4

With that setup, the only way to do it is to explicitly pass the object (the "Thing" instance) as a parameter, or use .call() or .apply().

If you instantiate a "Thing":

var thing = new Thing();

then you can get to that "bar" function as thing.foo.bar. Invoked from that reference:

thing.foo.bar();

the value of this inside "bar" will be the "foo" object on the prototype. You could however use .call():

thing.foo.bar.call(thing);

then this in the invocation of "bar" will indeed be the instantiated "Thing" object.

It's important to keep in mind that, in JavaScript, setting an object property to a function does not create any kind of special relationship between the object and the function. What matters is the relationship(s) discovered when referring to property values in expressions. It's always dynamic, and while the mechanics of following the prototype chain are somewhat dizzying, the rules for how this is determined are pretty simple.

Sign up to request clarification or add additional context in comments.

Comments

0

You can bind function to a context without executing it like call / apply does. Use bind.

For example:

function Thing () {
  this.val = 1;
}

Thing.prototype.some = function () {
  console.log('thing');
};

Thing.prototype.foo = {
      bar: function () {
        console.log(this.val);
      }
  }

var thing = new Thing();
// bind instance's `foo.bar` to `thing` instance
thing.foo.bar = thing.foo.bar.bind( thing );
// now you can call it without providing `thing` as the context every time like wit apply/call
console.log( thing.foo.bar() );

It's event possible to bind foo.bar to an instance of Thing, but then every instance of Thing has foo.bar bound to a shared instance of Thing. I'm not sure if it's a good idea, but it kind of works:

function Thing () {
  this.val = 1;
}

Thing.prototype.some = function () {
  console.log('thing');
};

Thing.prototype.foo = {
      bar: function () {
        console.log(this.val);
      }.bind( new Thing() )
  }

var thing = new Thing();

console.log( thing.foo.bar() );

1 Comment

I guess the only way to really make it the way I wanted, then, would be to loop through those methods and bind in the constructor. Which is awful. Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.