ES5/ES6 的继承除了写法以外还有什么区别?

发布于 2024-09-04 12:58:47 字数 5311 浏览 16 评论 0

在 ES5 和 ES6 中,继承机制不仅仅在写法上有区别,还有一些底层实现和行为上的差异。以下是 ES5 和 ES6 继承的主要区别:

1. 原型链的构建方式不同

ES5

  • 在 ES5 中,继承通常通过 prototypecallapply 方法来模拟。具体步骤包括将子类的 prototype 指向父类的实例,这样子类就继承了父类的所有属性和方法。
  • 为了确保子类构造函数的正确性,还需要手动调整 constructor 指向。
function Parent(name) {
    this.name = name;
}

Parent.prototype.sayName = function() {
    console.log(this.name);
};

function Child(name, age) {
    Parent.call(this, name); // 调用父类构造函数,继承属性
    this.age = age;
}

// 继承父类的方法
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

Child.prototype.sayAge = function() {
    console.log(this.age);
};

var child = new Child('John', 18);
child.sayName(); // 输出: John
child.sayAge();  // 输出: 18

在 ES5 中, Parent.call(this, name) 是为了在子类构造函数中调用父类构造函数,确保父类的属性能够正确地初始化。然后,通过 Object.create(Parent.prototype) 继承父类的方法和属性。

ES6

  • 在 ES6 中,使用 classextends 关键字来简化继承操作。子类通过 extends 关键字继承父类, super 关键字用于调用父类的构造函数和方法。
  • ES6 的继承机制与 ES5 的不同点在于,ES6 的子类会先初始化父类,随后再初始化子类的自身属性。
class Parent {
    constructor(name) {
        this.name = name;
    }

    sayName() {
        console.log(this.name);
    }
}

class Child extends Parent {
    constructor(name, age) {
        super(name); // 调用父类构造函数,继承属性
        this.age = age;
    }

    sayAge() {
        console.log(this.age);
    }
}

const child = new Child('John', 18);
child.sayName(); // 输出: John
child.sayAge();  // 输出: 18

在 ES6 中, super(name) 是必须的,因为 ES6 子类的构造函数中,必须先调用 super() ,才能使用 this 。这是因为在 ES6 中,子类的构造函数默认是空的,只有在调用了父类的构造函数后,子类才能完成自身的初始化。

2. 子类 this 的处理

ES5

  • 在 ES5 中, this 是先创建子类实例,再通过 Parent.call(this) 初始化父类的属性。

ES6

  • 在 ES6 中, this 的生成和绑定发生在调用 super() 之后。换句话说, super() 调用之前不能使用 this ,否则会抛出错误。
  • ES6 中, super() 的调用顺序决定了子类实例的初始化顺序,必须先调用父类构造函数来创建子类实例的 this 对象。
class Parent {
    constructor() {
        console.log('Parent constructor');
    }
}

class Child extends Parent {
    constructor() {
        // 如果此处不调用 super(),会报错
        console.log(this); // ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
        super(); 
        console.log('Child constructor');
    }
}

const child = new Child();

3. 内建对象的继承

ES5

  • 在 ES5 中,直接继承内建对象(如 ArrayError 等)是困难的。因为这些内建对象的构造函数在 ES5 中并不会返回正确的继承结果。
function MyArray() {
    Array.call(this);
}

MyArray.prototype = Object.create(Array.prototype);
MyArray.prototype.constructor = MyArray;

var arr = new MyArray();
arr.push(1); // 在 ES5 中,这样做并不会正常工作

ES6

  • 在 ES6 中,通过 classextends ,可以轻松地继承内建对象。ES6 继承机制内部处理了继承内建对象时的一些复杂性,确保子类正确地继承内建对象的方法和行为。
class MyArray extends Array {
    constructor(...args) {
        super(...args);
    }
}

const arr = new MyArray();
arr.push(1);
console.log(arr); // [1],在 ES6 中可以正常工作

4. 静态方法的继承

ES5

  • 在 ES5 中,静态方法需要手动继承。
function Parent() {}

Parent.staticMethod = function() {
    console.log('Parent static method');
};

function Child() {}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

// 手动继承静态方法
Child.staticMethod = Parent.staticMethod;

Child.staticMethod(); // 输出: Parent static method

ES6

  • 在 ES6 中,静态方法通过 extends 关键字自动继承,无需手动处理。
class Parent {
    static staticMethod() {
        console.log('Parent static method');
    }
}

class Child extends Parent {}

Child.staticMethod(); // 输出: Parent static method

5. 在引擎层面的优化

  • ES5 :由于 ES5 的继承是通过函数、原型链和手动管理 constructor 来实现,开发者需要显式处理继承细节,如原型链的连接、属性的初始化等,这种实现方式可能在某些场景下会导致性能开销较大。
  • ES6 :ES6 的继承机制是基于更现代的 class 语法和 super 关键字,JavaScript 引擎对其进行了优化,因此在某些情况下,ES6 的继承性能可能会优于 ES5。

总结

  • 写法上 :ES6 的继承写法更简洁、直观,使用了 classextendssuper 等关键字,而 ES5 需要手动操作原型链和构造函数。
  • this 绑定 :在 ES6 中, this 的绑定依赖于 super() 的调用,而 ES5 中 this 的绑定发生在构造函数调用时。
  • 内建对象继承 :ES6 对内建对象的继承支持更好。
  • 静态方法继承 :ES6 中静态方法继承更加自动化。
  • 性能和优化 :ES6 在底层引擎层面对 class 继承进行了优化,可能在某些场景下比 ES5 继承更高效。

总体来说,ES6 的继承机制更符合面向对象编程的概念,并简化了代码书写和维护。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

非要怀念

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

linfzu01

文章 0 评论 0

可遇━不可求

文章 0 评论 0

枕梦

文章 0 评论 0

qq_3LFa8Q

文章 0 评论 0

JP

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文