Prototype 继承(ES5)和 Class 继承(ES6)区别
-
ES5 继承实质是先创造子类的实例对象 this,然后再将父类的方法添加到 this 上面(Parent.apply(this))。
-
ES6 继承机制完全不同,实质是先将父类实例对象的属性和方法添加到 this 上。(这里必须先调用 super 方法),然后再用子类的构造函数修改 this 。需要注意的是,class 关键字只是原型的语法糖, JavaScript 继承仍然是基于原型实现的。
继承
面向对象编程很重要的一个方面,就是对象的继承。A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法。这对于代码的复用是非常有用的。大部分面向对象的编程语言,都是通过“类”(class)实现对象的继承。传统上,JavaScript 语言的继承不通过 class(ES6 引入了class 语法),而是通过“原型对象”(prototype)实现。在JS中常见的继承方式有六种。
六种方式
-
原型链继承: 子类型的原型为父类型的一个实例对象。
-
借用构造函数继承: 在子类型构造函数中通用call()调用父类型构造函数。
-
原型链+借用构造函数的组合继承: 通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用。
-
组合继承优化1: 通过父类原型和子类原型指向同一对象,子类可以继承到父类的公有方法当做自己的公有方法,而且不会初始化两次实例方法/属性,避免的组合继承的缺点。
-
组合继承优化2: 借助原型可以基于已有的对象来创建对象,
var B = Object.create(A)
以A对象为原型,生成了B对象。B继承了A的所有属性和方法。 -
ES6 中class 的继承: Class 继承和 Prototype 继承并不完全相同。Class 继承是 ES6 引入的语法,通过 extends 关键字来实现继承,语法简洁明了。还可以通过 static 关键字定义类的静态方法,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
class Person {
//调用类的构造方法
constructor(name, age) {
this.name = name
this.age = age
}
//定义一般的方法
showName () {
console.log("调用父类的方法")
console.log(this.name, this.age);
}
}
let p1 = new Person('kobe', 39)
console.log(p1)
//定义一个子类
class Student extends Person {
constructor(name, age, salary) {
super(name, age)//通过super调用父类的构造方法
this.salary = salary
}
showName () {//在子类自身定义方法
console.log("调用子类的方法")
console.log(this.name, this.age, this.salary);
}
}
let s1 = new Student('wade', 38, 1000000000)
console.log(s1)
s1.showName()
优点:语法简单易懂,操作更方便
缺点:并不是所有的浏览器都支持class关键字
参考文章