我找到的所有资源,它说如果我们使用Javascript原型模式,那就是'原型在该特定类型的所有对象之间共享。 这意味着以下内容;
function TestObj(){
}
TestObj.prototype = {
cVar: 15,
increase: function(){
this.cVar++;
}
};
var a = new TestObj();
var b = new TestObj();
a.increase();
console.log(a.cVar); // 16
console.log(b.cVar); // 15 ??
现在我的问题是,b.cVar不应该是16吗?那为什么呢?如果它是15则意味着具有protype的TestObj不在对象之间共享。
你知道吗?答案 0 :(得分:6)
是的,对象的原型在对象的实例之间共享,但this.cVar++
看起来有点误导。
我认为如果你重写
会更容易解释this.cVar++;
作为
this.cVar = this.cVar + 1;
重要的是this
指的是对象实例,而不是原型。因此,在this.cVar + 1
中,它将检查对象实例以查看它是否具有cVar
属性。第一次调用increase
时,它不会。所以JavaScript会查找原型链,直到找到它为止。所以它找到了15
。但是,当它将实际赋值返回到this.cVar
时,它会在对象实例本身上设置属性,而不是原型(对各种类型的影子)。
所以在你的例子中,
console.log(a.cVar); // returns property from `a` itself
console.log(b.cVar); // returns property from the prototype
我们可以使用hasOwnProperty
:
console.log( a.hasOwnProperty( "cVar" ) ); // true
console.log( b.hasOwnProperty( "cVar" ) ); // false
答案 1 :(得分:3)
go-oleg
所提到的那样,有一个原型链的概念。原型链有一些您必须了解的行为。
当您尝试访问对象上的属性时,它以递归方式从对象开始查找链并查找属性,然后返回值(这是读取/获取时发生的情况动作强>)。
当您尝试在对象上的属性上设置值时,它并不需要递归链以查找链中的属性。相反,如果它没有在对象上找到一个,它只会添加属性以及您在对象本身上设置的值。这有效地隐藏了原型链中较高的属性(这是写/置动作的情况)。
如果您将值放在一个对象中然后尝试设置该值,它会在读取尝试时递归到对象引用,并且由于您有一个指向该对象的引用指针,您将在该对象上设置该值直接哪个会产生你期望的结果:
function TestObj(){
}
TestObj.prototype = {
cVar: 15,
obj: { val: 5 },
increase: function(){
this.cVar++;
},
objInc: function() {
this.obj.val++;
}
};
var a = new TestObj();
var b = new TestObj();
a.increase();
console.log(a.cVar);
console.log(b.cVar);
b.objInc();
console.log(a.obj.val);
console.log(b.obj.val);
//output
//16
//15
//6
//6
希望这种区别可以消除混乱。
答案 2 :(得分:0)
要清楚," a"是一个对象," b"是另一个独立的对象。 然后,您只能在" a"而不是" b"上调用增加功能。因此,除非我离开摇杆,否则 b.cVar = 15是有意义的,因为它从未递增过。
答案 3 :(得分:0)
您对术语感到困惑,而TestObject
a
是TestObject
唯一被称为increase()
的{{1}}。因此,a = 16
和b = 16
是有意义的,因为您从不致电b.increase()
。
......函数'原型在该特定类型的所有对象之间共享。
这并不意味着每次TestObject
调用increase()
,然后每隔一个TestObject
,其本身也会增加cVar
。您对类似于设置EventListener
和EventDispatcher
系统的方式的想法。该函数的原型在该特定类型的所有对象之间共享意味着每个TestObject
实例都具有您定义的原型。