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();
结果:
链接:
答案 0 :(得分:5)
Chrome是正确的。这是由get和set之间的不平衡引起的。
OrdinarySet reciever
敏感,但OrdinaryGet不是。
所以super.x = 3
与this.x = 3
具有相同的效果,因为此处的接收方为this
。评估永远不会达到super.x
的{{1}}始终会this
,因为undefined
没有此类字段。
A.prototype
是SuperReference。对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
忽略 OrdinaryGet
。 Receiver
是
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
。请注意单词methods
。 super
不应使用properties
。无效的代码不应该运行。
答案 2 :(得分:0)
我看到的差异: -
super
有助于将上述课程的所有部分都纳入其中
我们可以相应改变这一点。
我们可以在JAVASCRIPT中通过super.x或this.x更改类点的this.x. 但是我们不能用super.x来改变tyescript(它会表现得很好 类colorPoint的新对象)..这个改变可以 只有这个才会发生。
我们甚至无法在JAVASCRIPT中第二次调用super()它会给出一个 错误,我们可以在类型脚本中调用super() 它将重新启动Point构造函数类
通过运行它在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
"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();