第一个是构造函数,因此可以通过 a 扩展prototype
,您可以通过instanceof
结果是否是这种类型的 Instance 进行测试。缺点:如果您忘记了new
-keyword,您的代码将会崩溃(除非您为 each 编写解决方法constuctor
)
当你实例化一个新对象时,你不能真正使用apply()
构造函数来传递参数数组;另一方面,不要那样做,即使你可以/可以。
第二个是工厂,而不是构造函数。无论您是否使用new
-keyword 都是独立的。通过这个实现,它创建了看起来相同但不共享类型或原型的对象(尽管底层 JS 引擎将它们识别为相似,因此只要它们具有相同的属性,它们就共享相同的隐藏类,添加到相同的顺序,......不同的主题)
长话短说,性能和内存占用都不会受到这种方法的影响(不再)
但是您无法检查它们是否属于同一类型,并且您没有可能影响所有实例的共享原型(可能是赞成或反对)。
我的 goto 方法如果我需要继承,是两者的混合:(
如果我只需要一个数据对象,我通常使用工厂和普通对象)。
function Book(conf) {
var book = Object.create(Book.prototype);
//a book like this usually has multiple configs/properties
if(typeof conf === "object"){
for(var k in conf) book[k] = conf[k];
}else if(conf){
//assuming that I get at least the name passed
book.name = String(conf);
}
return book;
}
//I have a prototype that can be extended
//with default-values for example; no idea for a good method
//to add to the prototype in this example ;)
Book.prototype.numPages = 0;
//but I can also use it like a plain function; no error if you
var myBook1 = Book("Peter Pan");
var myBook2 = Book({
name: "American Gods",
author: "Neil Gaiman"
});
如果我将以下行添加到函数的顶部,我还可以将其用作将任何内容转换为 Instance 的方法,Book
而无需克隆已经存在的实例
function Book(conf) {
//with this simple line I can also use this as a function to cast anything into a "Book"
if(conf instanceof Book) return conf;
var book = Object.create(Book.prototype);
//...
return book;
}
var data = [
"Peter Pan",
{name: "American Gods"},
//...
];
var books = data.map(Book);
在我看来,我通过这种方法获得了两全其美的好处。