超级的

基线 广泛可用

此功能已得到很好的建立,可在许多设备和浏览器版本中使用。从那时起,它就可以跨浏览器使用 2017年3月.

这个超级的关键字用于访问对象文字或类的[[Prototype]]上的属性,或调用超类的构造函数。

这个超级螺旋桨超级[expr]表达式在任何方法定义在两者中对象字面量. Thesuper(…参数)表达式在类构造函数中有效。

试试看

语法

js型
超级的([论据]) //调用父构造函数。
超级的.父级上的属性超级的[表达]

描述

这个超级的关键字有两种用法:作为“函数调用”(super(…参数)),或作为“属性查找”(超级螺旋桨超级[expr]).

注: 超级的是一个关键字,这些是特殊的句法结构。超级的不是指向原型对象的变量。正在尝试读取超级的它本身是一个语法错误.

js型
常数小孩= {
  我的父母() {慰问.日志(超级的); //语法错误:此处意外出现“super”关键字
  },
};

建造师派生类的主体(带有延伸),的超级的关键字可能显示为“函数调用”(super(…参数)),必须在关键字,并且在构造函数返回之前。它调用父类的构造函数并绑定父类的公共字段,然后派生类的构造函数可以进一步访问和修改.

“属性查找”表单可用于访问对象文字或类的[[Prototype]]的方法和属性。在类的主体中超级的可以是超类的构造函数本身,也可以是构造函数的原型,取决于执行上下文是实例创建还是类初始化。有关更多详细信息,请参阅示例部分。

请注意超级的由类或对象文字确定超级的是在中声明的,而不是调用该方法的对象。因此,解除绑定或重新绑定方法不会更改的引用超级的在其中(尽管他们确实更改了的引用). 你可以看到超级的作为类或对象文字范围中的变量,方法在其上创建闭包。(但也要注意,它实际上并不是一个变量,如上所述。)

通过设置属性时超级的,属性设置为而不是。

示例

在类中使用super

此代码段取自类示例(现场演示). 在这里super()调用以避免重复在矩形方形.

js型
 矩形 {
  建造师(高度,宽度) {
    .名称= “矩形”;
    .高度=高度;
    .宽度=宽度;
  }
  说出姓名() {慰问.日志(`嗨,我是${.名称}.`);
  }
  得到 地区() {
    返回 .高度* .宽度;
  }
  设置 地区(价值) {
    ._面积=价值;
  }
}

 方形 延伸 矩形 {
  建造师(长度) {
    //在这里,它使用长度调用父类的构造函数
    //为矩形的宽度和高度提供
    超级的(长度,长度);

    //注意:在派生类中,必须先调用super()
    //可以使用“this”。将其移到顶部会导致ReferenceError。
    .名称= “方形”;
  }
}

超级调用静态方法

你也可以打电话给super静止的方法。

js型
 矩形 {
  静止的 logNb边() {
    返回 “我有四个方面”;
  }
}

 方形 延伸 矩形 {
  静止的 日志描述() {
    返回 `${超级的.logNb边()}都是平等的`;
  }
}方形.日志描述(); //“我有四个相等的边”

访问类中的超级字段声明

超级的也可以在类字段初始化期间访问。参考超级的取决于当前字段是实例字段还是静态字段。

js型
 底座 {
  静止的基本静态字段= 90;
  基本方法() {
    返回 10;
  }
}

 扩展 延伸 底座 {扩展字段= 超级的.基本方法(); // 10
  静止的扩展静态字段= 超级的.基本静态字段; // 90
}

请注意,实例字段是在实例上设置的,而不是构造函数的原型,所以您不能使用超级的访问超类的实例字段。

js型
 底座 {基本字段= 10;
}

 扩展 延伸 底座 {扩展字段= 超级的.基本字段; //未定义
}

在这里,扩展字段未定义而不是10,因为基本字段定义为底座实例,而不是基本原型.超级的,在此上下文中,仅查找上的属性基本原型,因为这是的[[原型]]扩展原型.

删除超级属性将引发错误

您不能使用删除操作人员超级螺旋桨超级[expr]要删除父类的属性,它将抛出一个引用错误.

js型
 底座 {
  foo公司() {}
}
 派生 延伸 底座 {
  删除() {
    删除 超级的.foo公司; //这太糟糕了
  }
}

新的 派生().删除(); //ReferenceError:涉及“super”的删除无效。

在对象文本中使用super.prop

Super也可以用于对象初始化器符号。在这个例子中,两个对象定义了一个方法。在第二个对象中,超级的调用第一个对象的方法。这是在Object.setPrototypeOf()我们可以用它设置对象2对象1,所以超级的能够找到方法1对象1.

js型
常数对象1= {
  方法1() {慰问.日志(“方法1”);
  },
};

常数对象2= {
  方法2() {
    超级的.方法1();
  },
};对象.设置原型Of(对象2,对象1);对象2.方法2(); //记录“方法1”

当绑定到其他对象时,读取super.prop的方法不会有不同的行为

正在访问超级的。x个行为类似Reflect.get(Object.getPrototypeOf(objectLiteral),“x”,this),这意味着始终在对象文本/类声明的原型上查找属性,解除绑定和重新绑定方法不会更改的引用超级的.

js型
 底座 {
  基本获取X() {
    返回 1;
  }
}
 扩展 延伸 底座 {
  获取X() {
    返回 超级的.基本获取X();
  }
}

常数e(电子)= 新的 扩展();慰问.日志(e(电子).获取X()); // 1
常数 {获取X} =e(电子);慰问.日志(获取X()); // 1

同样的情况也发生在对象文字中。

js型
常数家长1= { 支柱: 1 };
常数父母2= { 支柱: 2 };

常数小孩= {
  我的父母() {慰问.日志(超级的.支柱);
  },
};对象.设置原型(小孩,家长1);小孩.我的父母(); //日志“1”

常数我的父母=小孩.我的父母;
我的父母(); //仍记录“1”

常数另一个孩子= { __原型__:父母2,我的父母};另一个孩子.我的父母(); //仍记录“1”

只有重置整个继承链才会更改的引用超级的.

js型
 底座 {
  基本获取X() {
    返回 1;
  }
  静止的 静态BaseGetX() {
    返回 ;
  }
}
 AnotherBase公司 {
  基本获取X() {
    返回 2;
  }
  静止的 静态BaseGetX() {
    返回 4;
  }
}
 扩展 延伸 底座 {
  获取X() {
    返回 超级的.基本获取X();
  }
  静止的 静态GetX() {
    返回 超级的.静态BaseGetX();
  }
}

常数e(电子)= 新的 扩展();
//重置实例继承对象.设置原型Of(扩展.原型, 另一个底座.原型);慰问.日志(e(电子).获取X()); //记录“2”而不是“1”,因为原型链已更改慰问.日志(扩展.静态GetX()); //仍然记录“3”,因为我们还没有修改静态部分
//重置静态继承对象.设置原型(扩展,另一个底座);慰问.日志(扩展.静态GetX()); //现在记录“4”

从超级调用方法

打电话时超级螺旋桨作为函数中的值支柱函数是当前,而不是超级的指向。例如super.getName()通话记录“扩展”,尽管代码看起来相当于基础.getName().

js型
 底座 {
  静止的 获取名称() {慰问.日志(.名称);
  }
}

 扩展 延伸 底座 {
  静止的 获取名称() {
    超级的.获取名称();
  }
}扩展.获取名称(); //日志“扩展”

这在与静态私有属性.

设置super.prop将设置此的属性

正在设置的属性超级的,例如超级.x=1,行为类似Reflect.set(Object.getPrototypeOf(objectLiteral),“x”,1,this)这是理解超级的简单地说,“prototype对象的引用”是不够的,因为它实际上设置了而不是。

js型
 A类 {}
 B类 延伸 A类 {
  集合X() {
    超级的.x个= 1;
  }
}

常数b条= 新的 B类();b条.集合X();慰问.日志(b条); //B{x:1}慰问.日志(对象.hasOwn(拥有)(b条, “x”)); //真的

超级.x=1将查找的属性描述符x个A.原型(并调用此处定义的setter),但值将设置为,这是b条在这种情况下。你可以阅读反射集有关案件的更多详细信息,请参见目标接受者不同。

这意味着虽然方法得到 超级螺旋桨通常不易受上下文,那些设置 超级螺旋桨是。

js型
/*重复使用与上面相同的声明*/

常数b2型= 新的 B类();b2型.集合X.呼叫(无效的); //TypeError:无法分配给对象“null”的只读属性“x”

然而,超级.x=1仍然会引用原型对象的属性描述符,这意味着您无法重写不可写的属性,并且会调用setter。

js型
 X(X) {
  建造师() {
    //创建不可写属性对象.定义属性(, “道具”, {
      可配置的: 真的,
      可写的: ,
      价值: 1,
    });
  }
}

 Y(Y) 延伸 X(X) {
  建造师() {
    超级的();
  }
  foo公司() {
    超级的.支柱= 2; //无法覆盖该值。
  }
}

常数= 新的 Y(Y)();.foo公司(); //TypeError:“prop”是只读的慰问.日志(.支柱); // 1

规格

规范
ECMAScript语言规范
#sec-super关键字

浏览器兼容性

BCD表仅在浏览器中加载

另请参见