In Javascript, I would like to define a class with an inner (or nested) class. Within the inner class I'd like to be able to get access to the parent instance. How can I do this efficiently?
Some code will show what I mean. Suppose I define a class, MyType1, which exposes several properties and one function, SayHello
:
(function(){
MyType1 = function(name){
this.TypeName = "MyType1";
this.Name = name;
};
MyType1.prototype.SayHello = function() {
say(this.Name + " says hello...");
};
})();
Ok, now, starting from there, I want to add an "inner class" to MyType1, so I add some new code so that it looks like this:
(function(){
MyType1 = function(name){
this.TypeName = "MyType1";
this.Name = name;
var parentName = name;
this.Child = function(name) {
this.Description = parentName + "'s child, " + name;
};
this.Child.prototype.Introduce = function() {
say(this.Description + ", greets you...");
};
};
MyType1.prototype.SayHello = function() {
say(this.Name + " says hello...");
};
})();
Now I can use these classes like this:
var x = new MyType1("Victor");
x.SayHello();
var c = new x.Child("Elizabeth");
c.Introduce();
that all works. But it defines a new Child function (or type, if you like) for every instance of MyType1. What I'd like to do is get access to the parent class scope, without resorting to that inefficiency. Something like this:
(function(){
MyType2 = function(name){
this.TypeName = "MyType2";
this.Name = name;
this.Prop1 = 1872;
var parentName = name;
};
MyType2.prototype.SayHello = function() {
say(this.Name + " says hello...");
};
var c1 = function(name) {
this.Description = parentName + "'s child, " + name;
// ^^ no go! ^^
};
c1.prototype.Introduce = function() {
say(this.Description + ", greets you...");
};
MyType2.prototype.Child = c1;
})();
But, this doesn't work. The parentName
var is out of scope, of course.
Is there an efficient way for the Child instance (in the constructor, or in any class function) to gain access to the parent (MyType2) instance?
I know that I could define the Child class to be an independent, non-nested class, then in the ctor for that, just pass the Parent instance. But this creates N references to the parent instance, one for every Child instance. That seems like an inefficiency I'd like to avoid.
thanks for any tips.
EDIT - the reason I want the Child to have access to the parent instance, is that the parent holds an object that is fairly expensive to create - something like a db connection - and I'd like the child to be able to utilize that thing.
In Javascript, I would like to define a class with an inner (or nested) class. Within the inner class I'd like to be able to get access to the parent instance. How can I do this efficiently?
Some code will show what I mean. Suppose I define a class, MyType1, which exposes several properties and one function, SayHello
:
(function(){
MyType1 = function(name){
this.TypeName = "MyType1";
this.Name = name;
};
MyType1.prototype.SayHello = function() {
say(this.Name + " says hello...");
};
})();
Ok, now, starting from there, I want to add an "inner class" to MyType1, so I add some new code so that it looks like this:
(function(){
MyType1 = function(name){
this.TypeName = "MyType1";
this.Name = name;
var parentName = name;
this.Child = function(name) {
this.Description = parentName + "'s child, " + name;
};
this.Child.prototype.Introduce = function() {
say(this.Description + ", greets you...");
};
};
MyType1.prototype.SayHello = function() {
say(this.Name + " says hello...");
};
})();
Now I can use these classes like this:
var x = new MyType1("Victor");
x.SayHello();
var c = new x.Child("Elizabeth");
c.Introduce();
that all works. But it defines a new Child function (or type, if you like) for every instance of MyType1. What I'd like to do is get access to the parent class scope, without resorting to that inefficiency. Something like this:
(function(){
MyType2 = function(name){
this.TypeName = "MyType2";
this.Name = name;
this.Prop1 = 1872;
var parentName = name;
};
MyType2.prototype.SayHello = function() {
say(this.Name + " says hello...");
};
var c1 = function(name) {
this.Description = parentName + "'s child, " + name;
// ^^ no go! ^^
};
c1.prototype.Introduce = function() {
say(this.Description + ", greets you...");
};
MyType2.prototype.Child = c1;
})();
But, this doesn't work. The parentName
var is out of scope, of course.
Is there an efficient way for the Child instance (in the constructor, or in any class function) to gain access to the parent (MyType2) instance?
I know that I could define the Child class to be an independent, non-nested class, then in the ctor for that, just pass the Parent instance. But this creates N references to the parent instance, one for every Child instance. That seems like an inefficiency I'd like to avoid.
thanks for any tips.
EDIT - the reason I want the Child to have access to the parent instance, is that the parent holds an object that is fairly expensive to create - something like a db connection - and I'd like the child to be able to utilize that thing.
Share Improve this question edited Jan 22, 2011 at 15:21 Cheeso asked Jan 22, 2011 at 15:10 CheesoCheeso 193k105 gold badges484 silver badges734 bronze badges 12- 3 Ugh, yet more abuse of Javascript to bring in "OOP" nonsense. This language does not have classes: if you want them, use something that does! – Lightness Races in Orbit Commented Jan 22, 2011 at 15:23
- 1 You may find this useful: blog.niftysnippets/2009/09/… It's a set of helper functions (and explanation thereof) that provides a simple, but efficient, means of creating "subclasses" of "classes" created via prototypical inheritance. Looks like you're doing that fairly manually, so it may save you some trouble. – T.J. Crowder Commented Jan 22, 2011 at 15:24
- 2 @Tomalek: You're quite right, of course, JavaScript doesn't have classes. It is object-oriented and it does have inheritance, though. – T.J. Crowder Commented Jan 22, 2011 at 15:25
- 2 @Crowder : I'm not doing prototypal inheritance. It's a nested/inner class. There is no inheritance in this example. @Vidas - the anon fn is just for scoping help in my code module. It adds nothing to the example. @Tomalak - sounds like you have hangups about what I do with my code. Hmmm. Ever think about seeing a therapist about that? – Cheeso Commented Jan 22, 2011 at 20:04
- 2 @LightnessRacesinOrbit abominations like this? developer.mozilla/en-US/docs/Web/JavaScript/… – Lorenzo Polidori Commented Jun 30, 2013 at 12:03
6 Answers
Reset to default 3It would probably help you out if you do away with notions like "type", "class", etc. when dealing with javascript. In javascript, there is no differentiation from "type", "class", "function", "instance", or "object" -- it's "object" all the way down.
Since every "type" is an "object" and is mutable, you get nothing of the sort of strong-typed efficiency gains you might get from Java or C++ by reusing a single type definition. Think of the "new" operator in javascript as something like "clone the definition and call the constructor", after which the definition of the instance could still be changed.
So go with your first, working example: you won't get any gains by doing something different.
This is what I came up after many hours:
var Parent = function() {
this.name = "Parent";
this.Child = Child;
this.Child.prototype.parent = this;
}
var Child = function() {
}
var parent = new Parent();
var child = new parent.Child();
console.log(child.parent.name);
This way you can instantiate as many Parents as you want, with their Childs underneath, and every Child instance will have access to it's parent instance through the variable parent.
The only way I can think of is to pass in the parent object to the Child constructor:
MyType2.Child = function (parent, name) {
this.parent = parent;
this.name = name;
this.Description = this.parent.name + "'s child, " + name;
};
And instantiate it with:
var x = new MyType2("Victor");
var c = new MyType2.Child(x, "Elizabeth");
My justification is that it makes more sense that the Child
constructor is a "static" property of MyType2
, instead of the instantiated object x
in your example, since we are talking about types here, which are the same across all instances of MyType2
.
I haven't tested this, but you should be able to use JSON for this:
//code here
var number = {
real : {
value : 0, //default value
rational : {
integer : {
isNegative : false,
value : 0 //default value
}
}
},
imaginary : {
//code
}
};
var number2 = Object.create(number.rational.integer.prototype);
Now there may be many issues with this, functional or stylistic. But it is an alternative from the other approaches posted here.
This is one way to do it. This declares an inner object - which is kinda like declaring an inner class and immediately getting an instance of it. A reference to the outer class is simply added as a object attribute in the declaration.
// ES6 - example of an inner object.
class DancingFoo {
constructor(radio) {
this._radioListener = {
outer: this,
onIsPlaying() { this.outer._dancing = true; },
onStoppedPlaying() { this.outer._dancing = false; }
}
radio.attachListener(this._radioListener);
}
}
or if you want an inner class you can create instances of later...
// ES6 inner class example
class DancingFoo {
constructor(radio) {
let RadioListener = class {
constructor(outer) { this.outer = outer; }
onIsPlaying() { this.outer._dancing = true; }
onStoppedPlaying() { this.outer._dancing = false; }
}
radio.attachListener(new RadioListener(this));
}
}
Old thread but I found it trying to do a similar thing. Here's my solution, to use a class with constructor. The parent initializes the class and passes itself to the child's constructor which sets a variable back to it's parent.
const myClass = new class {
#privateVar = "private var";
myFunc() {
return "My function";
}
private() {
return this.#privateVar;
}
nestedClass = new class {
#nestedPrivate = "nested private var";
#parent;
constructor(myParent) {
this.#parent = myParent;
}
nestFunc() {
return "My other function";
}
nestPrivate() {
return this.#nestedPrivate;
}
nestParentTest() {
return this.#parent.myFunc();
}
}(this)
}
console.log(myClass.nestedClass.nestParentTest()); // "My function"