I think the following code will make the question clear.
// My class
var Class = function() { console.log(\"Constructor\"); };
Class.prototype = { method: fu
A simpler, cleaner way with no "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
Because JavaScript doesn't have classes, let me reword your question: How to create a new object based on an existing object without using the new keyword?
Here is a method that doesn't use "new". It's not strictly a "new instance of" but it's the only way I could think of that doesn't use "new" (and doesn't 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 could get fancy and set the prototype, but then you get into cross-browser issues and I'm trying to keep this simple. Also you may want to use "hasOwnProperty" to filter which properties you add to the new object.
There are other ways that use "new" but sort of hide it. Here is one that borrows from the Object.create function in JavaScript: The Good Parts by 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 the Object.create method which will do this much better but is only supported in newer browsers (e.g., IE9, FF4), but you can use a polyfill (something that fills in the cracks), such as ES5 Shim, to get an 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 that helps
Another way:
var factory = function(clazz /*, arguments*/) {
var args = [].slice.call(arguments, 1);
return new function() {
clazz.apply(this, args)
}
}
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;
};
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;
}
Doesn't this work?
function factory(class_, ...arg) {
return new class_(...arg);
}
I don't understand why you can't use new
.