JavaScript进阶之路:继承
1. 什么是继承
想到继承,我会想到父子、子承父业之类的词,就是孩子得到父母的所有财产(一般情况下)。
如果从程序的角度解释,那首先说一下 Class 这个关键字,在一些其他的预言中像:Java、C# 等通过类(Class)实现继承(对于这块我多少还是了解的,因为大学学的是Java),这是一种面向对象的思想。然而 JS 中没有类,但是我们可以使用 Js 来模拟面向对象的编程思想通过构造函数模拟类的概念。
2. 通过原型实现继承
// 这里我叫做公共父类
function Person (name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 这里我叫做子类,去继承Person
Person.prototype.sayHi = function () {
console.log('你好呀!朋友')
}
function Student (score) {
this.score = score;
}
Student.prototype = new Person('ayong', 23, '男');
Student.prototype.totalScore = function () {
console.log(`这学期考试我得了:${ this.score }分`);
}
const stu = new Student(100);
console.log(stu.name); // ayong
console.log(stu.age); // 23
console.log(stu.sex); // 男
stu.sayHi(); // 你好呀!朋友
stu.totalScore(); // 这学期考试我得了:100分
⭐存在的不足:
- Student 的原型每次指向 Person 时,需要初始化。
- 当再次改变时,又需要初始化,始第一次初始化没有意义。
3. 借用构造函数实现继承
这里我们使用到了 call 方法指向 Person 的构造函数。
// 这里我叫做公共父类
function Person (name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 这里我叫做子类,去继承Person
Person.prototype.sayHi = function () {
console.log('你好呀!朋友')
}
function Student (name, age, sex, score) {
// 使用 call 方法
Person.call(this, name, age, sex);
this.score = score;
}
Student.prototype.totalScore = function () {
console.log(`这学期考试我得了:${ this.score }分`);
}
const stu = new Student('ayong',23, '男', 100);
console.log(stu.name); // ayong
console.log(stu.age); // 23
console.log(stu.sex); // 男
stu.totalScore(); // 这学期考试我得了:100分
// 这行代码报错了
stu.sayHi(); // Uncaught TypeError: stu.sayHi is not a function
⭐存在的不足:
- 清楚的看到,虽然我们可以正确的初始化对象,但是我们不能访问父类的方法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ox9IUF91-1633764605122)(C:\Users\H7113821\Desktop\學習篇\筆記\js继承\js_constructor.PNG)]
4. 原型链和构造函数组合使用(推荐)
// 这里我叫做公共父类
function Person (name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 这里我叫做子类,去继承Person
Person.prototype.sayHi = function () {
console.log('你好呀!朋友')
}
function Student (name, age, sex, score) {
Person.call(this, name, age, sex);
this.score = score;
}
// 不用进行传参
Student.prototype = new Person();
Student.prototype.totalScore = function () {
console.log(`这学期考试我得了:${ this.score }分`);
}
const stu = new Student('ayong',23, '男', 100);
console.log(stu.name); // ayong
console.log(stu.age); // 23
console.log(stu.sex); // 男
stu.totalScore(); // 这学期考试我得了:100分
stu.sayHi(); // 你好呀!朋友
5. 通过拷贝实现继承
// 这里我叫做公共父类
function Person (name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 这里我叫做子类,去继承Person
Person.prototype.sayHi = function () {
console.log('你好呀!朋友')
}
function Student (name, age, sex, score) {
Person.call(this, name, age, sex);
this.score = score;
}
// 应为 prototype 也是一个对象,所以我们深拷贝一下
for (const key in Person.prototype) {
if (Person.prototype.hasOwnProperty(key)) {
Student.prototype[key] = Person.prototype[key];
}
}
Student.prototype.totalScore = function () {
console.log(`这学期考试我得了:${ this.score }分`);
}
const stu = new Student('ayong',23, '男', 100);
console.log(stu.name);
console.log(stu.age);
console.log(stu.sex);
stu.totalScore();
stu.sayHi();
☀️如果对于深浅拷贝不太熟悉的话:参考之前的博客js必会技能:深浅拷贝
6. ES6 中 Class 实现继承
类似于 Java 中的 Class ,使用 extends 关键字继承父类,基本使用差不多,但是终归还是一个函数,不像 Java 中类的概念。
// 这是一个公共的父类
class Person {
// 构造函数
constructor(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
}
// Person 类中的方法
sayHi () {
console.log('你好呀!朋友')
}
}
// 子类,通过 extends 继承 Person 类
class Student extends Person {
constructor(name, age, sex, score){
// 写在 constructor 中的第一句。
super(name, age, sex);
this.score = score;
}
// Student 类中的方法
totalScore () {
console.log(`这学期考试我得了:${ this.score }分`);
}
}
const stu = new Student('ayong',23, '男', 100);
console.log(stu.name); // ayong
console.log(stu.age); // 23
console.log(stu.sex); // 男
stu.totalScore(); // 这学期考试我得了:100分
stu.sayHi(); // 你好呀!朋友
总结
在学习继承之前,我认为了解原型链还是有必要的。因为我们能够很清楚的知道每个类之间的关系(这里我就统称为类了)。可能是之前接触过 Java 的原因让我对继承似乎不那么的陌生,ES6 出了 Class 之后,就感觉是在写 Java 一样,像我在学习 TS 的时候接触到的 implements、interface,都让我感到很亲切。
最后祝大家前程似锦。🎉🎉🎉