博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS中的继承
阅读量:6580 次
发布时间:2019-06-24

本文共 2318 字,大约阅读时间需要 7 分钟。

前记

在维基百科中继承的含义是使子类别具有父类别的属性和方法,或者说子类构造的对象直接拥有父类对象的属性。

但是在JavaScript中并没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instance)的区分,JavaScript的继承是靠prototype(原型链)来实现的。

prototype继承实现

我曾写过一篇名为原型和原型链的文章,那时候说明了原型和原型链是什么,那继承只要在它的原型链中添加公有属性就可以了

假如我们写一个构造函数Human

function Human(name){  this.name = name//构造函数可以生成新对象,this就是这个新对象}

然后在Human的原型链上添加函数run

Human.prototype.run = function (){  console.log(this.name + '在跑')  return undefined}

这样当我们用Human构造一个对象时候

let a = new Human('lgm')//Human {name: "lgm"}//  name: "lgm"///  __proto__://    run: ƒ ()//    constructor: ƒ Human(name)//     __proto__: Object

现在我们再写一个构造函数Man

function Man(name){  this.name = name//this新生成的对象  this.gender: '男'//this新生成的对象}

然后在Man的原型链上添加函数fight

Man.prototype.fight = function (){  console.log(this.name + '会打架')}

这样用Man构造一个对象就是

let b = new Man('lgm')//Man {name: "lgm"}//  name: "lgm"///  gender: '男'//  __proto__://    fight: ƒ ()//    constructor: ƒ Man(name)//      __proto__: Object

当我们想要Man继承Human的属性的时候,就可以知道,只要

Man.prototype.__proto__ = Human.prototype

修改Man

function Man(name){  Human.call(this, name)  this.gender: '男'//this新生成的对象}

就可以完成继承了,让我们来试一下

再次构造一个Man对象

let lgm = new Man('lgm')//Man {name: "lgm", gender: "男"}//  gender: "男"//  name: "lgm"///  __proto__: Human//    fight: ƒ ()//    constructor: ƒ Man(name)//    __proto__://      run: ƒ ()//      constructor: ƒ Human(name)//      __proto__: Object

由此我们可以看到,Man继承了Human中的run()函数,但是有一个问题

直接操作__proto__是不属于ECMA规范的,在IE中直接操作并不可行,我们需要换一种写法

var f = function(){}f.prototype = Human.prototypeMan.prototype = new f()

这样是使用了new的特性,让我们来试一下,然后再次构造一个Man对象

let lgm = new Man('lgm')//Man {name: "lgm", gender: "男"}//  gender: "男"//  name: "lgm"///  __proto__: Human//    fight: ƒ ()//    __proto__://      run: ƒ ()//      constructor: ƒ Human(name)//      __proto__: Object

可以看到,效果是一样的

class语法糖

在ES6语法中,新增了一个叫做class的语法,专门用来实现继承,上面代码通过class改写如下

class Human {  constructor(name) {    this.name = name  }  run() {    console.log("我叫" + this.name + ",我在跑")    return undefined  }}class Man extends Human {//Man.prototype.__proto__ = Human.prototype  constructor(name) {    super(name)//Human.call(this, name)    this.gender = '男'  }  fight() {    console.log(this.name + '会打架')  }}

两种方法的优劣

prototype继承写法麻烦,但是简单易懂,而class继承的写法虽然简单,但难以理解

并且,原型链继承添加继承属性的话会会非常简单,只需

Human.prototype.headNumber = '1'

而class继承如果需要添加继承属性会非常麻烦

转载地址:http://eiino.baihongyu.com/

你可能感兴趣的文章
IOS 7 Study - UISegmentedControl
查看>>
八、通用类型系统
查看>>
JQuery的ajaxFileUpload的使用
查看>>
关于Integer类中parseInt()和valueOf()方法的区别以及int和String类性的转换.以及String类valueOf()方法...
查看>>
ios 控制器的生命周期
查看>>
JavaScript 特殊效果代码
查看>>
【?】codeforces721E Road to Home(DP+单调队列)
查看>>
MySQL 仅保留7天、一个月数据
查看>>
Diff Two Arrays
查看>>
下拉菜单
查看>>
[清华集训2014]玛里苟斯
查看>>
【MVC+EasyUI实例】对数据网格的增删改查(上)
查看>>
Project Euler 345: Matrix Sum
查看>>
你可能不知道的技术细节:存储过程参数传递的影响
查看>>
.htaccess 基础教程(四)Apache RewriteCond 规则参数
查看>>
UVM中的class--2
查看>>
ORACLE 存储过程异常捕获并抛出
查看>>
root用户重置其他密码
查看>>
Oracle推断值为非数字
查看>>
多年前写的一个ASP.NET网站管理系统,到现在有些公司在用
查看>>