资讯专栏INFORMATION COLUMN

JS面向对象之五 【继承】

genefy / 586人阅读

摘要:首先为了模拟类创建对象的功能搞出了构造函数。也就是名字肤色肤色这里是继承里的自有属性生命值这里继承的共有属性的方法攻击力兵种美国大兵攻击防御死亡肤色

JS面向对象之五 【继承】

我们已经准备了很多前置知识,包括

原型链,对象和对象之间的关系

this,对象和函数之间的关系

new, 用函数批量创建特定的对象的语法糖

JS面向对象的前世今生

我们说,面向对象是一种写代码的套路。因为如果满足 封装、继承、多态就是面向对象的话,那JS天生就有这3个特点。

那我们JS搞的这个面向对象其实是模仿java的面向对象,因为网景公司在发明JavaScript时,希望依托java让自己的语言火起来,
为此必须吸引java开发者来使用,所以要模仿java搞出相当于class的东西出来。

好的,现在JS和Java已经诞生了。但是Java中的继承可以通过类实现,而JS中没有类,JS里的继承是通过原型链实现的。

至此,我们做的事情就是,让java里用类能做的事情,我们JS也必须想办法搞出来,而且尽可能的像java (就ES6里class的语法糖)

明确需求: 我们JS要实现的就是,java的类能做的事情,我们也要能做。
首先,JS为了模拟类创建对象的功能,搞出了构造函数。

构造函数就像class一样可以,创建特定的对象,但是java程序员认为你这构造函数,不是类

因为java的类可以这样写,也就是子类可以继承父类

class Human extend Animal

但是JS最初没有extend这样的语法糖,来实现子构造函数继承父构造函数

所以,JS没法用extend关键字来直接继承,于是苦思冥想出了其他方法来模拟子类继承父类

## 于是,我们学习JS是如何模拟子类继承父类的

JS里没有类,所以我们肯定看的是JS是如何让子构造函数继承父构造函数的

版本1: 让Soldier继承Human
      function Human(options) {
          this.名字 = options.name,
          this.肤色 = options.肤色
      }
      Human.prototype.eat = function () {}
      Human.prototype.drink = function () {}
  
  
      function Soldier(options) {
          Human.call(this,options)   // 为了得到human里的自有属性
          this.生命值 = 42
          this.ID = options.id
      }
      Soldier.prototype.__proto__ = Human.prototype    // 为了得到human里的公有属性
      Soldier.prototype.攻击力 = 5
      Soldier.prototype.兵种 = "美国大兵"
      Soldier.prototype.攻击 = function () {}
      Soldier.prototype.防御 = function () {}
      Soldier.prototype.死亡 = function () {}
  
      var soldier = new Soldier({name:"ziwei",肤色:"yellow",id:"8"})
      console.log(soldier);  
这个方案是OK的,问题在于__proto__不允许在生产环境使用,文档明确有要求的,影响性能
版本2 : 不用__proto__,让Soldier继承Human

其实这个思路是很对的,JS肯定要用__proto__才能继承。

现在的问题就是,我要用__proto__,但是JS不让我用。

所以JS开发者就十分拧巴的用new来用__proto__,怎么用呢,看下面代码:

Soldier.prototype.__proto__ = Human.prototype

改成

function Fn(){}

Fn.prototype = Human.prototype

Soldier.prototype = new Fn()

怎么解释呢?

因为 Soldier.prototype是Fn构造函数的实例,

所以 Soldier.prototype.__proto__ ==== Fn.prototype

而 Fn.prototype === Human.prototype

推论 Soldier.prototype.__proto__ === Human.prototype

完整的Soldier继承Human

      function Human(options) {
          this.名字 = options.name,
          this.肤色 = options.肤色
      }
      Human.prototype.eat = function () {}
      Human.prototype.drink = function () {}
  
  
      function Soldier(options) {
          Human.call(this,options)              //  这里是继承Human里的自有属性
          this.生命值 = 42
          this.ID = options.id
      }
      function Fn(){}
      Fn.prototype = Human.prototype
      Soldier.prototype = new Fn()                // 成功继承Human的共有属性 ,私有属性不要           
      
      Soldier.prototype.攻击力 = 5
      Soldier.prototype.兵种 = "美国大兵"
      Soldier.prototype.攻击 = function () {}
      Soldier.prototype.防御 = function () {}
      Soldier.prototype.死亡 = function () {}
  
      var soldier = new Soldier({name:"ziwei",肤色:"yellow",id:"8"})
      console.log(soldier);  

版本2.1: ES5提供Object.create()的语法糖,让开发者避免借助new,这种拧巴的方式来用__proto__
介绍Object.create()

接收一个参数obj1,return一个结果obj2

obj2会继承obj1的属性。也就是obj2.__proto__ = obj1

      function Human(options) {
          this.名字 = options.name,
          this.肤色 = options.肤色
      }
      Human.prototype.eat = function () {}
      Human.prototype.drink = function () {}
  
  
      function Soldier(options) {
          Human.call(this,options)              //  这里是继承Human里的自有属性
          this.生命值 = 42
          this.ID = options.id
      }
      
      Soldier.prototype = Object.create(Human.prototype)    // 这里继承 Human 的共有属性,ES5的方法
      
      Soldier.prototype.攻击力 = 5
      Soldier.prototype.兵种 = "美国大兵"
      Soldier.prototype.攻击 = function () {}
      Soldier.prototype.防御 = function () {}
      Soldier.prototype.死亡 = function () {}
  
      var soldier = new Soldier({name:"ziwei",肤色:"yellow",id:"8"})
      console.log(soldier);  

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/110104.html

相关文章

  • Angular4之五 服务器通讯

    摘要:可以与任何支持与服务器进行通讯。首先,我们使用用语言创建一个服务器。一创建服务器步骤创建一个空的项目,取名为,名字可以按照情况而取。中,处理异步代码通常有种方式回调承诺可观察对象使用命令行组件名实例组件名为。运行时发生错误,提示改为则正常。 Angular可以与任何支持http与websocket服务器进行通讯。 首先,我们使用node.js用typescript语言创建一个web服务...

    Taste 评论0 收藏0
  • 天坑,CSS之定位Position(六分之五

    摘要:下文称位置属性即为。注意,不会脱离文档流,具体见下面的图示。直译为修正,简单粗暴,直接相对浏览器窗口显示区域定位。 Position定位 个人觉得position这个属性真的算是CSS的见面杀了。尤其是absolute,当年可是被虐的不轻。当然了,现在爱上了这个属性,谁用谁知道。 position属性 position是CSS的一个属性,地位较高,也是我们重点要说的一个属性。 对应了四...

    SwordFly 评论0 收藏0
  • 天坑,CSS之定位Position(六分之五

    摘要:下文称位置属性即为。注意,不会脱离文档流,具体见下面的图示。直译为修正,简单粗暴,直接相对浏览器窗口显示区域定位。 Position定位 个人觉得position这个属性真的算是CSS的见面杀了。尤其是absolute,当年可是被虐的不轻。当然了,现在爱上了这个属性,谁用谁知道。 position属性 position是CSS的一个属性,地位较高,也是我们重点要说的一个属性。 对应了四...

    anRui 评论0 收藏0
  • 天坑,CSS之定位Position(六分之五

    摘要:下文称位置属性即为。注意,不会脱离文档流,具体见下面的图示。直译为修正,简单粗暴,直接相对浏览器窗口显示区域定位。 Position定位 个人觉得position这个属性真的算是CSS的见面杀了。尤其是absolute,当年可是被虐的不轻。当然了,现在爱上了这个属性,谁用谁知道。 position属性 position是CSS的一个属性,地位较高,也是我们重点要说的一个属性。 对应了四...

    xuweijian 评论0 收藏0
  • 【面试系列】之五:关于字符串以及数组的操作

    摘要:之五关于字符串以及数组的操作关于数组的操作先掌握一些基本的数组操作用于拼接多个数组,接受多个参数从数组尾部插入一个数,并返回新的数组长度从数组尾部删除一个数,并返回被删除的数从数组头部删除一个数,并返回被删除的数从数组头部插入一个数,并返回 之五:关于字符串以及数组的操作 关于数组的操作 先掌握一些基本的数组操作 concat // 用于拼接多个数组,接受多个参数 push /...

    waterc 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<