在Javascript中,为什么应该将具有引用类型的实例变量放在构造函数中?

时间:2017-01-16 06:56:08

标签: javascript constructor prototype

阅读Google开发人员见解的摘录: https://developers.google.com/speed/articles/optimizing-javascript#initializing-instance-variables

将实例变量声明/初始化放在具有值类型(而不是引用类型)初始值的实例变量的原型上(即类型号,布尔值,空值,未定义或字符串的值)。这避免了每次调用构造函数时不必要地运行初始化代码。 (对于初始值取决于构造函数的参数或构造时的某个其他状态的变量,不能这样做。)

例如,而不是:

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_ = []的引用变量时,我们不是运行初始化代码。 (根据Google的例子)?这是不是每次调用构造函数都会创建一个新数组?

1 个答案:

答案 0 :(得分:2)

引用类型的实例属性需要添加到构造函数中,否则在添加到原型时,构造对象的每个实例将共享相同的引用。只是在阅读信息时没关系,但是在打架时会出现问题。请查看以下示例

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.barinstance2.bar是相同的数组,由两个对象共享。