我很好奇以下OOP javascript技术之间的区别。他们似乎最终做了同样的事情但被认为比另一个更好?
function Book(title) {
this.title = title;
}
Book.prototype.getTitle = function () {
return this.title;
};
var myBook = new Book('War and Peace');
alert(myBook.getTitle())
VS
function Book(title) {
var book = {
title: title
};
book.getTitle = function () {
return this.title;
};
return book;
}
var myBook = Book('War and Peace');
alert(myBook.getTitle())
答案 0 :(得分:46)
第二个并不真正创建实例,它只返回一个对象。这意味着您无法利用instanceof
等运营商。例如。在第一种情况下,您可以if (myBook instanceof Book)
检查变量是否是Book的类型,而第二种情况则会失败。
如果要在构造函数中指定对象方法,这是正确的方法:
function Book(title) {
this.title = title;
this.getTitle = function () {
return this.title;
};
}
var myBook = new Book('War and Peace');
alert(myBook.getTitle())
虽然在这个例子中两者的行为方式完全相同,但存在差异。使用基于闭包的实现,您可以拥有私有变量和方法(只是不要在this
对象中公开它们)。所以你可以做一些事情,比如:
function Book(title) {
var title_;
this.getTitle = function() {
return title_;
};
this.setTitle = function(title) {
title_ = title;
};
// should use the setter in case it does something else than just assign
this.setTitle(title);
}
Book函数之外的代码不能直接访问成员变量,它们必须使用访问器。
其他最大的不同是表现;由于使用闭包包含一些开销,基于原型的分类通常要快得多。您可以在本文中了解性能差异:http://blogs.msdn.com/b/kristoffer/archive/2007/02/13/javascript-prototype-versus-closure-execution-speed.aspx
答案 1 :(得分:12)
哪个更好有时可以根据其使用情况来定义。
我在原型和关闭编码方法之间做出选择的三个限制因素(我积极使用两者):
<强> 1。性能/资源强>
对于对象的单个实例,任何一种方法都可以。任何速度优势都很可能是微不足道的。
如果我要实例化其中的100,000个,比如建立一个图书馆,那么原型方法将是首选。所有.prototype。如果使用关闭方法,则只创建一次函数,而不是创建100,000次这些函数。资源不是无限的。
<强> 2。压缩强>
如果压缩效率很重要,请使用关闭方法(例如:大多数浏览器库/模块)。请参阅以下说明:
压缩 - 原型方法
function Book(title) {
this.title = title;
}
Book.prototype.getTitle = function () {
return this.title;
};
是否将YUI压缩为
function Book(a){this.title=a}Book.prototype.getTitle=function(){return this.title};
节省约18%(所有空格/制表符/退货)。此方法需要公开变量/函数(this.variable = value),因此每个原型函数都可以访问它们。因此,这些变量/函数无法在压缩中进行优化。
压缩 - 关闭方法
function Book(title) {
var title = title; // use var instead of this.title to make this a local variable
this.getTitle = function () {
return title;
};
}
是否将YUI压缩为
function Book(a){var a=a;this.getTitle=function(){return a}};
节省约33%。可以优化局部变量。在具有许多支持功能的大型模块中,这可以显着节省压缩。
第3。项目管理
在一个有多个开发人员的项目中,他们可以使用同一个模块,我更喜欢该模块的原型方法,如果不受性能或压缩的限制。
对于浏览器开发,我可以覆盖我自己的“test.js”中的“production.js”中的producton.prototype.aFunction(后面的文字),以便进行测试或开发,而无需修改“生产” .js“,可能由不同的开发人员积极开发。
我不是复杂的GIT存储库检出/分支/合并/冲突流的忠实粉丝。我更喜欢简单。
此外,通过测试平台重新定义或“劫持”模块功能的能力可能是有益的,但是在这里解决起来太复杂了......
答案 2 :(得分:11)
前一种方法是如何使用JavaScript。后者是更现代的技术,部分由Douglas Crockford推广。这种技术更加灵活。
你也可以这样做:
function Book(title) {
return {
getTitle: function () {
return title;
}
}
}
返回的对象只有一个名为getTitle
的访问器,它将返回保存在闭包中的参数。
Crockford在Private Members in JavaScript上有一个很好的页面 - 绝对值得一读,看看不同的选项。
答案 3 :(得分:5)
还有一点关于引擎盖下的可重用性。在具有Function.prototype
属性用法的第一个示例中,Book函数对象的所有实例将共享getTitle
方法的相同副本。第二个片段将使Book
函数执行创建并保留在堆“书架”中的本地可闭合 book
对象的不同副本。
function Book(title) {
var book = {
title: title
};
book.getTitle = function () {
return this.title += '#';
};
return book;
}
var myBook = Book('War and Peace');
var myAnotherBook = Book('Anna Karenina');
alert(myBook.getTitle()); // War and Peace#
alert(myBook.getTitle()); // War and Peace##
alert(myAnotherBook.getTitle()); // Anna Karenina#
alert(myBook.getTitle());// War and Peace###
另一方面,原型成员存在于对象的所有new
实例的唯一副本中。所以这是他们之间的一个微妙的区别,由于闭合技巧,第一次叹息不是很明显。
答案 4 :(得分:0)
这是一篇文章about this 一般来说,从Book.prototype预订inharets。在第一个示例中,您将函数添加到getTitle Book.prototype