super 关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。
1、super当做函数使用
super 作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次 super() 函数。注意:作为函数时,super() 只能用在子类的构造函数之中,用在其他地方就会报错。
- class A {}
- class B extends A {
- constructor() {
- super();
- }
- }
super 作为函数调用时,内部的 this 指的是子类实例
- class A {
- constructor() {
- this.show();
- }
- }
- class B extends A {
- constructor() {
- super();
- }
- show(){
- console.log('实例');
- }
- static show(){
- console.log('子类');
- }
- }
- new B() //输出 '实例' ,new B 时触发了 B 的构造函数,所以触发了 super 方法,即触发了父类 A 的构造函数,此时的 this.show 的 this 指的是子类
2、super 作为对象使用
super 作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
2.1、super在普通方法中(即非静态方法)及此时的 this 关键字指向
- class A {
- p() {
- return 2;
- }
- }
- class B extends A {
- constructor() {
- super();
- console.log(super.p()); // 2 此时的super指向父类原型对象,即 A.prototype
- }
- }
- let b = new B(); //2
由于在普通方法中的 super 指向父类的原型对象,所以如果父类上的方法或属性是定义在实例上的,就无法通过 super 调用的。如下所示:
- class A {
- constructor() { //在构造函数上定义的属性和方法相当于定义在父类实例上的,而不是原型对象上
- this.p = 2;
- }
- }
- class B extends A {
- get m() {
- return super.p;
- }
- }
- let b = new B();
- console.log(b.m) // undefined
在子类普通方法中通过 super 调用父类的方法时,方法内部的 this 指向的是当前的子类实例。
- class A {
- constructor() {
- this.x = 1;
- }
- print() {
- console.log(this.x);
- }
- }
- class B extends A {
- constructor() {
- super();
- this.x = 2;
- super.y = 123; //如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性。
- }
- m() {
- super.print();
- }
- }
- let b = new B();
- b.m() // 2
- console.log(b.y); //123
2.2、super在静态方法中及此时的 this 关键字指向
super作为对象,用在静态方法之中,这时 super 将直接指向父类,而不是父类的原型对象。
- class Parent {
- static myMethod(msg) {
- console.log('static', msg);
- }
- myMethod(msg) {
- console.log('instance', msg);
- }
- }
- class Child extends Parent {
- static myMethod(msg) {
- super.myMethod(msg);
- }
- myMethod(msg) {
- super.myMethod(msg);
- }
- }
- Child.myMethod(1); // static 1
- var child = new Child();
- child.myMethod(2); // instance 2
在子类的静态方法中通过 super 调用父类的方法时,方法内部的 this 指向当前的子类,而不是子类的实例。
- class A {
- constructor() {
- this.x = 1;
- }
- static print() {
- console.log(this.x);
- }
- }
- class B extends A {
- constructor() {
- super();
- this.x = 2;
- }
- static m() {
- super.print();
- }
- }
- B.x = 3;
- B.m() // 3
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
2020-08-17 react组件通信方式总结