I'm trying to get my head around Javascript OO, using the IIFE module pattern to mimic a class:
var MyClass = (function() {
// Constructor
return function() {
return {
foo: 'foo'
}
}
}());
I'm passing arguments with something like:
var MyClass = (function() {
// Constructor
return function(arg) {
return {
foo: function() {
return 'foo'+arg
}
}
}
}());
To mimic classical inheritance I am using the pattern suggested here:
function inherit(base, child, obj) {
child.prototype = Object.create(base.prototype);
child.prototype.constructor = child;
obj&&Object.keys(obj).forEach(function(key){
child.prototype[key] = obj[key];
})
}
var Base = (function() {
var init = function() {};
init.prototype = {
foo: function() {
return "foo";
}
};
return init;
}());
var Child = (function() {
var init = function() {
Base.call(this);
};
inherit(Base, init, {
bar: function() {
return 'bar';
}
});
return init;
}());
So far so good. My only problem is in understanding how to pass parameters to my class constructor when I'm doing inheritance in the above way. I like the fact that in the 'pure' IIFE module I can simply refer to the constructor parameter in any functions defined within it, so that they become closures. But how do I access constructor params when I'm adding these subsequent functions using the constructor variable, as in the inheritance example above? I suppose I could do something like:
var init = function(arg) {
this.theArg = arg;
};
Then I can access it within anything subsequent:
init.prototype = {
foo: function() {
return "foo"+this.theArg;
}
};
And for the child:
var init = function(arg) {
Base.call(this, arg);
};
This makes arg
available to the outside world, so to make it read-only I suppose a getter would work:
var init = function(arg) {
var theArg = arg;
this.getArg = function() { return theArg };
};
On the face of it I can't see anything wrong with that, and I can't think of a better alternative. Is there one? Am I missing something obvious?
I can't think of a better alternative. Is there one?
No. Not in your example.
I like the fact that in the 'pure' IIFE module I can simply refer to the constructor parameter in any functions defined within it, so that they become closures.
You can access args
in each function because, in your first example, you are defining foo
on each object instance separately. Therefore each definition of foo
has a separate closure containing the args
passed when it was defined.
This is also only possible, because foo
is defined within the scope containing your args
.
But how do I access constructor params when I'm adding these subsequent functions ... in the inheritance example above?
By using the classical inheritance patten you found, you are now defining the foo
function on the constructor prototype. This means that only a single foo
definition exists which is inherited by all instances created using your constructor. So foo
can not be made specific to each instance anymore.
As you have figured, it also means foo
is no longer defined inside the scope containing args
and has no direct access.
You are therefore correct by assigning args
to this.thisArgs
which allows foo
to access thisArgs
on each instance. You have made foo
a general case function that can handle any instance it is applied to.
Passing arguments to the IIFE constructor: The IIFE itself is not the constructor, it simply builds the constructor object. The IIFE's scope has long since been returned by the time the constructor itself is invoked.
Am I missing something obvious?
Yes. Javascript is a prototypical language. It was never meant to be like "classical" languages. Just let it be Javascript. :)