super
åºçº¿
广æ³å¯ç¨
èª 2016å¹´3æ èµ·ï¼æ¤ç¹æ§å·²å¨ä¸»æµæµè§å¨ä¸å¾å°æ¯æï¼å¯å¨å¤§å¤æ°è®¾å¤åæµè§å¨çæ¬ä¸æ£å¸¸ä½¿ç¨ã
super å ³é®åç¨äºè®¿é®å¯¹è±¡åé¢éæç±»çååï¼[[Prototype]]ï¼ä¸ç屿§ï¼æè°ç¨ç¶ç±»çæé 彿°ã
super.prop å super[expr] 表达å¼å¨ç±»å对象åé¢é任使¹æ³å®ä¹ä¸é½æ¯ææçãsuper(...args) 表达å¼å¨ç±»çæé 彿°ä¸ææã
è¯æ³
super([arguments]) // è°ç¨ç¶ç±»çæé 彿°
super.propertyOnParent
super[expression]
æè¿°
super å
³é®åæä¸¤ç§ä½¿ç¨æ¹å¼ï¼ä½ä¸ºâ彿°è°ç¨âï¼super(...args)ï¼ï¼æä½ä¸ºâ屿§æ¥è¯¢âï¼super.prop å super[expr]ï¼ã
夿³¨ï¼super æ¯ä¸ä¸ªå
³é®åï¼å¹¶ä¸æä¸äºç¹æ®çè¯æ³ç»æãsuper 䏿¯ä¸ä¸ªæååå对象çåéãè¯å¾è¯»å super æ¬èº«ä¼å¯¼è´ SyntaxErrorã
const child = {
myParent() {
console.log(super); // SyntaxError: 'super' keyword unexpected here
},
};
卿´¾çç±»çæé 彿°ä½ä¸ï¼ä½¿ç¨ extendsï¼ï¼super å
³é®åå¯ä»¥ä½ä¸ºâ彿°è°ç¨âï¼super(...args)ï¼åºç°ï¼å®å¿
é¡»å¨ä½¿ç¨ this å
³é®åä¹ååæé 彿°è¿åä¹å被è°ç¨ãå®è°ç¨ç¶ç±»çæé 彿°å¹¶ç»å®ç¶ç±»çå
Œ
±å段ï¼ä¹åæ´¾çç±»çæé 彿°å¯ä»¥è¿ä¸æ¥è®¿é®åä¿®æ¹ thisã
â屿§æ¥è¯¢âå½¢å¼å¯ä»¥ç¨æ¥è®¿é®ä¸ä¸ªå¯¹è±¡åé¢æç±»ç [[Prototype]] çæ¹æ³å屿§ãå¨ä¸ä¸ªç±»ç主ä½ä¸ï¼super çå¼ç¨å¯ä»¥æ¯ç¶ç±»çæé 彿°æ¬èº«ï¼ä¹å¯ä»¥æ¯æé 彿°ç prototypeï¼è¿åå³äºæ§è¡ç¯å¢æ¯å®ä¾åå»ºè¿æ¯ç±»çåå§åãæ´å¤ç»è请åè§ç¤ºä¾é¨åã
注æï¼super çå¼ç¨æ¯ç± super 声æçç±»æå¯¹è±¡åé¢å³å®çï¼è䏿¯æ¹æ³è¢«è°ç¨ç对象ãå æ¤ï¼åæ¶ç»å®æéæ°ç»å®ä¸ä¸ªæ¹æ³å¹¶ä¸ä¼æ¹åå
¶ä¸ super çå¼ç¨ï¼å°½ç®¡å®ä»¬ä¼æ¹å this çå¼ç¨ï¼ãä½ å¯ä»¥æ super ç使¯ç±»æå¯¹è±¡åé¢èå´å
çä¸ä¸ªåéï¼è¿äºæ¹æ³å¨å®ä¸é¢å建äºä¸ä¸ªéå
ã(ä½ä¹è¦æ³¨æï¼å®å®é
ä¸å¹¶ä¸æ¯ä¸ä¸ªåéï¼æ£å¦ä¸é¢æè§£éç飿 ·)ã
å½éè¿ super è®¾ç½®å±æ§æ¶ï¼è¯¥å±æ§å°è¢«è®¾ç½®å¨ this ä¸ã
示ä¾
>å¨ç±»ä¸ä½¿ç¨ super
以ä¸ä»£ç çæ®µæ¥èªäº classes sampleï¼å¨çº¿æ¼ç¤ºï¼ãè¿éè°ç¨ super() æ¯ä¸ºäºé¿å
éå¤å¨ Rectangle ä¸ Square çæé 彿°ä¹é´å
±åçé¨åã
class Polygon {
constructor(height, width) {
this.name = "Rectangle";
this.height = height;
this.width = width;
}
sayName() {
console.log("Hi, I am a ", this.name + ".");
}
get area() {
return this.height * this.width;
}
set area(value) {
this._area = value;
}
}
class Square extends Polygon {
constructor(length) {
this.height; // ReferenceErrorï¼super éè¦å
被è°ç¨ï¼
// è¿éï¼å®è°ç¨ç¶ç±»çæé 彿°å¹¶ä¼ å
¥ length
// ä½ä¸º Polygon ç height, width
super(length, length);
// 注æï¼å¨æ´¾ççç±»ä¸ï¼å¨ä½ å¯ä»¥ä½¿ç¨ 'this' ä¹åï¼å¿
é¡»å
è°ç¨ super()ã
// ç°å¨å¯ä»¥ä½¿ç¨ 'this' äºï¼å¿½ç¥ 'this' å°å¯¼è´å¼ç¨é误ï¼ReferenceErrorï¼
this.name = "Square";
}
}
è°ç¨ç¶ç±»ä¸çéææ¹æ³
ä½ ä¹å¯ä»¥ç¨ super è°ç¨ç¶ç±»çéææ¹æ³ã
class Rectangle {
static logNbSides() {
return "I have 4 sides";
}
}
class Square extends Rectangle {
static logDescription() {
return `${super.logNbSides()} which are all equal`;
}
}
Square.logDescription(); // 'I have 4 sides which are all equal'
å¨ç±»å段声æä¸è®¿é® super
super ä¹å¯ä»¥å¨ç±»å段åå§åæ¶è¢«è®¿é®ãsuper çå¼ç¨åå³äºå½ååæ®µæ¯ä¸ä¸ªå®ä¾åæ®µè¿æ¯ä¸ä¸ªéæå段ã
class Base {
static baseStaticField = 90;
baseMethod() {
return 10;
}
}
class Extended extends Base {
extendedField = super.baseMethod(); // 10
static extendedStaticField = super.baseStaticField; // 90
}
注æï¼å®ä¾å段æ¯å¨å®ä¾ä¸è®¾ç½®çï¼è䏿¯å¨æé 彿°çååä¸ï¼æä»¥ä½ ä¸è½ç¨ super æ¥è®¿é®ç¶ç±»çå®ä¾å段ã
class Base {
baseField = 10;
}
class Extended extends Base {
extendedField = super.baseField; // undefined
}
å¨è¿éï¼extendedField æ¯ undefined è䏿¯ 10ï¼å 为 baseField 被å®ä¹ä¸º Base å®ä¾çèªæå±æ§ï¼è䏿¯ Base.prototypeãå¨è¿ç§æ
åµä¸ï¼super åªæ¥æ¾ Base.prototype ç屿§ï¼å ä¸ºå®æ¯ Extended.prototype ç [[Prototype]]ã
å é¤ super ä¸ç屿§å°æåºå¼å¸¸
ä½ ä¸è½ä½¿ç¨ delete æä½ç¬¦å super.prop æè
super[expr] å»å é¤ç¶ç±»ç屿§ï¼è¿æ ·åä¼æåº ReferenceErrorã
class Base {
foo() {}
}
class Derived extends Base {
delete() {
delete super.foo; // è¿å¾ç³ç³
}
}
new Derived().delete(); // ReferenceError: invalid delete involving 'super'.
å¨å¯¹è±¡åé¢éä¸ä½¿ç¨ super.prop
super ä¹å¯ä»¥å¨å¯¹è±¡åå§åå¨/对象åé¢é符å·ä¸ä½¿ç¨ãå¨è¿ä¸ªä¾åä¸ï¼ä¸¤ä¸ªå¯¹è±¡å®ä¹äºä¸ä¸ªæ¹æ³ãå¨ç¬¬äºä¸ªå¯¹è±¡ä¸ï¼super è°ç¨ç¬¬ä¸ä¸ªå¯¹è±¡çæ¹æ³ãè¿æ¯å¨ Object.setPrototypeOf() ç帮å©ä¸å®ç°çï¼æä»¬å° obj2 çåå设置为 obj1ï¼è¿æ · super å°±è½å¤å¨ obj1 䏿¾å° method1ã
const obj1 = {
method1() {
console.log("method 1");
},
};
const obj2 = {
method2() {
super.method1();
},
};
Object.setPrototypeOf(obj2, obj1);
obj2.method2(); // logs "method 1"
读å super.prop çæ¹æ³å¨ç»å®å°å ¶ä»å¯¹è±¡æ¶ä¸ä¼æä¸åç表ç°
è®¿é® super.x çè¡ä¸ºç±»ä¼¼äº Reflect.get(Object.getPrototypeOf(objectLiteral), "x", this)ï¼è¿æå³çè¯¥å±æ§æ»æ¯å¨å¯¹è±¡åé¢/类声æçååä¸å¯»æ¾ï¼åæ¶ç»å®åéæ°ç»å®æ¹æ³ä¸ä¼æ¹å super çå¼ç¨ã
class Base {
baseGetX() {
return 1;
}
}
class Extended extends Base {
getX() {
return super.baseGetX();
}
}
const e = new Extended();
console.log(e.getX()); // 1
const { getX } = e;
console.log(getX()); // 1
åæ ·çæ åµä¹åçå¨å¯¹è±¡åé¢éä¸ã
const parent1 = { prop: 1 };
const parent2 = { prop: 2 };
const child = {
myParent() {
console.log(super.prop);
},
};
Object.setPrototypeOf(child, parent1);
child.myParent(); // æå° "1"
const myParent = child.myParent;
myParent(); // ä¾ç¶æå° "1"
const anotherChild = { __proto__: parent2, myParent };
anotherChild.myParent(); //ä¾ç¶æå° "1"
åªæé设æ´ä¸ªç»§æ¿é¾æè½æ¹å super çå¼ç¨ã
class Base {
baseGetX() {
return 1;
}
static staticBaseGetX() {
return 3;
}
}
class AnotherBase {
baseGetX() {
return 2;
}
static staticBaseGetX() {
return 4;
}
}
class Extended extends Base {
getX() {
return super.baseGetX();
}
static staticGetX() {
return super.staticBaseGetX();
}
}
const e = new Extended();
// éç½®å®ä¾é¨åçç»§æ¿
Object.setPrototypeOf(Extended.prototype, AnotherBase.prototype);
console.log(e.getX()); // æå° "2" è䏿¯ "1", å 为ååé¾å·²ç»æ¹å
console.log(Extended.staticGetX()); // ä¾ç¶æå° "3", å 为æä»¬è¿æ²¡æä¿®æ¹éæé¨åã
// éç½®éæé¨åçç»§æ¿
Object.setPrototypeOf(Extended, AnotherBase);
console.log(Extended.staticGetX()); //ç°å¨æå° "4"
设置 super.prop å°å¨æ¤åºç¡ä¸è®¾ç½®å±æ§
设置 super ç屿§ï¼æ¯å¦ super.x = 1ï¼å°±å Reflect.set(Object.getPrototypeOf(objectLiteral), "x", 1, this) çè¡ä¸ºãè¿æ¯ä¸ä¸ªå° super ç®åç解为âåå对象çå¼ç¨âçæ
åµï¼å 为å®å®é
䏿¯å¨ this ä¸è®¾ç½®å±æ§ã
class A {}
class B extends A {
setX() {
super.x = 1;
}
}
const b = new B();
b.setX();
console.log(b); // B { x: 1 }
console.log(Object.hasOwn(b, "x")); // true
super.x = 1 å°å¨ A.prototype ä¸å¯»æ¾ x ç屿§æè¿°ç¬¦ï¼å¹¶è°ç¨é£éå®ä¹ç setterï¼ï¼ä½ this çå¼å°è¢«è®¾ç½®ä¸º thisï¼å¨è¿ç§æ
åµä¸å°±æ¯ bãä½ å¯ä»¥é
读 Reflect.set 以äºè§£æ´å¤å
³äº target å receiver ä¸åæ
åµçç»èã
è¿æå³çï¼è½ç¶ get super.prop çæ¹æ³é常ä¸ä¼åå° this ä¸ä¸æçå½±åï¼ä½ set super.prop çæ¹æ³å´å®¹æåå°å½±åã
/* Reusing same declarations as above */
const b2 = new B();
b2.setX.call(null); // TypeError: Cannot assign to read only property 'x' of object 'null'
ç¶èï¼super.x = 1 ä»ç¶ä¼æ¥è¯¢åå对象ç屿§æè¿°ç¬¦ï¼è¿æå³çä½ ä¸è½éåä¸å¯åç屿§ï¼èä¸ setter ä¼è¢«è°ç¨ã
class X {
constructor() {
// Create a non-writable property
Object.defineProperty(this, "prop", {
configurable: true,
writable: false,
value: 1,
});
}
}
class Y extends X {
constructor() {
super();
}
foo() {
super.prop = 2; // Cannot overwrite the value.
}
}
const y = new Y();
y.foo(); // TypeError: "prop" is read-only
console.log(y.prop); // 1
è§è
| è§è |
|---|
| ECMAScript® 2027 Language Specification > # sec-super-keyword > |