ruanyf / es6tutorial

《ECMAScript 6入门》是一本开源的 JavaScript 语言教程,全面介绍 ECMAScript 6 新增的语法特性。

Home Page:http://es6.ruanyifeng.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

class私有属性(方法)继承问题

yaomk opened this issue · comments

commented

阮老师好。
Class 的继承-3.super关键字一章中,提到

ES6 规定,在子类普通方法中通过super调用父类的方法时,方法内部的this指向当前的子类实例。

如果父类有私有属性的话,子类继承后问题,有些疑问,举个例子:

class A {
  #name = 'class A'
  print() {
    console.log(this.#name)
  }
}
class B extends A {
  #name  = 'class B'
  print() {
    super.print()
    console.log(this.#name)
  }
}
let a = new A, b = new B
a.print() // class A
b.print() // class A class B

当我首次这样运行时,对结果感觉很疑惑,在B中我已经改写了私有属性#name的值,为什么调用b.print()却依然打印出来class A?这没有符合原文的描述。后来使用babel编译过后大致明白,当类使用私有属性就创建了一个this为键值,私有属性为value的WeakMap(方便理解:{父类实例的this => 'class A'})。当子类继承时,由于重写了#name,所以又新创建了一个WeakMap:{子类实例的this => 'class B'},同时又在父类的WeakMap里新增了一个子类实例this的键值对{子类实例的this => 'class A'}。当调用super.print()就返回了class A
我描述的可能不够清楚,我现在疑问是私有属性、方法是否是像babel编译的那样子,借助了WeakMap?私有属性、方法是否可以继承?在以后私有属性、方法正式成为标准时,使用上有什么注意的地方?是否应该尽量避免继承有私有属性的类?

新建子类实例时,会自动执行一次父类的构造函数。

commented

新建子类实例时,会自动执行一次父类的构造函数。

这个似乎不能解释上边例子里子类实例调用print()打印出来的结果,为什么会打印出来’class A‘。

class A {
  name = 'class A'
  print() {
    console.log(this.name)
  }
}
class B extends A {
  name  = 'class B'
  print() {
    super.print()
    console.log(this.name)
  }
}
let a = new A, b = new B
a.print() // class A
b.print() // class B class B

普通实例属性为什么可以重写,而继承过来的私有属性就不能重写呢?

私有属性只限于它所在的类,子类拿不到父类的私有属性。