欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【前端面试】JS中通过原型链和class语法分别实现类的继承

程序员文章站 2022-06-09 21:38:39
...

【前端面试】JS中通过原型链和class语法分别实现类的继承


JS中的 本质上是一个 function类型的对象,这是JS的独特之处。

原型链实现继承

在ES6的class语法推出之前,要实现类的继承要通过修改原型链来实现:

  • 首先定义一个父类,本质上是定义父类的构造函数,其对应的Person.prototype会自动被创建
function Person(name, age) {
	this.name = name
	this.age = age
}
Person.prototype.setName = function(name) {
	this.name = name
}
  • 然后定义一个子类,通过在子类中用call函数,以子类的身份调用父类的构造函数,实现继承父类的成员变量
function Student (name, age) {
	Person.call(this,name,age)
}

这样做还不够,因为父类的成员函数还没有被继承。可以通过将Studentprototype的原型链__proto__指向Personprototype,来实现这一功能。

Student.prototype = new Person //这里无需入参,参数默认是undefined就行,
// 反正成员变量已经在前一步通过call继承到子类型Student对象上了
// 如果需要调用Student的成员变量,也轮不到沿着原型链找到这个new Person头上

然后试一下功能

const s1 = new Student('Bob', 23)
s1.setName('Tom')
console.log(s1)

【前端面试】JS中通过原型链和class语法分别实现类的继承
看起来大功告成!
但是…还有一个细节没有处理,那就是:Student.prototype.constructor此刻还指向Person,而正确的情况是:它应该指向Student本身,因此应该:

Student.prototype.constructor = Student

一个细节

Student.prototype = new Person这一步中,我提到了可以不带参数,因为Student对象本身就有nameage属性,只不过是undefined,因此不会沿着原型链找到new Person上。这里做个简单的测试。

Student.prototype = new Person('Jerry', 100) //改变Student原型链的时候带入参
const student1 = new Student  //新建student实例的时候不带入参
console.log(student1.name)  //undefined 而不是 Jerry

ES6 class 语法实现继承

要实现和上面的代码一样的逻辑,我们应该这么做:

  • 先定义父类Person
class Person {
	constructor(name, age) {
		this.name = name
		this.age = age
	}
	setName(newName) {
		this.name = newName
	}
}

然后定义子类Student,继承父类Person

class Student extends Person{
	constructor(name, age){
		super(name, age)
	}
}

测试一下:

const student1 = new Student('Tom', 24)
student1.setName('Jerry')

结果如下:
【前端面试】JS中通过原型链和class语法分别实现类的继承
检查继承关系:
【前端面试】JS中通过原型链和class语法分别实现类的继承