JavaScript面向对象—继承的实现

前言面向对象的三大特性:封装、继承和多态 。上一篇我们简单的了解了封装的过程,也就是把对象的属性和方法封装到一个函数中,这一篇讲一下JAVAScript中继承的实现,继承是面向对象中非常重要的特性,它可以帮助我们提高代码的复用性 。继承主要的思想就是将重复的代码逻辑抽取到分类中,子类只需要通过继承分类,就可以使用分类中的方法,但是在实现JavaScript继承之前,需要先了解一个重要的知识点“原型链” 。
1.JavaScript中的原型链

在上一篇JavaScript面向对象—对象的创建和操作中已经简单的了解过了JavaScript中对象的原型和函数的原型,当我们从一个对象上获取属性时,如果在当前对象自身没有找到该属性的话,就会去它原型上面获取,如果原型中也没有找到就会去它原型的原型上找,沿着这么一条线进行查找,那么这条线就是我们所说的原型链了 。
示例代码:
const obj = {name: 'curry',age: 30}obj.__proto__ = {}obj.__proto__.__proto__ = {}obj.__proto__.__proto__.__proto__ = { height: 1.83 }console.log(obj.height) // 1.83对应的内存中的查找过程:
JavaScript面向对象—继承的实现

文章插图
 
当通过原型链查找某个属性时,一直找不到的话会一直查找下去么?肯定是不会的,JavaScript的原型链也是有尽头的,这个尽头就是Object的原型 。
2.Object的原型
事实上,不管是对象还是函数,它们原型链的尽头都是Object的原型,也称之为顶层原型,我们可以打印看看这个顶层原型长什么样 。
(1)打印Object的原型
console.log(Object.prototype)
  • 在node环境中:

JavaScript面向对象—继承的实现

文章插图
 
  • 在浏览器中:

JavaScript面向对象—继承的实现

文章插图
 
(2)Object原型的特殊之处
  • 如果我们再次打印Object.prototype的原型,这个原型属性已经指向了null;
  • console.log(Object.prototype.__proto__) // null
  • 并且在Object.prototype上有很多默认的属性和方法,像toString、hasOwnProperty等;
(3)上一篇中讲到当使用new操作符调用构造函数时,其对象的[[prototype]]会指向该构造函数的原型prototype,其实Object也是一个构造函数,因为我们可以使用new操作符来调用它,创建一个空对象 。
  • 示例代码:
  • const obj = new Object() obj.name = 'curry' obj.age = 30 console.log(obj.__proto__ === Object.prototype) // true console.log(obj.__proto__) // [Object: null prototype] {} console.log(obj.__proto__.__proto__) // null
  • 内存表现:
  •  
(4)总结
  • 从Object的原型可以得出一个结论“原型链最顶层的原型对象就是Object的原型对象”,这也就是为什么所有的对象都可以调用toString方法了;
  • 从继承的角度来讲就是“Object是所有类的父类”;
3.JavaScript继承的实现方案3.1.方案一:通过原型链实现继承
如果需要实现继承,那么就可以利用原型链来实现了 。
  • 定义一个父类Person和子类Student;
  • 父类中存放公共的属性和方法供子类使用;
  • 核心:将父类的实例化对象赋值给子类的原型;
【JavaScript面向对象—继承的实现】// 定义Person父类公共的属性function Person() {this.name = 'curry'this.age = 30}// 定义Person父类的公共方法Person.prototype.say = function() {console.log('I am ' + this.name)}// 定义Student子类特有的属性function Student() {this.sno = 101111}// 实现继承的核心:将父类的实例化对象赋值给子类的原型Student.prototype = new Person()// 定义Student子类特有的方法Student.prototype.studying = function() {console.log(this.name + ' studying')}// 实例化Studentconst stu = new Student()console.log(stu.name) // curryconsole.log(stu.age) // 30console.log(stu.sno) // 101111stu.say() // I am currystu.studying() // curry studying内存表现:
JavaScript面向对象—继承的实现

文章插图
 
缺点: