【问题标题】:In JavaScript Class, super cannot access attributes, but can modify attributes?在 JavaScript 类中,super 不能访问属性,但可以修改属性?
【发布时间】:2021-05-13 14:39:52
【问题描述】:

超属性不能访问,但可以修改?

super 代表什么?有人说是原型?我知道Class的功能在对象的原型中,但是为什么super.name ='Lucy';可以修改对象实例的属性呢?

class a {
  name = 'jack';
  speak() {
    console.log(this.name);
  }
}

class b extends a {
  count() {
    super.name = 'Lucy';
    console.log(super.name) // undefined
    super.speak();
  }
}

new b().count(); // Lucy

【问题讨论】:

    标签: javascript es6-class


    【解决方案1】:

    prop 是在父对象的原型 上定义时,分配给super.prop 很有用,而不是当它被定义为实例属性时,就像代码中的name 的情况一样。意识到分配name = 'jack' 发生在由new b 创建的实例 上,而不是其他某个对象上。

    因此,当您执行super.name = 'Lucy' 时,您除了this.name = 'Lucy' 之外什么也没做。当您在分配后咨询super.name 时,此更改不可见,因为这将扫描父级的原型链,而不是实例对象。而且该原型链上的任何地方都没有定义name...

    super.name 用于 lookupassignment 的行为方式之间的区别是特定的:对于(非设置者)assignment,这与在 this 上分配没有什么不同,而对于 lookup(包括 setter 查找),它会跳过 this 并在父原型链中开始查找。

    super.prop 语法的威力只有在您必须处理 在原型上创建的方法时才会显现出来。

    为了证明这一点,让我们将name 定义为原型上的getter/setter 函数:

    class A {
      _name = 'jack';
      speak() {
        console.log(this.name);
      }
      get name() {
          return this._name;
      }
      set name(name) {
          return this._name = name + " (A)";
      }
    }
    
    class B extends A {
      count() {
        super.name = 'Lucy'; // This will not call the setter of B.prototype, but of A.prototype
        super.speak();
      }
      get name() {
          return this._name;
      }
      set name(name) {
          return this._name + " (B)";
      }
    }
    
    new B().count(); // Lucy (A)

    注意这里super.name首先被识别为上层原型链中的一个函数,因此赋值变成了函数调用。如果它是一个属性修改分配,它会发生在this

    请参阅this answer to "ES6 inheritance: uses super to access the properties of the parent class" 中有关这方面规范的详细分析

    【讨论】:

    • "对于分配,它与在this上分配没有什么不同" - 你自己的例子证明了这一点:-)
    • @Bergi,我试图在该示例下面的文本中解释这一点:虽然语法使用=,但它确实解析为函数调用,因此它不属于赋值规则. this 将发生标准(非 setter 类型)分配。
    • 啊,对。 setter 调用对我来说仍然是一项任务,所以我不认为要在那里破例。对我来说,super 总是查找超类属性,只有当它没有找到任何东西时,它才会回退到接收器上的正常属性创建/更新。
    • 是的,但是它可以在原型链中找到一个非setter属性,如字符串属性(例如A.prototype.name = "test"),然后它仍然会正常分配给this属性。
    • 感谢您告诉我这个链接,stackoverflow.com/a/44160500/9854149
    【解决方案2】:

    super关键字用于访问和更新父类的变量、方法、属性等,调用父类的构造函数。但是super不是可以在子类中直接使用的对象。

    super(arguments);  // calls the parent constructor (only inside the constructor)
    super.parentMethod(arguments);  // calls a parent method
    

    class a {
      name = 'jack';
      speak() {
        console.log(this.name);
      }
    }
    
    class b extends a {
      count() {
        this.name = 'Lucy';
        console.log(this.name) // will not be undefined, you already have access to parent class property using this keyword
        super.speak();
      }
    }
    
    new b().count(); // Lucy

    【讨论】:

    • OP 询问的是 super.name = 'Lucy';,而不是构造函数和方法调用。
    • @Bergi super.name="Lucy" 和 this.name="Lucy" 在这里的工作方式相同,并且会为您提供相同的输出,但您可以在子项中访问父属性的值只使用这个关键字的类
    猜你喜欢
    • 2021-04-25
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 2012-11-19
    • 2011-11-14
    相关资源
    最近更新 更多