的JavaScript - 原型链

问题描述:

请考虑这样的代码:的JavaScript - 原型链

class a { 
    constructor() { 
     this.test = "test from a"; 
     this.testA = "X"; 
    } 

    mimi() { 
     console.log('aaaaaaaa', this.test, this.testA) 
    } 

} 

class b extends a { 
    constructor() { 
     super(); 
     this.test = "test from b" 
    } 

    mimi() { 
     console.log('bbbbbbbb', this.test, this.testA) 
    } 

} 

class c extends b { 
    constructor() { 
     super(); 
     this.test = "test from c" 
    } 

    mimi() { 
     console.log('cccccccc', this.test, this.testA) 
    } 

    meme() { 
     var test = kalreg.__proto__.__proto__; 
     test.mimi(); 
     var test2 = kalreg.__proto__.__proto__.__proto__; 
     test2.mimi(); 
    } 
} 

var kalreg = new c(); kalreg.mimi(); kalreg.meme(); 

我得到的输出是:

cccccccc test from c X 
bbbbbbbb undefined undefined 
aaaaaaaa undefined undefined 

我的目标逻辑让我用“一个”为最通用类,作为小孩的“b”,作为“b”的小孩的“c”。我想“Ç”拥有的“b”和“a”而是功能的一部分“一个”被覆盖“b”所以唯一的办法“Ç”所有方法和属性可能有权访问覆盖的功能是使用原型链。 不幸的是,我的路行不通,因此问题是:

  1. meme()功能,如何避免kalreg.proto - 我已经告诉访问原型的这样的方式是邪恶和危险的代码。
  2. 在我看来,输出中应该没有“未定义”,但是,有。 预期的输出结果是:从B X从X

如何实现从C X

CCCCCCCC测试

BBBBBBBB测试

AAAAAAAA测试?

谢谢!

in meme() function,如何避免kalreg。

使用super的使用情况下,你确实需要访问从超类的属性(但要注意,不会与testtestA帮助,因为这些都不是在超或它的prototype对象,它们使用new c创建的实例;更多内容在下面)。

另外:避免__proto__。在需要访问对象原型的罕见情况下,请使用Object.getPrototypeOf

在我看来,应该没有“未定义”的输出,但是有。预期输出是:从B X选自C X

CCCCCCCC测试

BBBBBBBB测试从X

的输出是正确

AAAAAAAA测试,因为原型对象在其上”重新拨打mimi没有testtestA属性。只有使用new c创建的对象才具有这些属性。而且只有一个这样的对象,所以test将会是"test from c",不管你拨打哪个mimi,而testA永远是"X"

在一个评论中,你已经问过当每个构造函数在其中有this.test = ...时只有一个test。让我们来看看什么是在内存中,一旦你做了var kalreg = new c();

 
             +−−−−−−−−−−−−+ 
a−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−>| (function) | +−−−>(Function.prototype) 
             | +−−−−−−−−−−−−+ | 
             | | __proto__ |−−+   +−−−−−−−−−−−−−+ 
             | | prototype |−−−−−−−−−−+−>| (object) | 
             | +−−−−−−−−−−−−+   | +−−−−−−−−−−−−−+ 
             |       | | __proto__ |−−>... 
         +−−−−−−−−−−−−+ |       | | constructor |−−>a 
b−−−−−−−−−−−−−−−−−−−+−>| (function) | |       | | mimi  |−−>... 
        | +−−−−−−−−−−−−+ |       | +−−−−−−−−−−−−−+ 
        | | __proto__ |−+   +−−−−−−−−−−−−−+ | 
        | | prototype |−−−−−−−−+−>| (object) | | 
        | +−−−−−−−−−−−−+  | +−−−−−−−−−−−−−+ | 
        |      | | __proto__ |−−+ 
    +−−−−−−−−−−−−+ |      | | constructor |−−>b 
c−−−>| (function) | |      | | mimi  |−−>... 
    +−−−−−−−−−−−−+ |      | +−−−−−−−−−−−−−+ 
    | __proto__ |−+  +−−−−−−−−−−−−−+ | 
    | prototype |−−−−−−−+−>| (object) | | 
    +−−−−−−−−−−−−+  | +−−−−−−−−−−−−−+ | 
          | | __proto__ |−+ 
          | | constructor |−−>c 
      +−−−−−−−−−−−−+ | | mimi  |−−>... 
kalreg−−−>| (object) | | | meme  |−−>... 
      +−−−−−−−−−−−−+ | +−−−−−−−−−−−−−+ 
      | __proto__ |−−+ 
      | test  | 
      | testA  | 
      +−−−−−−−−−−−−+ 

正如你所看到的,只有对象kalreg点到了testtestA。为什么?因为在调用每个构造函数期间,this引用该对象;这就是newsuper()的工作方式。因此,由于this引用了该对象,因此每个构造函数都会执行其this.test = ...一行,并且由于c中的那个是最后一个运行的对象,因此它“获胜”。

您可以访问mimi方法的超类版本,但由于它们全都显示test属性,它们都将显示"test from c"。要显示不同的东西,他们必须要有不同的属性才能显示。此外,与super你只能去一个级别,所以如果你想要去向上两级,你要么使用a.prototype.mimi(或this.__proto__.__proto__.mimi明确,或把一些设施在b调用amimi

具有用于每个级别不同的属性,并与b提供superMimi实施例这样c可以使用amimi

class a { 
 
    constructor() { 
 
     this.testA = "test from a (this.testA)"; 
 
    } 
 

 
    mimi() { 
 
     console.log('aaaaaaaa', this.testA); 
 
    } 
 
} 
 

 
class b extends a { 
 
    constructor() { 
 
     super(); 
 
     this.testB = "test from b (this.testB)"; 
 
    } 
 

 
    mimi() { 
 
     console.log('bbbbbbbb', this.testB) 
 
    } 
 
    
 
    superMimi() { 
 
     return super.mimi(); 
 
    } 
 
} 
 

 
class c extends b { 
 
    constructor() { 
 
     super(); 
 
     this.testC = "test from c (this.testC)"; 
 
    } 
 

 
    mimi() { 
 
     console.log('cccccccc', this.testC); 
 
    } 
 

 
    meme() { 
 
     super.mimi();  // Uses b's version 
 
     super.superMimi(); // Uses a's version 
 
     this.__proto__.__proto__.__proto__.mimi.call(this); // Also uses a's version 
 
     var p = Object.getPrototypeOf(this); 
 
     var p2 = Object.getPrototypeOf(p); 
 
     var p3 = Object.getPrototypeOf(p2); 
 
     p3.mimi.call(this); // Also uses a's version 
 
    } 
 
} 
 

 
var kalreg = new c(); 
 
kalreg.mimi(); 
 
kalreg.meme();

+0

对象如何可能没有this.test每个类是否在它们的构造函数中定义了this.test? – Kalreg

+0

您可否详细说明如何在'meme()'方法中使用'super'来完成OPs的目标。 – Adam

+1

@亚当:完成,感谢您将它挂起,我的意思是回到那个并忘记。 :-) –