每天做个总结吧,坚持就是胜利!
/**
@date 2021-07-10
@description JS的几种继承
*/
复制代码
壹(序)
JavaScript中的类并不像其他面向类语言中的类,JS中的类只是一种关联关系
,都是通过原型机制
去实现,今天总结几种继承方式
贰(继承)
- 原型链继承:将子的
prototype
属性改写为父类的实例对象,这样子类就能使用父类中的属性及方法,同时自己也能重写属性
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.getInfo = function () {
console.log(`i'm ${this.name}, ${this.age} years old`);
};
function Student(name, age, profession) {
this.name = name;
this.age = age;
this.profession = profession;
}
Student.prototype = new Person();
const student1 = new Student('E1e', 18, 'student');
const student2 = new Student('wy', 24, 'student');
student1.__proto__.getInfo = function () {
console.log(
`i'm ${this.name}, ${this.age} years old, i'm a ${this.profession}, hhh`
);
};
student1.getInfo(); // 'i'm E1e, 18 years old, i'm a student, hhh'
student2.getInfo(); 'i'm wy, 24 years old, i'm a student, hhh'
复制代码
但是,重写子类原型上的方法时,会导致所有子类实例方法都被覆盖
,并且比如上面的student1,自己有name,age属性,__proto__上也有
- 构造函数继承:借用构造函数实现继承,核心代码就是在子类
执行
父类构造函数,并改变this指向
function Person(name, age) {
this.name = name;
this.age = age;
this.getInfo = function () {
console.log(`i'm ${this.name}, ${this.age} years old`);
};
}
function Student(name, age) {
Person.call(this, name, age);
}
const student = new Student('E1e', 18);
student.getInfo(); // 'i'm E1e, 18 years old'
复制代码
这种继承方式很简单,就是在子类改变this并调用父类函数,这样子类就拥有父类上的属性及方法了,但是无法继承父类原型上的属性及方法,而且每个子类实例都要去调用父类函数,性能消耗严重
- 组合继承:将原型链继承与构造函数继承组合实现继承,用原型链实现父类原型上的继承,用构造函数实现父类自身的继承
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.getInfo = function () {
console.log(`i'm ${this.name}, ${this.age} years old`);
};
function Student(name, age, profession) {
Person.call(this, name, age, profession);
}
Student.prototype = new Person();
const student = new Student('E1e', 18, 'student');
student.getInfo();
复制代码
这样虽然继承了父类本身及原型上的属性及方法,但是也有之前两种继承方式的缺点
- 原型式继承:使用Object.create方法,将被继承对象指定为子对象的原型
const person = {
name: 'E1e',
age: 18
}
const anotherPerson = Object.create(person);
anotherPerson.name = 'wy';
anotherPerson.age = 24;
复制代码
通过Object.create
方法指定原型,实现原型式的继承,但是这样就无法传递参数,也容易因为修改原型上的属性方法等,而影响所有实例对象
- 寄生组合继承:与组合继承类似,只是在设置子类prototype属性时,使用Object.create方法处理
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.getInfo = function () {
console.log(`i'm ${this.name}, ${this.age} years old`);
};
function Student() {
Person.call(this, ...arguments);
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
const student = new Student('E1e', 18);
student.getInfo(); // 'i'm E1e, 18 years old'
复制代码
这就是基于ES5最终
实现的一种继承方式了,可以把之前的每一种方式写出来点开每一个子类及实例对象观察,会发现这种方式是看起来最好的
- 使用ES6的class,其实也是基于ES5的继承实现的,可以看作是一种语法糖,这里不做介绍,总结一下class与ES5继承的不同点
a. class声明的类与let/const声明的变量一样存在TDZ(暂时性死区)
b. class内部使用严格模式
c. class中的所有内部方法都是不可枚举的(包括静态方法与实例方法)
d. 使用class必须使用new
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END