ES6继承:使用`super`来访问父类的属性

时间:2017-05-24 04:53:21

标签: javascript typescript inheritance ecmascript-6 babel

Javascript的super关键字,当我在Chrome,Babel,TypeScript上运行代码时,我得到了不同的结果。

我的问题是哪个结果是正确的?规范的哪一部分定义了这种行为?

以下代码:

class Point {
  getX() {
    console.log(this.x); // C
  }
}

class ColorPoint extends Point {
  constructor() {
    super();
    this.x = 2;
    super.x = 3;
    console.log(this.x)   // A
    console.log(super.x)  // B
  }

  m() {
    this.getX()
  }
}

const cp = new ColorPoint();
cp.m();

结果:

  • Chrome 58.0.3029.110 64bit(V8 5.8.283.38)
  • Babel Repl 6.24.2
  • TypeScript 2.3

链接:

3 个答案:

答案 0 :(得分:5)

简答:

Chrome是正确的。这是由get和set之间的不平衡引起的。

OrdinarySet reciever敏感,但OrdinaryGet不是。

所以super.x = 3this.x = 3具有相同的效果,因为此处的接收方为this。评估永远不会达到super.x的{​​{1}}始终会this,因为undefined没有此类字段。

更多详情:

A.prototypeSuperReference。对super.x的分配将调用PutValue(V, W),然后调用SuperReference对象的内部广告位[[Set]],最后调用super

在纯JavaScript中,语句OrdinarySet基本上等同于:

super.x = 3

其中OrdinarySet(proto, 'x', 3, this)是超级对象,在构造函数proto的{​​{3}}内部。 ColorPoint等同于proto[[HomeObject]]指定,并以Object.create(Point.prototype)的形式传递给构造函数。

现在让我们看看[[HomeObject]]的工作原理。 在步骤4c和4d中,规范要求设置操作在接收方OrdinarySet上完成,而不是this对象。

  

让existingDescriptor成为? [GetOwnProperty]接收机。

     

如果未定义existingDescriptor,则

     

如果IsAccessorDescriptor(existingDescriptor)为true,则返回false。

     

如果existingDescriptor。[[Writable]]为false,则返回false。

     

让valueDesc成为PropertyDescriptor {[[Value]]:V}。

     

回归? Receiver。[[DefineOwnProperty]](P,valueDesc)。

这些陈述说proto表示OrdinarySet(proto, 3, this)

另一方面,this.x = 3 忽略 OrdinaryGetReceiver

super.x

OrdinaryGet(proto, 'x', this)根本没有OrdinaryGet条款!因此Receiver相当于super.x,当然是Object.create(Point.prototype).x

根据经验,如果转换器和浏览器之间存在差异,浏览器(尤其是Chrome)通常对ECMAScript规范更加忠诚。对于运行时效率,通常会对一些边缘情况的正确性进行交换。

答案 1 :(得分:0)

编程规则Garbage in -> Garbage out。以下代码:

class Point {
  x: number;
  getX() {
    console.log(this.x);
  }
}

class ColorPoint extends Point {
  constructor() {
    super();
    this.x = 2;
    super.x = 3; // ERROR
  }
}

你得到一个很好的TypeScript错误Only public and protected methods can be accessed。请注意单词methodssuper不应使用properties。无效的代码不应该运行。

答案 2 :(得分:0)

我看到的差异: -

super有助于将上述课程的所有部分都纳入其中  我们可以相应改变这一点。

  1. 我们可以在JAVASCRIPT中通过super.x或this.x更改类点的this.x.   但是我们不能用super.x来改变tyescript(它会表现得很好   类colorPoint的新对象)..这个改变可以   只有这个才会发生。

  2. 我们甚至无法在JAVASCRIPT中第二次调用super()它会给出一个   错误,我们可以在类型脚本中调用super()   它将重新启动Point构造函数类

  3. 通过运行它在TypeScript Playground中注意到的Typescript事件

    "use strict";
    class Point {
    
        getX() {
            console.log("POINT " + this.x);
        }
        constructor() {
            this.x = 10;
        }
    }
    
    class ColorPoint extends Point {
        constructor() {
            super();
            this.y = 2;
            console.log("THIS x" + this.x); //  10
            console.log("THIS y" + this.y); //  2
            console.log("SUPER !" + super.x); //  undef
    
            super.x = 3;
    
            console.log("THIS.x after a " + this.x); //  10
            this.x = 20;
    
            console.log("THIS.x after b " + this.x); //  20
    
            super();
            console.log("SUPER x" + super.x); // 
            console.log("THIS x" + this.x); // 
    
            console.log(this); // give this of colorPoint
            console.log(super()); // give this of colorPoint
        }
    }
    
    const cp = new ColorPoint();
    cp.getX();
    

    通过命令node super.js

    在控制台中注意到的Javascript事项
    "use strict";
    class Point {
    
        getX() {
            console.log("POINT " + this.x);
        }
        constructor() {
            this.x = 10;
        }
    }
    
    class ColorPoint extends Point {
        constructor() {
            super();
            this.y = 2;
            console.log("THIS x" + this.x); // 
            console.log("THIS y" + this.y); // 
            // console.log("SUPER" + super.x); // 
    
            super.x = 3;
    
            console.log("THIS.x after a " + this.x); // 
            this.x = 20;
    
            console.log("THIS.x after b " + this.x); // 
    
            //gives err 
            // super();
            // console.log("SUPER x" + super.x); // 
            // console.log("THIS x" + this.x); // 
        }
    
        // m() {
        //     this.getX();
        // }
    }
    
    const cp = new ColorPoint();
    cp.getX();