JavaScript: how to create a new instance of a class without using a new keyword?

I think the following code will raise the question clearly.

// 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); 
+20
javascript constructor oop instance
Oct. 16 '09 at 23:15
source share
6 answers

Does it work?

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

I do not understand why you cannot use new .

+18
16 Oct. '09 at 23:22
source share

A simpler and clearer way without "factories"

 function Person(name) { if (!(this instanceof Person)) return new Person(name); this.name = name; } var p1 = new Person('Fred'); var p2 = Person('Barney'); p1 instanceof Person //=> true p2 instanceof Person //=> true 
+25
May 31 '12 at 03:23
source share

If you really do not want to use the new keyword, and you are not against only Firefox support, you can install the prototype yourself. There really is no point in doing so, as 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; }; 
+7
Oct. 16 '09 at 23:57
source share

I think a 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; } 
+3
Apr 11 '10 at
source share

Since JavaScript has no classes, let me reformulate your question: how to create a new object based on an existing object without using a new keyword?

Here is a method that does not use "new". This is not strictly a “new instance”, but the only way I could think of was not to use a “new one” (and does not use any ECMAScript 5 features).

 //a very basic version that doesn't use 'new' function factory(clazz) { var o = {}; for (var prop in clazz) { o[prop] = clazz[prop]; } return o; }; //test var clazz = { prop1: "hello clazz" }; var testObj1 = factory(clazz); console.log(testObj1.prop1); //"hello clazz" 

You can get fancy and install a prototype, but then you get into cross-browser issues, and I'm trying to keep it simple. You can also use "hasOwnProperty" to filter the properties that you add to the new object.

There are other ways to use the "new", but it seems to hide them. Here is the one that takes from the Object.create function in JavaScript: Good details of Douglas Crockford :

 //Another version the does use 'new' but in a limited sense function factory(clazz) { var F = function() {}; F.prototype = clazz; return new F(); }; //Test var orig = { prop1: "hello orig" }; var testObj2 = factory(orig); console.log(testObj2.prop1); //"hello orig" 

EcmaScript 5 has an Object.create method that will do it much better, but is only supported in new browsers (e.g. IE9, FF4), but you can use polyfill (something that fills the cracks) like ES5 Shim to get implementation for older browsers. (See John Resig's article on new ES5 features, including Object.create .)

In ES5, you can do it like this:

 //using Object.create - doesn't use "new" var baseObj = { prop1: "hello base" }; var testObj3 = Object.create(baseObj); console.log(testObj3.prop1); 

I hope this helps

+2
Apr 22 '11 at 15:00
source share

Another way:

 var factory = function(clazz /*, arguments*/) { var args = [].slice.call(arguments, 1); return new function() { clazz.apply(this, args) } } 
+1
Jun 04
source share



All Articles