(八) class中的继承

class中的继承

extends 关键字

class Father { }
class Son extends Father { }

super 关键字

super既可以当作函数又可以当作对象

1. 当作函数使用时

先来看一个示例, A继承自B, 然后直接实例化A

class B { }
class A extends B {
  constructor() {
    console.log(this)
  }
}
new A()
//  Must call super constructor in derived class before accessing 'this' or returning from derived
//  constructor
//  在访问“this”或从派生构造函数返回之前,必须在派生类中调用超级构造函数

**报错了 ! ** 从错误中很容易看出, 我们要先在子类中调用super()函数, 才能访问this,这也是ES6的规定

  • super当函数使用时, 规定只能在子类的constructor中使用, 且必须写在constructor开头第一行

这是因为当使用extends继承时, 子类是没有this对象的, 而是继承父类的this对象, 并对其进行一些加工, 而super()函数就是来做这件事的,

  • @记住: 使用extends继承必须在子类构造函数的第一行调用super()函数, 且只能在子类构造函数中使用
class B { }
class A extends B {
  constructor() {
    super()
    console.log(this)
  }
}
new A()   // A {}

而且, 当通过调用super()来继承父类的this时, 会调用父类的constructor方法, 并为子类返回一个this, this指向的是子类的实例

示例 => 验证调用super()后的this指向子类的实例

class A {
  info = "我是父类的实例属性"
  print() {
    console.log(this.info)
  }
}

class B extends A {
  info = "我是子类的实例属性"
  constructor() {
    super()
  }

  m() {
    // super当对象使用, 介绍在下面
    super.print()
  }
}
let b = new B()
b.m() // 我是子类的实例属性

2. 当作对象使用时

2.1 在普通方法中

super (没有小括号, 表示对象) 在普通方法中, 指向父类的原型对象

  • 直接在类内部定义的方法都是定义在原型上的
  • 直接定义在类内部的属性是实例属性

示例 1

class Father {
  name = 'father'
	say() {
  console.log('我是父类原型上的方法')
	}
}

class Son extends Father {
  constructor() {
    super()

    console.log(super.name)   // undefined
    super.say()   // 我是父类原型上的方法
  }
}

new Son()

通过super对子类属性赋值时, super相当于子类实例里面的this

示例 2

class A {
  constructor() {
    this.x = 1
  }
}

class B extends A {
  constructor() {
    super()
    console.log(this.x)   // 1  调用super后, 自动调用父类的构造函数
    this.x = 2
    super.x = 3 	// 相当于this.x = 3
    console.log(super.x); // undefined   
    console.log(this.x); // 3  
  }
}
new B()

2.2 在静态方法中

此时super将指向父类, 而不是父类的原型

  • 静态方法/属性又称为类方法/属性, 通过类名.方法名/属性名的方式调用

示例 3

class Father {
  static name = '我是父类的属性'
say() {
  console.log('我是父类原型上的方法')
}
}

class Son extends Father {
  constructor() {
    super()
  }
	
  static show() {
    console.log(super.name)   // 我是父类的属性
    super.say()   // .say is not a function, 因为say是父类原型上的方法
  }
}

Son.show()

巩固例子

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调用父类方法时, , super相当于子类实例里面的this

class Father {
  constructor() {
    this.name = 'father'
  }
  static say() {
    console.log(this.name)
  }
}

class Son extends Father {
  static name = '我是子类的属性'
  constructor() {
    super()
    this.name = 'son'
  }

  static show() {
    super.say()
  }
}
Son.show()    // 我是子类的属性
posted @ 2021-08-02 22:40  只猫  阅读(130)  评论(0编辑  收藏  举报