Reputation: 780
Consider the Following Example
var Foo = function(){
this.identity = 'Foo';
};
Foo.prototype.bar = function(){
this.identity = 'bar';
};
var fooInstance = new Foo(),
bar = new fooInstance.bar();
Question
Within bar
, how may I obtain the fooInstance
variable? Is there a way for a child of Foo
to recognize its parent as fooInstance
? For example, how could I create a function in bar
that would return fooInstance
. A slight caveat is that bar must by created using the prototype
command and cannot simply be nested in Foo
to access any Foo
instances that way.
My Ideas and Why They Don't Work
It would be possible to rewrite the functions like so
var Foo = function(){
this.identity = 'Foo';
};
Foo.prototype.createBar = function(){
var parent = this;
function bar(){
this.parent = parent;
this.identity = 'bar';
};
return new bar();
};
var fooInstance = new Foo(),
bar = fooInstance.createBar();
Yet for the purposes of creating easily readable code i would rather not use this approach if not needed.
Further Clarification
Let me put the question in context. I am prototyping on CanvasRenderingContext2D so that all contexts for the canvas element will contain my new method. Lets call that method foo and assume context is a created canvas context. How create a variable like so "new context.foo()" such that the foo function can use the context variable?
Upvotes: 0
Views: 119
Reputation: 665121
how could I create a function in bar that would return fooInstance
If that function is called as a constructor (with new
), you can't really do it. The this
keyword, the only reference to the "parent" (the object on which you called the method) is set to the new instance in a constructor invocation. You can get the reference only with a closure, for example by creating the constructor in the parent's constructor function (which doesn't work for you) or by returning the constructor from a closure on the prototype (which you nearly got in the second example):
Foo.prototype.getBarCoonstructor = function() {
var parentFoo = this;
return function Bar() {
// constructor things
// using "parentFoo" reference
};
};
// Usage:
var bar = new (foo.getBarConstructor()) (); // ugly.
Instead of creating new constructors for every call of getBarConstructor
, you better should put it outside of the method and put parentFoo
as an argument to it. Your idea was already quite good.
function Bar(parent) {
// constructor things, referring "parent"
}
Bar.prototype.… = …;
Foo.prototype.createBar = function() {
return new Bar(this); // passing the Foo instance
};
(@plalx has the same solution, but wrapped in a module closure)
Upvotes: 1
Reputation: 43728
If you need to reference the fooInstance
object from the bar
object, you could use dependency injection like this:
Foo.prototype.bar = function(fooInstance) {
this.identity = 'bar';
this.fooInstance = fooInstance;
};
var fooInstance = new Foo(),
bar = new foo.bar(fooInstance);
You could simplify the creation process by implementing a factory function on Foo
.
Foo.prototype.createBar = (function() {
function Bar(parent){
this.parent = parent;
this.identity = 'bar';
};
return function () {
return new Bar(this);
};
})();
var fooInstance = new Foo(),
bar = fooInstance.createBar();
Upvotes: 2
Reputation: 14004
Foo.prototype.bar
is simply a function on the prototype Object of Foo. There is no way for that function to know of its 'parent' unless you explicitly define it in its scope chain.
I.e. if you would do
var Foo = function(){
this.identity = 'Foo';
};
var fooInstance = new Foo();
Foo.prototype.bar = function(){
console.log(fooInstance); // retrieve from scope
this.identity = 'bar';
};
bar = new foo.bar();
that would work.
Upvotes: 0