JavaScript 使用 extends 继承 class


JavaScript 的 extends 关键字是在 ES6 中引入的, 也包含连同一起使用的 super 关键字, 可以通过它们来进行 class 的继承

比如我们有一个名为 Book 的类, 包含 “书名” 与 “作者” 两个属性,以及一个书籍介绍的方法 getInfo()


            class Book {
                constructor(title, author){
                    this.title = title;
                    this.author = author;
                }
                // 获取书籍介绍
                getInfo(){
                    return "这本书叫《" + this.title 
                    + "》,作者是" + this.author;
                }
            }
        

更多关于 class 的定义: JS 如何使用 class 关键字定义类

使用 extends 进行继承

我们创建一个历史书籍类,名为 HistoryBook ,通过 extends 关键字让它继承自 Book类 ,并为它添加一个 “朝代” 属性 dynasty


            class HistoryBook extends Book {
                constructor(title, author, dynasty){
                    super(title, author);
                    this.dynasty = dynasty;
                }
            }
        

此处的 super 关键字用于显式调用父类构造函数 constructor

实例化子类

我们来尝试通过实例化一个 HistoryBook 类,看能否获得它的父类属性 titleauthor 以及父类方法 getInfo()


            let book = new HistoryBook("水浒传", "施耐庵", "北宋");
            console.log(book);
            console.log(book.getInfo());
        

打印如下:


            HistoryBook { title: '水浒传', author: '施耐庵', dynasty: '北宋' }
            这本书叫《水浒传》,作者是施耐庵
        

可以看到,通过实例化 HistoryBook 得到的 book 对象,包含了自身属性 dynasty,也包含父级属性 titleauthor ,以及父级方法 getInfo()

函数重写

如果子类的方法名与父级方法名一致,父级的将会被覆盖。比如我们在 HistoryBook 中定义一个与父级 Book 一致的函数名 getInfo()


            class HistoryBook extends Book {
                /* ... 此处省略了一些代码 */

                // 重写父级的 getInfo 方法
                getInfo(){
                    return "这本历史书叫《" + this.title 
                    + "》,作者是" + this.author 
                    + ",年代为:" + this.dynasty;
                }
            }
        

参照 #实例化子类 步骤实例化 book 对象后执行:


            console.log(book.getInfo());
        

调用的是重写后的函数,打印如下:


            这本历史书叫《水浒传》,作者是施耐庵,年代为:北宋
        

子类中的 this/super

在某些情况下,我们重写了父类的方法后,任然想要调用父类已被覆盖的方法,这时候可以使用 super 关键字。 例如,我们需要一个书籍的简短介绍的方法 getBriefInfo() ,想通过调用父级的 getInfo() 实现


            class HistoryBook extends Book {
                /* ... 此处省略了一些代码 */

                // 重写父级的 getInfo (书籍介绍)方法
                getInfo(){
                    return "这本历史书叫《" + this.title 
                    + "》,作者是" + this.author 
                    + ",年代为:" + this.dynasty;
                }

                // 书籍简短介绍
                getBriefInfo(){
                    return super.getInfo();
                }
            }
        

在文章开始时,我们在 HistoryBook 的构造函数 constructor 中使用过一次 super,那里我们将它当作函数来使用,作用是显示的调用父类构造函数。 而此处的 super 我们把它当作 “对象” 来使用,在这里它指代的是父类中的 this

子类中的 this 与常规类一样,都是指代类的实例本身

我们继续下一步,参照 #实例化子类 步骤实例化 book 对象后执行:


            console.log(book.getBriefInfo());
        

可以看到,打印的是父级的介绍


            这本书叫《水浒传》,作者是施耐庵
        

所以这里的 super.getInfo() 表示调用父级的 getInfo() 方法

完整代码


            // 书籍基类
            class Book {
                constructor(title, author){
                    this.title = title;
                    this.author = author;
                }
                // 获取书籍介绍
                getInfo(){
                    return "这本书叫《" + this.title 
                    + "》,作者是" + this.author;
                }
            }

            // 历史书籍,继承自 Book
            class HistoryBook extends Book {
                constructor(title, author, dynasty){
                    super(title, author);
                    this.dynasty = dynasty;//朝代
                }
                
                // 重写父级的 getInfo 方法,增加了年代的描述
                getInfo(){
                    return "这本历史书叫《" + this.title 
                    + "》,作者是" + this.author 
                    + ",年代为:" + this.dynasty;
                }

                // 书籍简短介绍,通过调用父级 getInfo 实现
                getBriefInfo(){
                    return super.getInfo();
                }
            }

            // 实例化 HistoryBook
            let book = new HistoryBook("水浒传", "施耐庵", "北宋");
            console.log(book);
            console.log(book.getInfo());
            console.log(book.getBriefInfo());
        

back home