0

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?

2
  • Not sure, have you tried something like: Foo.apply(this,a); ? Commented Jan 28, 2013 at 14:49
  • This does not work for initializiation of the class. Commented Jan 28, 2013 at 14:51

2 Answers 2

3

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

Sign up to request clarification or add additional context in comments.

Comments

2

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.

2 Comments

+1 but #1 pattern is not good as it will call initialize twice. #2 is better but hacky as it goes into internals / outside the API. I'd go for extending the class to take an array or arguments or a list.
I agree with @DimitarChristoff, this looks a little bit hacky. But I did not know, that it could work like this, so +1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.