我认为以下代码会使问题清楚。
// 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);
答案 0 :(得分:27)
没有“工厂”的更简单,更清洁的方式
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
答案 1 :(得分:18)
这不起作用吗?
function factory(class_) {
return new class_();
}
我不明白为什么你不能使用new
。
答案 2 :(得分:7)
如果确实不想使用new
关键字,并且您不介意只支持Firefox,则可以自行设置原型。但是,这并没有任何意义,因为你可以使用Dave Hinton的答案。
// 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;
};
答案 3 :(得分:3)
我认为独立于浏览器的解决方案会更好
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;
}
答案 4 :(得分:3)
因为JavaScript没有类,所以让我重新提出一个问题:如何在不使用new关键字的情况下基于现有对象创建新对象?
这是一种不使用“new”的方法。它不是严格意义上的“新实例”,但它是我能想到的唯一不使用“新”的方式(并且不使用任何ECMAScript 5功能)。
//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"
你可以得到幻想并设置原型,但是你会遇到跨浏览器的问题而我正试图保持这个简单。此外,您可能希望使用“hasOwnProperty”来过滤添加到新对象的属性。
还有其他方法可以使用“新”但有点隐藏它。这是借用JavaScript: The Good Parts by Douglas Crockford中的Object.create函数:
//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有Object.create方法可以做得更好,但只在较新的浏览器(例如,IE9,FF4)中支持,但你可以使用polyfill(填补空白的东西) ,例如ES5 Shim,以获得旧浏览器的实现。 (见John Resig's article on new ES5 features including Object.create)。
在ES5中你可以这样做:
//using Object.create - doesn't use "new"
var baseObj = { prop1: "hello base" };
var testObj3 = Object.create(baseObj);
console.log(testObj3.prop1);
我希望有帮助
答案 5 :(得分:2)
另一种方式:
var factory = function(clazz /*, arguments*/) {
var args = [].slice.call(arguments, 1);
return new function() {
clazz.apply(this, args)
}
}