【问题标题】:In Javascript, why should instance variables with reference type be put in the constructor?在Javascript中,为什么要将引用类型的实例变量放在构造函数中?
【发布时间】:2017-05-30 23:17:48
【问题描述】:

阅读 Google 开发者洞察的摘录: https://developers.google.com/speed/articles/optimizing-javascript#initializing-instance-variables


将实例变量声明/初始化放在原型上,用于具有值类型(而不是引用类型)初始化值(即类型 number、Boolean、null、undefined 或 string)的实例变量。这避免了每次调用构造函数时不必要地运行初始化代码。 (对于初始值取决于构造函数的参数或构造时的某些其他状态的实例变量,不能这样做。)

例如,而不是:

foo.Bar = function() {
  this.prop1_ = 4;
  this.prop2_ = true;
  this.prop3_ = [];
  this.prop4_ = 'blah';
};

用途:

foo.Bar = function() {
  this.prop3_ = [];
};

foo.Bar.prototype.prop1_ = 4;

foo.Bar.prototype.prop2_ = true;

foo.Bar.prototype.prop4_ = 'blah';

我理解将具有值类型的变量放入函数原型背后的逻辑,但是当我们有像 this.prop3_ = []; 这样的引用变量时,我们不是在运行初始化代码吗? (根据谷歌的例子)?这不会在每次调用构造函数时创建一个新数组吗?

【问题讨论】:

  • "这不会在每次调用构造函数时创建一个新数组吗?" - 确实如此,这就是重点。
  • 没有“引用类型”或“值类型”。 ECMA-262 §6.1 中列出了有效的语言类型。变量有一个值,该值可能是 primitive value 或 reference(又名 Reference Specification Type)。

标签: javascript constructor prototype


【解决方案1】:

引用类型的实例属性需要添加到构造函数中,否则当添加到原型时,构造对象的每个实例将共享相同的引用。只是读取信息时可以,但是修改时出现问题。请检查以下示例

var Test = function () {
    this.foo = [];
};

Test.prototype.bar = [];

var instance1 = new Test();
var instance2 = new Test();

instance1.foo.push(1);
instance1.bar.push(1);
instance2.foo.push(2);
instance2.bar.push(2);

console.log(instance1.foo, instance1.bar); // [1], [1,2]

虽然instance1.bar.push只被调用了一次,但数组有两个值,因为instance1.bar和instance2.bar是同一个数组,被两个对象共享。

【讨论】:

    猜你喜欢
    • 2010-11-26
    • 2014-05-07
    • 2021-05-03
    • 1970-01-01
    • 2019-10-13
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    相关资源
    最近更新 更多