面向对象编程很重要的一个方面,就是对象的继承。A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法。这对于代码的复用是非常有用的。
大部分面向对象的编程语言,都是通过“类”(class)实现对象的继承。传统上,JavaScript 语言的继承不通过 class(ES6 引入了class 语法),而是通过“原型对象”(prototype)实现。那么在JS中常见的继承方式有几种呢?
方式一、原型链继承
//父类型
function Animal(name) {
this.name = name;
this.eat = function (food) {
console.log(this.name + "正在吃:"+ food);
}
}
function Dog() {
}
Dog.prototype = new Animal();
Dog.prototype.name = "大皇狗";
var dog = new Dog();
console.log(dog.name);
dog.eat('打骨头');
console.log(dog instanceof Animal); //true
console.log(dog instanceof Dog); //true
特点:
- 非常纯粹的继承关系,实例是子类的实例,也是父类的实例
- 父类新增原型方法/原型属性,子类都能访问到
- 简单,易于实现
缺点:
- 要想为子类新增属性和方法,必须要在
new Animal()这样的语句之后执行,不能放到构造器中 - 无法实现多继承
- 来自原型对象的所有属性被所有实例共享
- 创建子类实例时,无法向父类构造函数传参
方式二: 借用构造函数继承
function Dog() {
Animal.call(this);
this.name = name || '大黄狗';
}
var dog = new Dog();
console.log(dog.name);
dog.eat("大骨头");
console.log(dog instanceof Animal); // false
console.log(dog instanceof Dog); // true
特点:
- 解决了1中,子类实例共享父类引用属性的问题
- 创建子类实例时,可以向父类传递参数
- 可以实现多继承(call多个父类对象)
缺点:
- 实例并不是父类的实例,只是子类的实例
- 只能继承父类的实例属性和方法,不能继承原型属性/方法
- 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
方式三:ES6中class 的继承
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()
本文介绍了JavaScript中三种主要的继承实现方式:原型链继承、构造函数继承以及ES6的Class继承。每种方式的特点、优缺点都进行了详细阐述,包括如何实现属性和方法的继承,以及实例化过程中的特性。对于理解JavaScript的继承机制提供了深入的洞察。

被折叠的 条评论
为什么被折叠?



