白骑士的JavaScript教学进阶篇之原型与继承 3.1.2 继承的实现(ES5与ES6)

        继承是面向对象编程中的一个重要概念,它允许一个对象基于另一个对象来创建,并继承其属性和方法。JavaScript中的继承是通过原型链实现的,但在不同的版本中,继承的实现方式有所不同。传统上(ES5),JavaScript通过原型和构造函数来实现继承,而在ES6中,引入了 ‘class‘ 语法,使得继承变得更加直观和易于使用。在本节中,我们将详细探讨如何在ES5和ES6中实现继承,帮助你理解这两种实现方式的异同,并在实际开发中选择适合的方案。

ES5中的继承

        在ES5中,继承是通过构造函数和原型链手动实现的。主要步骤包括:定义父构造函数,创建子构造函数,设置子构造函数的原型为父构造函数的实例,并确保子构造函数的 ‘constructor‘ 指向自身。

定义父构造函数

        父构造函数通常包含父类的属性和方法。

示例

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

Animal.prototype.speak = function() {
    console.log(this.name + ' makes a sound.');
};

        在这个示例中,‘Animal‘ 构造函数定义了一个 ‘name‘ 属性,并且在 ‘Animal.prototype‘ 上定义了一个 ‘speak‘ 方法。

创建子构造函数

        子构造函数继承父构造函数的属性,并可以定义自己的属性和方法。

示例

function Dog(name, breed) {
    Animal.call(this, name); // 继承父类的属性
    this.breed = breed;
}

        在这个示例中,‘Dog‘ 构造函数通过 ‘Animal.call(this, name)‘ 调用了父构造函数,继承了 ‘name‘ 属性,同时 ‘Dog‘ 自己也定义了一个 ‘breed‘ 属性。

设置原型链

        为了让子构造函数继承父构造函数的方法,需要将子构造函数的原型设置为父构造函数的实例,并确保 ‘constructor‘ 指向子构造函数本身。

示例

Dog.prototype = Object.create(Animal.prototype); // 设置原型链
Dog.prototype.constructor = Dog; // 修正 constructor 的指向

Dog.prototype.speak = function() {
    console.log(this.name + ' barks.');
};

        在这个示例中,‘Dog.prototype‘ 被设置为 ‘Animal.prototype‘ 的一个新实例,这意味着 ‘Dog‘ 实例可以访问 ‘Animal‘ 的方法。我们还通过 ‘Dog.prototype.constructor = Dog;‘ 确保 ‘constructor‘ 指向正确的构造函数。

使用子类

示例

let myDog = new Dog('Rex', 'German Shepherd');
myDog.speak(); // 输出: Rex barks.

        在这个示例中,‘myDog‘ 是 ‘Dog‘ 类的实例,并继承了 ‘Animal‘ 类的 ‘speak‘ 方法。由于我们在 ‘Dog.prototype‘ 上重新定义了 ‘speak‘ 方法,所以它会覆盖 ‘Animal.prototype.speak‘,输出“Rex barks”。

ES6中的继承

        ES6引入了 ‘class‘ 语法,使得定义类和实现继承变得更加简洁和易于理解。‘class‘ 语法背后依然是基于原型的继承机制,但语法上更贴近传统面向对象编程的语言如Java、C++等。

定义父类

        在ES6中,父类通过 ‘class‘ 关键字定义,类似于传统的构造函数。

示例

class Animal {
    constructor(name) {
        this.name = name;
    }

    speak() {
        console.log(‘${this.name} makes a sound.‘);
    }
}

        在这个示例中,‘Animal‘ 类定义了一个 ‘constructor‘ 方法来初始化 ‘name‘ 属性,并且有一个 ‘speak‘ 方法。

创建子类

        在ES6中,子类通过 ‘extends‘ 关键字继承父类。子类可以调用父类的 ‘constructor‘ 方法来继承父类的属性,并可以定义自己的属性和方法。

示例

class Dog extends Animal {
    constructor(name, breed) {
        super(name); // 调用父类的 constructor 方法
        this.breed = breed;
    }

    speak() {
        console.log(‘${this.name} barks.‘);
    }
}

        在这个示例中,‘Dog‘ 类继承了 ‘Animal‘ 类。‘super(name)‘ 调用了父类的构造函数,并传递了 ‘name‘ 参数,同时 ‘Dog‘ 类还增加了一个 ‘breed‘ 属性。‘speak‘ 方法在 ‘Dog‘ 类中被重新定义,覆盖了父类的实现。

使用子类

示例

let myDog = new Dog('Rex', 'German Shepherd');
myDog.speak(); // 输出: Rex barks.

        在这个示例中,‘myDog‘ 是 ‘Dog‘ 类的实例,继承了 ‘Animal‘ 类的属性和方法,同时还拥有 ‘Dog‘ 类特有的行为。

ES5与ES6继承的对比

        虽然ES5和ES6实现继承的机制本质上相同,但ES6的 ‘class‘ 语法提供了更清晰、更简洁的方式来定义和使用继承。

  • 语法简洁:ES6通过 ‘class‘ 和 ‘extends‘ 关键字大大简化了类的定义和继承过程,而ES5需要手动处理原型链和 ‘constructor‘ 的指向。
  • 可读性更强:ES6的语法更贴近传统面向对象编程语言,使得代码更加易读和易于维护。
  • 原型链控制更简便:在ES5中,需要手动设置原型链并修正 ‘constructor‘ 的指向,而ES6则自动处理这些细节,使得代码更加规范。

总结

        理解JavaScript中的继承机制,无论是在ES5还是ES6中,都对于掌握JavaScript面向对象编程至关重要。ES6的 ‘class‘ 语法简化了继承的实现,提升了代码的可读性和开发效率。在现代JavaScript开发中,推荐使用ES6的继承语法,以便更好地组织代码结构,提升代码质量。通过深入掌握这两种继承方式,你将能够在不同的项目需求中灵活应用,编写更具扩展性和维护性的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白骑士所长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值