ES5与ES6的继承语法

本文深入探讨了JavaScript中面向对象编程(OOP)的实现方式,包括ES5和ES6的继承模型。通过具体代码示例,讲解了如何在JS中通过原型链实现类的继承,以及ES6中class语法糖的使用。
前言

本文默认读者对于JavaScript原型链面向对象编程OOP有一定的了解

JS中没有类class的概念也没有继承的概念,这里使用这些术语只是为了方便理解JS面向对象编程的方式

ES5的JS继承模型

//基类
function Animal(name, energy) {
    this.name = name
    this.energy = energy
}

Animal.prototype.eat = function (amount) {
    console.log(`${this.name} is eating.`)
    this.energy += amount
}

Animal.prototype.sleep = function (length) {
    console.log(`${this.name} is sleeping.`)
    this.energy += length
}
Animal.prototype.play = function (length) {
    console.log(`${this.name} is playing.`)
    this.energy -= length
}
复制代码

//子类
function Dog(name, energy, breed) {
    Animal.call(this, name, energy)
    this.breed = breed	
}
Dog.prototype = Object.create(Animal.prototype) 
Dog.prototype.constructor = Dog 
Dog.prototype.bark = function () {
    console.log('Woof Woof!')
    this.energy -= 1
}
复制代码

ES5中实现继承的几个关键操作:

  • 子类构造函数中调用父类的构造函数,实现部分属性构造

    Animal.call(this, name, energy)

    操作本质在于:对于子类实例调用父类的构造函数,但是this关键字的指向是子类的实例,而不是父类实例

  • 子类的原型对象指向父类

    Dog.prototype = Object.create(Animal.prototype)

    子类的原型是父类的一个实例对象,因此原型链的查找原则对于子类适用

  • 子类的构造函数指向子类自身的构造函数

    Dog.prototype.constructor = Dog

    由于上面第二步的操作,导致子类原型对象(也就是父类的一个实例对象)的constructor属性是父类的构造函数,因此需要手动将其设置为子类自身原来的构造函数

ES6中原型与继承

ES6中JS可以使用class关键字,但是只是语法糖(syntax sugar)而已,本质上原型链方式并没有改变

//父类
class Animal{
    constructor(name,energy){
        this.name=name
        this.energy=energy
    }
    eat (amount) {
        console.log(`${this.name} is eating.`)
        this.energy += amount
    }
    sleep(length) {
        console.log(`${this.name} is sleeping.`)
        this.energy += length
    }
    play(length) {
        console.log(`${this.name} is playing.`)
        this.energy -= length
    }
}
//子类
class Dog extends Animal{
    constructor(name,energy,breed){
        super(name,energy)
        this.breed=breed
    }
    bark() {
        console.log('Woof Woof!')
        this.energy -= 1
    }    
}
复制代码

作为JS原语言使用者的一些感想

JavaScript是一门多范式编程语言,可以是 函数式编程面向对象编程面向过程编程...

这里的范式指代编程中的一些原则:

  1. js中函数也是一种数据类型,因此可以实现函数式编程方式
  2. 如同本文讲述的JS继承语法问题,这让JS可以实现面向对象编程的方式

。。。。。。

本质而言,这些都是语法层面上为熟悉OOP编程或者FP编程开发者减少开发时间成本

我个人对JS语言感觉就是,这门语言真的很混乱,从语言标准ES到语言实现JS存在这很大的差距,不仅是语法上的差距,还有实现原理上的差距,幸运的是我们有 babelJS

所以个人看法就是:熟悉JS基本原理 + 学习ES最新语法 + babel转码

有反驳的欢迎来锤

### ES5 ES6 继承的区别 在 JavaScript 中,继承机制是面向对象编程的核心概念之一。ES5ES6 都支持继承,但它们在实现方式和行为上存在显著差异。 #### 1. 创建对象的方式 ES5 中的继承通常通过构造函数和原型链实现。例如,可以通过原型链继承、借用构造函数继承或组合继承等方式实现。这些方式通常涉及手动操作原型链和构造函数调用。 ```javascript function Person(name) { this.name = name; } Person.prototype.sayHello = function() { console.log('Hello, ' + this.name); }; function Student(name, grade) { Person.call(this, name); // 借用构造函数继承 this.grade = grade; } Student.prototype = Object.create(Person.prototype); // 原型链继承 Student.prototype.constructor = Student; ``` ES6 引入了 `class` 和 `extends` 关键字,简化了继承的实现。通过 `class` 关键字定义类,使用 `extends` 关键字实现继承。 ```javascript class Person { constructor(name) { this.name = name; } sayHello() { console.log('Hello, ' + this.name); } } class Student extends Person { constructor(name, grade) { super(name); // 调用父类的构造函数 this.grade = grade; } } ``` #### 2. `this` 对象的创建顺序 在 ES5 中,子类的构造函数会先创建自己的 `this` 对象,然后通过调用父类的构造函数来修改这个 `this` 对象。这种方式允许子类在调用父类构造函数之前进行一些操作。 在 ES6 中,子类的构造函数必须先调用 `super()` 方法,这是为了确保父类的 `this` 对象已经被创建并可以被子类继承[^5]。如果不调用 `super()`,子类将无法获得 `this` 对象,从而导致错误。 #### 3. 原型链的设置 在 ES5 中,手动设置子类的原型链通常涉及使用 `Object.create()` 方法来创建一个新的对象,并将其赋值给子类的原型。 ```javascript Student.prototype = Object.create(Person.prototype); Student.prototype.constructor = Student; ``` 在 ES6 中,`class` 和 `extends` 关键字自动处理了原型链的设置。子类的原型对象的 `__proto__` 属性会自动指向父类的原型对象。 ```javascript console.log(Student.prototype.__proto__ === Person.prototype); // true ``` #### 4. 继承机制的底层实现 尽管 ES6 提供了更简洁的语法,但其底层实现仍然是基于 ES5 的混合继承方式。ES6 的 `class` 和 `extends` 只是对这些机制的一种封装,使得继承的实现更加直观和易于理解[^3]。 #### 5. 调用 `super` 方法 在 ES6 中,子类必须在 `constructor` 方法中调用 `super` 方法,否则在创建实例时会报错。这是因为子类没有自己的 `this` 对象,而是继承了父类的 `this` 对象,并对其进行加工。如果不调用 `super` 方法,子类将无法获得 `this` 对象[^5]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值