【ES6 教程】第四章 ES6类07—JavaScript继承使用extends & super

03294a5b6715689610aa5dfbdd7f683e.png

英文 | https://www.javascripttutorial.net

翻译 | 杨小爱

在今天的文章中,我们将一起来学习如何在 ES6 中使用 extends 和 super 实现 JavaScript 继承。

使用extends和super实现JavaScript继承

在 ES6 之前,实现正确的继承需要多个步骤,最常用的策略之一是原型继承。

下面说明了 Bird 如何使用原型继承技术从 Animal 继承属性:

 
 
function Animal(legs) {
    this.legs = legs;
}


Animal.prototype.walk = function() {
    console.log('walking on ' + this.legs + ' legs');
}


function Bird(legs) {
    Animal.call(this, legs);
}


Bird.prototype = Object.create(Animal.prototype);
Bird.prototype.constructor = Animal;




Bird.prototype.fly = function() {
    console.log('flying');
}


var pigeon = new Bird(2);
pigeon.walk(); // walking on 2 legs
pigeon.fly();  // flying

ES6 通过使用 extends 和 super 关键字简化了这些步骤。

以下示例定义了 Animal 和 Bird 类,并通过 extends 和 super 关键字建立继承。

 
 
class Animal {
    constructor(legs) {
        this.legs = legs;
    }
    walk() {
        console.log('walking on ' + this.legs + ' legs');
    }
}


class Bird extends Animal {
    constructor(legs) {
        super(legs);
    }
    fly() {
        console.log('flying');
    }
}




let bird = new Bird(2);


bird.walk();
bird.fly();

它们怎么运作。

首先,使用 extends 关键字使 Bird 类继承自 Animal 类:

 
 
class Bird extends Animal {
   // ...
}

Animal 类称为基类或父类,而 Bird 类称为派生类或子类。通过这样做,Bird 类继承了 Animal 类的所有方法和属性。

其次,在 Bird 的构造函数中,调用 super() 以调用带有 leg 参数的 Animal 的构造函数。

如果子类有构造函数,JavaScript 要求子类调用 super()。正如你在 Bird 类中看到的,super(legs) 等价于 ES5 中的以下语句:

 
 
Animal.call(this, legs);

如果 Bird 类没有构造函数,则无需执行任何其他操作:

 
 
class Bird extends Animal {
    fly() {
        console.log('flying');
    }
}

它等价于以下类:

 
 
class Bird extends Animal {
    constructor(...args) {
        super(...args);
    }
    fly() {
        console.log('flying');
    }
}

但是,子类有一个构造函数,它需要调用super()。例如,以下代码会导致错误:

 
 
class Bird extends Animal {
    constructor(legs) {
    }
    fly() {
        console.log('flying');
    }
}

错误:

 
 
ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor代码语言:JavaScript  (javascript )

因为super()初始化了this对象,所以,在访问this对象之前需要调用super()。在调用 super() 之前尝试访问它也会导致错误。

例如,如果要初始化 Bird 类的 color 属性,可以如下进行:

 
 
class Bird extends Animal {
  constructor(legs, color) {
    super(legs);
    this.color = color;
  }
  fly() {
    console.log("flying");
  }
  getColor() {
    return this.color;
  }
}


let pegion = new Bird(2, "white");
console.log(pegion.getColor());

Shadowing methods

ES6 允许子类和父类拥有同名的方法。在这种情况下,当你调用子类的某个对象的方法时,子类中的方法会影响父类中的方法。

以下 Dog 类扩展了 Animal 类并重新定义了 walk() 方法:

 
 
class Dog extends Animal {
    constructor() {
        super(4);
    }
    walk() {
        console.log(`go walking`);
    }
}


let bingo = new Dog();
bingo.walk(); // go walking

要在子类中调用父类的方法,可以像这样使用 super.method(arguments):

 
 
class Dog extends Animal {
    constructor() {
        super(4);
    }
    walk() {
        super.walk();
        console.log(`go walking`);
    }
}


let bingo = new Dog();
bingo.walk();
// walking on 4 legs
// go walking

继承静态成员

除了属性和方法,子类还继承了父类的所有静态属性和方法。例如:

 
 
class Animal {
    constructor(legs) {
        this.legs = legs;
    }
    walk() {
        console.log('walking on ' + this.legs + ' legs');
    }
    static helloWorld() {
        console.log('Hello World');
    }
}


class Bird extends Animal {
    fly() {
        console.log('flying');
    }
}

在此示例中,Animal 类具有 helloWorld() 静态方法,此方法可用作 Bird.helloWorld(),其行为与 Animal.helloWorld() 方法相同:

 
 
Bird.helloWorld(); // Hello World

从内置类型继承

JavaScript 允许你通过继承扩展内置类型,例如 Array、String、Map 和 Set。

以下 Queue 类扩展了 Array 引用类型,语法比使用构造函数/原型模式实现的队列要干净得多。

 
 
class Queue extends Array {
    enqueue(e) {
        super.push(e);
    }
    dequeue() {
        return super.shift();
    }
    peek() {
        return !this.empty() ? this[0] : undefined;
    }
    empty() {
        return this.length === 0;
    }
}


var customers = new Queue();
customers.enqueue('A');
customers.enqueue('B');
customers.enqueue('C');


while (!customers.empty()) {
    console.log(customers.dequeue());
}

总结

在 ES6 中使用 extends 关键字来实现继承,要扩展的类称为基类或父类,扩展基类或父类的类称为派生类或子类。

在子类的构造函数中调用 super(arguments) 来调用父类的构造函数。

使用 super 关键字在子类的方法中调用父类的方法。

学习更多技能

请点击下方公众号

dbff97186ef5ad6232900150ae23d8f0.gif

f75ae57efe922b08c4d7c028819d34ba.jpeg

8d8ae25059313699ac019be71f8095c9.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值