Reputation: 4330
I have a Mootools class:
var Foo = new Class({
initialize: function(param1, param2) {
// do stuff
}
});
The values to initialize Foo with are in an array:
a = ['value1', 'value2'];
How can I use the values from a
to initialize an instance of Foo
?
Upvotes: 0
Views: 393
Reputation: 36
There is no direct way of calling a constructor with an array of arguments to be expanded, like you do it with Function.apply
.
If you create a new instance of your class with new Foo()
, MooTools calls the constructor (initialize
) implicitly passing it the arguments you called Foo() with. However, initialize
is still present as a method of the instance, so you could simply call it "again" like so:
var myFoo = new Foo();
myFoo.initialize.apply(myFoo, ['value1', 'value2']);
But this is really bad practice, because a constructor is normally not meant to be called twice and chances are that you run into problems.
Another way is to create the instance without letting MooTools call the constructor. First you need a plain instance and then call initialize
as a method of the instance. This is rather hackish, but could be realized like this:
var Foo = new Class({
initialize: function(param1, param2) {
this.param1 = param1;
this.param2 = param2;
},
getParams: function() {
console.log(this.param1 + ', ' + this.param2);
}
});
Class.createInstance = function(klass, args) {
klass.$prototyping = true;
var inst = new klass();
klass.$prototyping = false;
inst.initialize.apply(inst, args);
return inst;
}
var myFoo = Class.createInstance(Foo, ['a', 'b']);
// returns "a, b"
myFoo.getParams();
$prototyping
is the switch for MooTools to not call the constructor.
Upvotes: 2
Reputation: 26165
I'd go with extending the proto of the class so it does not care (see Felix' answer).
var Foo = new Class({
initialize: function(param1, param2) {
console.log(param1, param2);
}
});
(function(){
var oldFoo = Foo.prototype.initialize;
Foo.implement({
initialize: function(){
var args = typeOf(arguments[0]) == 'array' ? arguments[0] : arguments;
return oldFoo.apply(this, args);
}
});
}());
new Foo(['one', 'two']); // one two
new Foo('three', 'four'); // three four
It involves less hacking and is probably easier to understand/maintain than creating special constructor abstractions.
if you can, you can even do
var Foo2 = new Class({
Extends: Foo,
initialize: function () {
var args = typeOf(arguments[0]) == 'array' ? arguments[0] : arguments;
this.parent.apply(this, args);
}
});
new Foo2(['one', 'two']);
new Foo2('three', 'four');
Thus, making a very clear abstraction without modifying the parent proto and expectation - and keeping pesky SOLID principles assholes happy :D
Upvotes: 3