为什么在原型中声明实例属性而不是在构造函数中声明
Why declare an instance property in prototype instead of constructor?
我完全理解为什么使用原型而不是构造函数来定义类方法更好,(即使用'prototype'和& # 39;这个# 39;在JavaScript中?)然而,我最近遇到一个HashMap类,它在原型中定义了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_ = {};
呢?
编辑:一个类似的问题被问到,为什么在JavaScript实例变量的原型上声明属性,并且"默认值"被作为一个用例提出,但是没有解释为什么这比仅仅在构造函数中定义默认值更可取。
我不认为HashMap
类是在原型中声明一个实例属性的好处的最好例子。考虑一个Response
类:
function Response() {
this.headers = {};
}
Response.prototype.statusCode = 200;
所有Response
的实例将共享200
的statusCode
——实际上,所有实例将共享相同的内存数量。如果您希望服务器在大多数情况下使用状态码200 进行响应,那么这是有意义的。那些需要不同状态码的Requests
可以覆盖它们默认的statusCode
,这会在内存中创建一个新的数字。
。如果您有10,000个并发请求,其中5个是404请求,那么您只需要在内存中使用6个数字来表示所有10,000个statusCodes
。
注意参见Lucas的回答,为什么一个属性是一个对象(例如map
或headers
)不能在原型中:所有实例将共享相同的引用,因此任何对该引用的更新都会更新所有实例
这取决于它是如何使用的,你确定count_
没有定义哈希桶的数量,而不是哈希中有多少项的确切计数吗?如果您希望在类的所有实例中值保持不变和全局,则在原型中定义变量是很好的,因为无论创建多少个类实例,都只使用一个变量的内存。
适用于count_
,但不适用于map_
。
count_
为整数值,map_
为对象引用。如果一个HashMap
实例更新了count_
,它将在自己的实例上创建一个count_
属性。
但是,如果它向map_
插入一些东西,因为所有实例共享相同的map_
引用,所有实例将在映射中以相同的值结束。这是行不通的,这就是为什么每个实例在其构造函数中得到不同的map_
引用的原因。
对于count_
属性,它在原型中被声明为默认值。如果在构造函数中实例化,则是相同的。我想这只是编码风格的问题。
原型是JavaScript OOP扩展和继承的方式。因此,这是使代码可重用的方法。您可能是构造函数的程序员,但其他人可能希望扩展您的对象,如果他们重用您的代码。你可能不希望他们在你的代码中乱做。
好的描述在这里:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model
的问候Axel
考虑类Customer代表银行的客户,该银行的利率可能会发生变化。对于每个客户,您必须计算利息,这是根据银行的政策设置的。在此场景中,有一个变量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的例子是用来说明你的问题。
- 在OPP JS中,您可以从构造函数访问原型函数内部声明的方法
- 构造函数中的私有函数声明是否在每次创建实例时重新实例化
- JavaScript:构造函数声明相对于其使用的位置,当在函数内时
- ES7 类:在构造函数之外声明属性
- 需要在构造函数内部声明一个方法而不是将其声明为原型方法的情况示例
- 在构造函数和原型中声明javascript对象方法
- 如何处理在 JavaScript 中的构造函数中声明的变量
- 在Javascript中,函数声明是创建构造函数的唯一方法
- JavaScript:声明构造函数中的所有成员,以备文档之用
- 习语Javascript编码风格-何时在原型上声明函数,何时在函数构造函数内声明函数
- 为什么原型必须在构造函数之外声明
- 为什么函数在构造函数中声明时不使用new关键字
- 为什么我得到“构造函数必须在声明时初始化”谷歌闭包编译器警告
- 为什么在原型中声明实例属性而不是在构造函数中声明
- 可以在javascript构造函数中声明不可枚举的属性吗?
- 在构造函数中声明属性
- 如何在构造函数中使用静态助手方法(不需要在构造函数中声明它们)
- 声明构造函数的优点/缺点
- 具有开放端构造函数参数的参数属性声明
- 在构造函数angular 2中声明属性