返回

ES5 和 ES6 继承的区别与比较

前端

ES5 和 ES6 继承的区别

1. 原型链和类

1.1 原型链

在 ES5 中,继承是通过原型链来实现的。每个对象都有一个内部的属性 __proto__,指向其原型对象。原型对象包含了该对象继承的属性和方法。例如,如果我们定义了一个 Human 类,它具有 nameage 两个属性,我们可以使用 new Human("John", 25) 创建一个新的人类对象 john。该对象 john__proto__ 属性指向 Human.prototype,而 Human.prototype__proto__ 属性指向 Object.prototype

1.2 类

在 ES6 中,继承是通过 class 来实现的。类是一个语法糖,它使我们能够以更清晰和直观的方式定义对象。例如,我们可以定义一个 Human 类如下:

class Human {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

然后,我们可以使用 new Human("John", 25) 创建一个新的人类对象 john。该对象 john__proto__ 属性指向 Human.prototype

2. 继承语法

2.1 ES5

在 ES5 中,我们可以使用 Object.create() 方法来创建一个新对象,并指定其原型对象。例如,我们可以使用以下代码创建一个新的人类对象 john,其原型对象是 Human.prototype

var john = Object.create(Human.prototype);
john.name = "John";
john.age = 25;

2.2 ES6

在 ES6 中,我们可以使用 extends 关键字来继承另一个类。例如,我们可以定义一个 Student 类,它继承了 Human 类:

class Student extends Human {
  constructor(name, age, school) {
    super(name, age);
    this.school = school;
  }
}

然后,我们可以使用 new Student("John", 25, "Harvard") 创建一个新学生对象 john。该对象 john__proto__ 属性指向 Student.prototype,而 Student.prototype__proto__ 属性指向 Human.prototype

3. 方法重写

3.1 ES5

在 ES5 中,我们可以通过覆盖原型对象的方法来实现方法重写。例如,我们可以覆盖 Human.prototype.sayHello() 方法,为 Student 类定义一个新的 sayHello() 方法:

Human.prototype.sayHello = function() {
  console.log("Hello, I am a human!");
};

Student.prototype.sayHello = function() {
  console.log("Hello, I am a student!");
};

var john = new Student("John", 25, "Harvard");
john.sayHello(); // 输出:Hello, I am a student!

3.2 ES6

在 ES6 中,我们可以通过使用 super 关键字来实现方法重写。例如,我们可以覆盖 Human.prototype.sayHello() 方法,为 Student 类定义一个新的 sayHello() 方法:

class Human {
  sayHello() {
    console.log("Hello, I am a human!");
  }
}

class Student extends Human {
  sayHello() {
    super.sayHello(); // 调用父类的方法
    console.log("I am also a student!");
  }
}

var john = new Student("John", 25, "Harvard");
john.sayHello(); // 输出:Hello, I am a human! I am also a student!

4. 多态

4.1 ES5

在 ES5 中,我们可以通过覆盖原型对象的方法来实现多态。例如,我们可以覆盖 Human.prototype.sayHello() 方法,为 Student 类定义一个新的 sayHello() 方法:

Human.prototype.sayHello = function() {
  console.log("Hello, I am a human!");
};

Student.prototype.sayHello = function() {
  console.log("Hello, I am a student!");
};

var john = new Human("John", 25);
var mary = new Student("Mary", 22, "Harvard");

john.sayHello(); // 输出:Hello, I am a human!
mary.sayHello(); // 输出:Hello, I am a student!

4.2 ES6

在 ES6 中,我们可以通过使用 super 关键字来实现多态。例如,我们可以覆盖 Human.prototype.sayHello() 方法,为 Student 类定义一个新的 sayHello() 方法:

class Human {
  sayHello() {
    console.log("Hello, I am a human!");
  }
}

class Student extends Human {
  sayHello() {
    super.sayHello(); // 调用父类的方法
    console.log("I am also a student!");
  }
}

var john = new Human("John", 25);
var mary = new Student("Mary", 22, "Harvard");

john.sayHello(); // 输出:Hello, I am a human!
mary.sayHello(); // 输出:Hello, I am a human! I am also a student!

5. 总结

ES5 和 ES6 中的继承机制都有各自的优点和缺点。ES5 中的继承机制更灵活,但代码结构也更复杂。ES6 中的继承机制更清晰和直观,但它对类和方法的访问权限控制较严格。