bevacqua
bevacqua

Reputation: 48566

Access prototype from child object function

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?

Upvotes: 1

Views: 66

Answers (2)

pawel
pawel

Reputation: 37005

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() );

Upvotes: 0

Pointy
Pointy

Reputation: 414086

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.

Upvotes: 4

Related Questions