Here它说:
在实例变量的原型上放置实例变量声明/初始化,使用值类型(而不是引用类型)初始化值(即类型号,布尔值,空值,未定义或字符串的值)。这避免了每次调用构造函数时不必要地运行初始化代码。 (对于初始值依赖于构造函数的参数或构造时的某个其他状态的变量,不能这样做。)
它给出了以下示例,而不是:
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';
现在,我创建了两个foo.Bar w.r.t的实例。第二种情况:
foo = {}
f1 = new foo.Bar()
f2 = new foo.Bar()
然后测试:
f1.prop1_ // gives 4
f1.prop1_ = 5 // changed it
f2.prop1_ // still gives 4
Object.getPrototypeOf(f1) === Object.getPrototypeOf(f2) // true
现在我的问题是:虽然f1
和f2
共享相同的原型,但每个原型似乎都有不同的范围(附件?),因此,他们有自己的prop1_副本;这意味着发生了单独的内存分配。为什么这会带来性能提升?
答案 0 :(得分:1)
它更高效,因为你没有在构造函数中运行一堆赋值代码,这应该是显而易见的。它在原型上共享相同的值,因为原型上共享任何内容。
问题是,当你读取值f1.prop1_
时,它会查找原型链中的值,因为f1
本身没有属性{{1 }}。 但是 ,当您使用prop1_
分配属性时,会直接分配给f1.prop1_ = 5
对象上的属性。换句话说,赋值会在对象本身上创建属性。此后,原型值被实例属性遮蔽。这就是为什么实例会有不同的值。
这对于不可变值很好;对于像数组这样的可变值,这是一个坏主意,因为f1
会改变原型上的对象而不是在单个实例上创建属性。
答案 1 :(得分:1)
没有。如果您创建两个实例,整个原型链将如下所示:
foo.Bar.prototype {
prop1_ :4
}
f1{
proto:foo.Bar.prototype
}
f2{
proto:foo.Bar.prototype
}
所以当你这样做时
f1.prop1_
它检查f1中是否存在属性(它没有),然后在原型中查找它,并计算为4.
如果你这样做
f1.prop1_ = 1;
它不会设置原型的属性,而是设置元素本身的属性:
foo.Bar.prototype {
prop1_ :4
}
f1{
proto:foo.Bar.prototype
prop1_:1
}
f2{
proto:foo.Bar.prototype
}
结果如下:
f1.prop1_ // 1
f2.prop2_ // 4 (looked up in prototype)