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
    属性。返回它
  • 在实际的js中,这是():

    因此,如果
    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
      对象上设置一个属性
    • 在后一个示例中,您在
      c1
      s原型上的对象上设置了一个属性,该属性在所有其他
      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