views:

423

answers:

3

I think the following code will make the question clear.

// My class
var Class = function() { console.log("Constructor"); };
Class.prototype = { method: function() { console.log("Method");} }

// Creating an instance with new
var object1 = new Class();
object1.method();
console.log("New returned", object1);

// How to write a factory which can't use the new keyword?
function factory(clazz) {
    // Assume this function can't see "Class", but only sees its parameter "clazz".
    return clazz.call(); // Calls the constructor, but no new object is created
    return clazz.new();  // Doesn't work because there is new() method
};

var object2 = factory(Class);
object2.method();
console.log("Factory returned", object2);
+2  A: 

Doesn't this work?

function factory(class_) {
    return new class_();
}

I don't understand why you can't use new.

Dave Hinton
the stipulation was no use of "new"
Jimmy
Darn yes! This works great. I thought (incorrectly!) that I couldn't use the "new" keyword in this case, but of course it doesn't matter if new takes a "class" that was just defined, or if that "class" is passed in parameter to a function and the "new" is called later. Me stupid.
Alessandro Vernet
+3  A: 

If you really don't want to use the new keyword, and you don't mind only supporting Firefox, you can set the prototype yourself. There's not really any point to this though, since you can just use Dave Hinton's answer.

// This is essentially what the new keyword does
function factory(clazz) {
    var obj = {};
    obj.__proto__ = clazz.prototype;
    var result = clazz.call(obj);
    return (typeof result !== 'undefined') ? result : obj;
};
Matthew Crumley
A: 

I guess browser independent solution would be better

function empty() {}

function factory(clazz /*, some more arguments for constructor */) {
    empty.prototype = clazz.prototype;
    var obj = new empty();
    clazz.apply(obj, Array.prototype.slice.call(arguments, 1));
    return obj;
}
Dima Vidmich
Dima, why is this more browser independent than the solution proposed by Dave?
Alessandro Vernet
cause "obj.__proto__ = something" doesn't work in all browsersand Dave's solution doesn't support arguments for constructor
Dima Vidmich