JavaScript简餐——关于类的继承


前言

写本《JavaScript简餐》系列文章的目的是记录在阅读学习《JavaScript高级程序设计(第4版)》一书时出现的各个知识点。虽是对读书的笔记和总结,但是希望它轻量、简洁、犀利,不会引起阅读疲劳,可以在碎片化时间和闲暇之余轻巧地沐浴一下知识点。每篇文章只针对一个小部分进行讲解式的梳理,来达到个人复习总结和分享知识的目的。


一、继承基础

ECMAScript6新增的特性中最出色的一个就是原生支持了类继承机制。省去了之前ES5中各种花里胡哨的继承方式。虽然类继承使用的是新语法,但背后依旧使用的是原型链。ES6支持单继承。使用extends关键字,就可以继承任何拥有[ [Construct] ]和原型的对象。很大程度上,这意味着不仅可以继承一个类,也可以继承普通的构造函数。来看一下具体例子:
class Person {}

class Student extends Person {}

let stu = new Student();
console.log(stu instanceof Student); // true
console.log(stu instanceof Person); // true

function Animal() {}

class Dog extends Animal {}

let d = new Dog();
console.log(d instanceof Dog); // true
console.log(d instanceof Animal); // true
另外,类表达式中也可以使用extends关键字,如下所示:
let Student = class extends Person {}

二、super关键字

如果接触过JAVA一定会对super关键字感到非常亲切,在JavaScript中也同样有super关键字,这个关键字只能在派生类中使用,而且仅限于类构造函数、静态方法内部。在派生类构造函数中使用super可以调用父类构造函数。来看一下具体例子:
class Person {
  constructor() {
    this.name = "Lucy";
  }
}

class Student extends Person {
  constructor() {
    super();
  }
}

let stu = new Student();
console.log(stu.name); // Lucy
在静态方法中可以通过super调用父类上定义的静态方法:
class Person {
  static sayHi() {
    console.log("Hi, there!");
  }
}

class Student extends Person {
  static greeting() {
    super.sayHi();
  }
}

Student.greeting(); // Hi, there!
在使用super关键字时要注意的几个问题:
  1. super只能在派生类构造函数和静态方法中使用。
  2. 不能单独引用super关键字,要么用它调用构造函数,要么用它引用静态方法。
  3. 调用super()会调用父类构造函数,并将返回的实例赋值给this。
class Person {}

class Student extends Person {
  constructor() {
    super();
    console.log(this); // Student {}
  }
}

let stu = new Student();
  1. 在派生类中调用super()时是可以给super传参的,此参数将传给父类的构造函数。
  2. 如果没有定义类构造函数,在实例化派生类时会调用super(),而且会传入所有传给派生类的参数。
class Person {
  constructor(name) {
    this.name = name;
  }
}

class Student extends Person {}

console.log(new Student("Lucy")); // Student { name: 'Lucy' }
  1. 在派生类构造函数中,不能在调用super()之前引用this。
  2. 如果在派生类中显式定义了构造函数,则要么必须在其中调用super(),要么必须在其中返回一个对象。

三、抽象基类

有时候可能需要定义这样一个类,它可以供其他类继承,但本身不会被实例化。虽然ECMAScript没有专门支持这种语法,但通过new.target也很容易实现。new.target保存通过new关键字调用的类或函数。通过在实例化时检测new.target是不是抽象基类可以阻止对抽象基类的实例化。如下所示:
class Person {
  constructor() {
    if (new.target === Person) {
      throw new Error("Person cannot be directly instantiated!");
    }
  }
}

class Student extends Person {}

let stu = new Student();
console.log(stu); // Student {}
let p = new Person(); // Error: Person cannot be directly instantiated!

四、总结

以上就是今天要讲的内容,今天简单地介绍了一下类的继承方式、super关键字的用法和注意事项以及抽象基类和new.target的作用。下一篇我们来介绍一下代理Proxy。撒花~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值