I'm trying to define a class that, in its constructor, instantiates other objects and passes them a reference to itself:
var Child = function(m) {
var mother = m;
return {
mother: mother
}
}
var Mother = function() {
var children = makeChildren();
return {
children: children
}
function makeChildren() {
var children = [];
for (var i = 0; i < 10; i++) {
var c = new Child(this); // <--- 'this' is an empty object here
children.push(c)
}
return children;
}
}
This doesn't work, and the Child instances end up with an empty object in their mother
property. What is the proper way to do this?
I'm trying to define a class that, in its constructor, instantiates other objects and passes them a reference to itself:
var Child = function(m) {
var mother = m;
return {
mother: mother
}
}
var Mother = function() {
var children = makeChildren();
return {
children: children
}
function makeChildren() {
var children = [];
for (var i = 0; i < 10; i++) {
var c = new Child(this); // <--- 'this' is an empty object here
children.push(c)
}
return children;
}
}
This doesn't work, and the Child instances end up with an empty object in their mother
property. What is the proper way to do this?
4 Answers
Reset to default 4Javascript's this
is not lexical. This means that makeChildren
gets its own this
instead of getting the Mother
's this
you want.
Set a normal variable to this and use it instead.
var that = this;
function makeChildren(){
blabla = that;
}
I don't think doing this is just enough though. By returning an object from the constructor you ignore the this
. Set things into it:
this.children = children;
instead of returning a new object.
You could try passing a reference to the mother object when you call makeChildren() from within the mother object, something like this maybe:
var Mother = function() {
var children = makeChildren(this);
}
The makeChildren() function can then accept as an argument the reference, which you can use:
function makeChildren(ref)
var c = new Child(ref);
No idea whether or not that will work, but it might be worth a try.
A nested function does not inherit this
from its parent, so the this
within makeChildren()
is not the same as the this
within the Mother constructor unless you explicitly set it when calling makeChildren()
:
var children = makeChildren.call(this);
That should work without any further changes to your code. Have a look at MDN for more detail about .call().
Alternatively you can save a reference to this
and pass that into the function:
var Mother = function() {
var self = this; // <-- new variable
var children = makeChildren();
return {
children: children
}
function makeChildren() {
var children = [];
for (var i = 0; i < 10; i++) {
var c = new Child(self); // <--- change 'this' to 'self'
children.push(c)
}
return children;
}
}
Local variables within a function are accessible to nested functions.
var Child = function(m) {
var mother = m;
return {
mother: mother
}
};
var Mother = function() {
if (!(this instanceof Mother)) {
return new Mother();
}
var that = this;
var makeChildren = function() {
var children = [];
for (var i = 0; i < 10; i++) {
var c = new Child(that); // <--- 'that' is the reference to Mother
children.push(c)
}
return children;
};
var children = makeChildren();
return {
children: children
}
};
then do:
var m = Mother();
The first three lines in the Mother
object ensure that the value of that
is the Mother
instance and not the global object. Without them, you would always have to write:
var m = new Mother();