为什么在原型中声明实例属性而不是在构造函数中声明

Why declare an instance property in prototype instead of constructor?

本文关键字:声明 构造函数 实例 原型 为什么 属性      更新时间:2023-09-26

我完全理解为什么使用原型而不是构造函数来定义类方法更好,(即使用'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的实例将共享200statusCode——实际上,所有实例将共享相同的内存数量。如果您希望服务器在大多数情况下使用状态码200 进行响应,那么这是有意义的。那些需要不同状态码的Requests可以覆盖它们默认的statusCode,这会在内存中创建一个新的数字。

。如果您有10,000个并发请求,其中5个是404请求,那么您只需要在内存中使用6个数字来表示所有10,000个statusCodes

总而言之,如果您希望许多实例在大多数情况下共享相同的默认值,那么使用prototype可能是值得的。否则,您可以将其归因于编码风格。(显然,对于静态属性,总是使用prototype。)

注意参见Lucas的回答,为什么一个属性是一个对象(例如mapheaders)不能在原型中:所有实例将共享相同的引用,因此任何对该引用的更新都会更新所有实例

这取决于它是如何使用的,你确定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, yousomebody之间共享它。

编辑:我已经回答假设HashMap的例子是用来说明你的问题。