Javascript 原型是怎么回事
因此,我有以下几点:Javascript 原型是怎么回事,javascript,prototype,Javascript,Prototype,因此,我有以下几点: function A () { this.a = 0; } function B () { this.b = 0; } function C () {} C.prototype = new B(); var c1 = new C(); var c2 = new C(); c1.b = 10; console.log(c1.b); // 10 console.log(c2.b); // 0 当我将B.B更改为一个对象时,它似乎为每个新的C存储相同的对象: fun
function A () { this.a = 0; }
function B () { this.b = 0; }
function C () {}
C.prototype = new B();
var c1 = new C();
var c2 = new C();
c1.b = 10;
console.log(c1.b); // 10
console.log(c2.b); // 0
当我将B.B
更改为一个对象时,它似乎为每个新的C
存储相同的对象:
function A () { this.a = 0; }
function B () { this.b = new A(); }
function C () {}
C.prototype = new B();
var c1 = new C();
var c2 = new C();
c1.b.a = 10;
console.log(c1.b.a); // 10
console.log(c2.b.a); // 10 - I want this to be 0
谁能解释一下发生了什么/问题出在哪里。你什么时候解释的
C.prototype = new B();
你没有说“只要你需要一个原型,就做新的B
”。您所说的是“将原型分配给new B()
(这应该不会很奇怪)。您得到的是:
C.prototype.b.a === 0
无论何时执行newc
,您都不会复制C.prototype
——您只是链接到它,链接到相同的B
对象集:
C.prototype = new B()
^ ^
| |
c1 c2
c1.b === c2.b; //true
正如您所知,对象可以根据您的内心内容进行更改。因此,当您执行c1.b.a=4
时,您将进入底层对象并对其进行处理
编辑:第一个示例的工作原理取决于属性解析的工作方式。b
属性不位于对象c1
或c2
。当您说“给我c1.b
”时,js引擎会执行以下操作:
c1
上是否有b
属性?不,没有c1
的原型(实际的原型,对象从中获得方法和属性的内容-在本例中,C.prototype
)b
属性。返回它b
是一个对象,那么您就掌握了一个对象。更改它会像更改普通对象一样更改它(请注意,您没有直接指定给c1.b
,您会在一点时间内明白我的意思)。用箭头解释:
C.prototype.b = 0
^ ^
| |
c1.b c2.b
这一点很重要,所以我要再次强调:当你抓住c1.b
时,你得到的是一个对象,它像任何其他对象一样被操纵。为它指定属性就像任何其他普通对象一样,并对它进行变异……嗯,变异它
现在,在前一种情况下(c1.b=10
),您实际上是在分配一个属性。这意味着您正在c1
对象本身上创建一个键/值配对。因此,在第一步中,我们查看c1
是否有一个属性b
,并且它有。用更多箭头解释:
C.prototype.b = 0
^
|
c1.b=10 c2.b
改变后一个例子,我们可以观察到同样的效果:
//changing
c1.b.a = 10;
//to
c1.b = 4;
c2.b !== 4 && c2.b.a === 0; //true
重述:
- 在前一个示例中,您只需在
对象上设置一个属性c1
- 在后一个示例中,您在
s原型上的对象上设置了一个属性,该属性在所有其他c1
对象上对其进行了变异C
- 据我所知,发生了以下事情:
function A () { this.a = 0; }
function B () { this.b = 0; }
function C () {}
C.prototype = new B();
var c1 = new C();
var c2 = new C();
c1.b = 10;
当您编写c1.b=10
时,JavaSript只会添加或更改对象c1
的本地属性b
。它并不关心原型已经有一个属性b
,在这种情况下,该属性保持完全不受影响。因此:
console.log(c1.b); // 10 --> local property in c1
console.log(c2.b); // 0 --> prototype property
在第二个示例中,您正在执行一些不同的操作。您没有将属性指定给c1
,而是在操作它的原型,从而同时影响所有实例:
c1.b.a = 10;
c1
没有属性b
,因此它将从prototype对象中获取该属性,并添加或更改其属性a
。现在无论是c1
还是c2
都没有获得本地属性,因此都引用了更改后的原型:
console.log(c1.b.a); // 10 --> points to the prototype
console.log(c2.b.a); // 10 --> points to the prototype
可能的解决方案
c1.b = new A();
c1.b.a = 10
这是一篇很好的文章,我认为它可以解释这个问题,也许这是一个更好的例子来理解发生了什么:这解释了我的例子中的第一个例子吗,我改变了基础B,它们是不同的?@Ben在第一个例子中,
C.prototype.B
不是一个对象,而是一个原始值。当你访问B
在后一个示例中,您在c1
s prototype链接上访问了它;在前一个示例中,您只是在对象上分配了它。我将编辑我的答案来解释这一点。在第一个示例中,您为实例设置了一个值,该值仅替换该实例的prototype值。@Ben Edited。希望它现在更清晰。
c1.b = new A();
c1.b.a = 10