我完全理解为什么最好使用原型而不是构造函数来定义类方法,(Use of 'prototype' vs. 'this' in JavaScript?)但是,我最近遇到了HashMap class它定义了原型中的count
属性和构造函数中的map
属性:
js_cols.HashMap = function(opt_map, var_args) {
/**
* Underlying JS object used to implement the map.
* @type {!Object}
* @private
*/
this.map_ = {};
/...
}
/**
* The number of key value pairs in the map.
* @private
* @type {number}
*/
js_cols.HashMap.prototype.count_ = 0;
在原型中声明像count
这样的实例属性而不是在构造函数中说this.count_ = 0;
是否有好处?如果是这样,为什么不js_cols.HashMap.prototype.map_ = {};
?
编辑:提出了一个类似的问题Why declare properties on the prototype for instance variables in JavaScript,并且“默认值”是作为用例引发的,但没有解释为什么这比定义构造函数中的默认值。
答案 0 :(得分:5)
我认为HashMap
类不是在原型中声明实例属性的最好例子。请考虑使用Response
类:
function Response() {
this.headers = {};
}
Response.prototype.statusCode = 200;
Response
的所有实例都将共享statusCode
的{{1}} - 字面上,内存中的相同数字将在所有实例中共享。如果您希望服务器在大多数情况下使用状态代码200 进行响应,这是有意义的。那些需要不同状态代码的200
可以覆盖其默认Requests
,这会在内存中创建一个新数字。
即。如果您有10,000个并发请求,其中5个是404,那么您在内存中只有6个数字代表所有10,000个statusCode
。
总之,如果您希望大多数实例在大多数时间共享相同的默认值,那么使用原型可能是值得的。否则,你可以将它归结为编码风格。 (显然对于静态属性,总是使用原型。)
注意请参阅Lucas的答案,了解为什么作为对象的属性(例如statusCodes
或map
)不能在原型中:所有实例都将共享相同的属性引用,因此对该引用的任何更新都将更新所有实例。
答案 1 :(得分:1)
这取决于它的使用方式,你确定count_
没有定义散列桶的数量,而不是散列中有多少项的确切数量?如果您期望值保持常量并且对于类的所有实例都是全局的,那么在原型中定义变量是很好的,因为无论您使用多少个类实例,都只使用一个变量的内存。
答案 2 :(得分:1)
适用于count_
,但不适用于map_
。
count_
是整数值,而map_
是对象引用。如果HashMap
实例更新count_
,它实际上会在自己的实例上创建count_
属性。
但是,如果它向map_
插入内容,因为所有实例共享相同的map_
引用,所有实例最终都会在地图中显示相同的值。这不起作用,这就是每个实例在其构造函数中获得不同map_
引用的原因。
对于count_
属性,它在原型中声明为默认值。如果它在构造函数中实例化,它将是相同的。我想这只是编码风格的问题。
答案 3 :(得分:0)
原型设计是JavaScript OOP扩展和继承的方式。所以这是使代码可重用的方法。您可能是构造函数的程序员,但是如果他们重用您的代码,其他人可能希望扩展您的对象。你可能不希望,他们在你的代码中乱砍。
好的描述在这里:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model
问候
阿克塞尔
答案 4 :(得分:0)
考虑代表银行客户的客户,其利率可能会发生变化。对于每个客户,您必须计算利息,这是根据银行的政策设定的。在这种情况下,存在一个变量 interest ,其值对于某些客户是相同的,此变量的更改也必须传播给所有客户。让我们用JavaScript模拟它。
var Customer = function(name, amount) {
this.name = name;
this.amount = amount;
};
Customer.prototype.interest = 10; //default value. which changes later
Customer.prototype.computeInterest = function() {
this.amount += this.amount * this.interest / 100; //assume they are savings account
};
var me = new Customer('Ajinkya', 100);
var you = new Customer('RKBWS47', 1000);
var somebody = new Customer('Jon Doe', 10000);
me.computeInterest();
you.computeInterest();
somebody.computeInterest();
console.log(me.amount); //110
console.log(you.amount); //1100
console.log(somebody.amount); //11000
Customer.prototype.interest = 20; //yay!
me.computeInterest();
you.computeInterest();
somebody.computeInterest();
console.log(me.amount); //132
console.log(you.amount); //1320
console.log(somebody.amount); //13200
对于这些方法也是如此。它们由类的所有实例共享,并将 this 变量设置为调用对象或实例。您还可以使用在构造函数上定义的属性来模拟静态方法或我想要记住它们的方式,即在类上调用的方法。在我们的示例中使用this.interest
并不允许我们在me
,you
和somebody
之间共享它。
编辑:我已经回答假设HashMap示例用于说明您的问题。