前端学习笔记

浅谈 JS 中继承的写法

2019-10-10  本文已影响0人  _ClariS_
JS中的几种流派

继承是属于面向对象流派

什么是类

定义:能产生对象的东西即为“类”

举个例子

这里的 Human 就是一个类

什么是继承

定义:继承就是描述类和类之间的关系,它可以使得子类别具有父类别的各种属性和方法

上面的例子中,Human的部分属性继承自Object,这是所有对象都存在的一个自带的继承关系。而Man继承自Human,这是我们自己实现的一个继承关系。

image.png

这里要特别注意实例属性与继承的区别

实例属性与继承的区别

从上图中可以看出,继承的实质就是进行两次的原型搜索

另外,只有构造函数有prototype属性,prototype属性只有一个功能就是存放共有属性对象
的地址

继承

ES5实现继承的写法

如何实现下图中的继承关系

image.png image.png

这两句代码就实现了上图中的继承关系。但是__proto__不是一个标准属性,因此不能直接写 Man.prototype.__proto__ = Human.prototype,我们可以通过 new 来间接操作__proto__

new内部做的几件事

但是 Human 中有this.name = name

 function Human(name){
     this.name = name
 }

直接写为Man.prototype = new Human()的话,由于 new 内的第④个步骤,会执行Human.call(),会出现我们不需要的结果。

你说把this.name = name删掉就可以了呀,但这样又会破坏原本的父类Human中的结构,于是我们就陷入了想删又不能删的境地。

解决方法:

我们可以用下面三句代码来代替

 var f = function(){} // 声明一个空函数f
 f.prototype = Human.prototype // 让这个空函数f的原型指向Human的原型
 Man.prototype = new f() // Man.prototype.__proto__ = f.prototype

这三句代码的作用就是让 Man.prototype.__proto = Human.prototype,且解决了上面的问题

于是,最终完整版代码如下

 function Human(name){
     this.name = name
 }
 Human.prototype.run = function(){
     console.log("我叫"+this.name+",我在跑")
     return undefined
 }
 function Man(name){
// 这里的this指向Man实例,将Man实例和name作为参数传入构造函数Human中
     Human.call(this, name) 
     this.gender = '男'
 }

/*Man.prototype.__proto__ = Human.prototype*/
 var f = function(){}
 f.prototype = Human.prototype
 Man.prototype = new f()

 Man.prototype.fight = function(){
     console.log('糊你熊脸')
 }

ES6实现继承的写法

对比ES5的写法,ES6的写法就很容易理解了

 class Human{ 
     constructor(name){ // 自身属性写到constructor中
         this.name = name
     }
     run(){ // 原型上的属性就直接写在Human这个类中
         console.log("我叫"+this.name+",我在跑")
         return undefined
     }
 }
// Man extends Human 等价于 Man.prototype.__proto = Human.prototype,也相当于上面的三句代码
 class Man extends Human{ 
     constructor(name){ 
         super(name) // 相当于Human.call(this, name) 
         this.gender = '男'
     }
     fight(){
         console.log('糊你熊脸')
     }
 }

那如果想在原型上声明一个非函数如何做到呢?

ES5的写法:

 function Human(name){
     this.name = name
 }
 Human.prototype.种族 = '人类'
 Human.prototype.run = function(){
     console.log("我叫"+this.name+",我在跑")
     return undefined
 }

ES6的写法:

 class Human{ 
     constructor(name){ // 自身属性写到constructor中
         this.name = name
     }
     get 种族(){
         return '人类'
     }
     run(){ // 原型上的属性就直接写在这个类中
         console.log("我叫"+this.name+",我在跑")
         return undefined
     }
 }
上一篇下一篇

猜你喜欢

热点阅读