JavaScript原型继承_动力节点Java学院整理


Posted in Javascript onJune 30, 2017

在传统的基于Class的语言如Java、C++中,继承的本质是扩展一个已有的Class,并生成新的Subclass。
由于这类语言严格区分类和实例,继承实际上是类型的扩展。但是,JavaScript由于采用原型继承,我们无法直接扩展一个Class,因为根本不存在Class这种类型。

但是办法还是有的。我们先回顾Student构造函数:

function Student(props) {
  this.name = props.name || 'Unnamed';
}

Student.prototype.hello = function () {
  alert('Hello, ' + this.name + '!');
}

以及Student的原型链:

JavaScript原型继承_动力节点Java学院整理

现在,我们要基于Student扩展出PrimaryStudent,可以先定义出PrimaryStudent

function PrimaryStudent(props) {
  // 调用Student构造函数,绑定this变量:
  Student.call(this, props);
  this.grade = props.grade || 1;
}

但是,调用了Student构造函数不等于继承了StudentPrimaryStudent创建的对象的原型是:

new PrimaryStudent() ----> PrimaryStudent.prototype ----> Object.prototype ----> null

必须想办法把原型链修改为:

new PrimaryStudent() ----> PrimaryStudent.prototype ----> Student.prototype ----> Object.prototype ----> null

这样,原型链对了,继承关系就对了。新的基于PrimaryStudent创建的对象不但能调用PrimaryStudent.prototype定义的方法,也可以调用Student.prototype定义的方法。
如果你想用最简单粗暴的方法这么干:
PrimaryStudent.prototype = Student.prototype;

是不行的!如果这样的话,PrimaryStudentStudent共享一个原型对象,那还要定义PrimaryStudent干啥?

我们必须借助一个中间对象来实现正确的原型链,这个中间对象的原型要指向Student.prototype。为了实现这一点,参考道爷(就是发明JSON的那个道格拉斯)的代码,中间对象可以用一个空函数F来实现:

// PrimaryStudent构造函数:
function PrimaryStudent(props) {
  Student.call(this, props);
  this.grade = props.grade || 1;
}

// 空函数F:
function F() {
}

// 把F的原型指向Student.prototype:
F.prototype = Student.prototype;

// 把PrimaryStudent的原型指向一个新的F对象,F对象的原型正好指向Student.prototype:
PrimaryStudent.prototype = new F();

// 把PrimaryStudent原型的构造函数修复为PrimaryStudent:
PrimaryStudent.prototype.constructor = PrimaryStudent;

// 继续在PrimaryStudent原型(就是new F()对象)上定义方法:
PrimaryStudent.prototype.getGrade = function () {
  return this.grade;
};

// 创建xiaoming:
var xiaoming = new PrimaryStudent({
  name: '小明',
  grade: 2
});
xiaoming.name; // '小明'
xiaoming.grade; // 2

// 验证原型:
xiaoming.__proto__ === PrimaryStudent.prototype; // true
xiaoming.__proto__.__proto__ === Student.prototype; // true

// 验证继承关系:
xiaoming instanceof PrimaryStudent; // true
xiaoming instanceof Student; // true

用一张图来表示新的原型链:

JavaScript原型继承_动力节点Java学院整理

注意,函数F仅用于桥接,我们仅创建了一个new F()实例,而且,没有改变原有的Student定义的原型链。
如果把继承这个动作用一个inherits()函数封装起来,还可以隐藏F的定义,并简化代码:

function inherits(Child, Parent) {
  var F = function () {};
  F.prototype = Parent.prototype;
  Child.prototype = new F();
  Child.prototype.constructor = Child;
}
这个inherits()函数可以复用:
function Student(props) {
  this.name = props.name || 'Unnamed';
}

Student.prototype.hello = function () {
  alert('Hello, ' + this.name + '!');
}

function PrimaryStudent(props) {
  Student.call(this, props);
  this.grade = props.grade || 1;
}

// 实现原型继承链:
inherits(PrimaryStudent, Student);

// 绑定其他方法到PrimaryStudent原型:
PrimaryStudent.prototype.getGrade = function () {
  return this.grade;
};

小结

JavaScript的原型继承实现方式就是:

1.定义新的构造函数,并在内部用call()调用希望“继承”的构造函数,并绑定this;
2.借助中间函数F实现原型链继承,最好通过封装的inherits函数完成;
3.继续在新的构造函数的原型上定义新方法。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
ExtJS PropertyGrid中使用Combobox选择值问题
Jun 13 Javascript
情人节专属 纯js脚本1k大小的3D玫瑰效果
Feb 11 Javascript
jQuery实现带动画效果的多级下拉菜单代码
Sep 08 Javascript
三种Node.js写文件的方式
Mar 08 Javascript
JS表格组件BootstrapTable行内编辑解决方案x-editable
Sep 01 Javascript
BootStrap实现带有增删改查功能的表格(DEMO详解)
Oct 26 Javascript
微信小程序 欢迎界面开发的实例详解
Nov 30 Javascript
Angularjs中使用轮播图指令swiper
May 30 Javascript
让你彻底掌握es6 Promise的八段代码
Jul 26 Javascript
扫微信小程序码实现网站登陆实现解析
Aug 20 Javascript
24行JavaScript代码实现Redux的方法实例
Nov 17 Javascript
基于JavaScript实现贪吃蛇游戏
Mar 16 Javascript
JavaScript之排序函数_动力节点Java学院整理
Jun 30 #Javascript
JavaScript操作文件_动力节点Java学院整理
Jun 30 #Javascript
JavaScript之生成器_动力节点Java学院整理
Jun 30 #Javascript
详解vue组件通信的三种方式
Jun 30 #Javascript
JavaScript实现瀑布流图片效果
Jun 30 #Javascript
十大 Node.js 的 Web 框架(快速提升工作效率)
Jun 30 #Javascript
vue.js移动端tab组件的封装实践实例
Jun 30 #Javascript
You might like
DOTA2 玩家自创拉野攻略 特色英雄快速成长篇
2020/04/20 DOTA
用php实现让页面只能被百度gogole蜘蛛访问的方法
2009/12/29 PHP
php使用curl和正则表达式抓取网页数据示例
2014/04/13 PHP
thinkphp中ajax与php响应过程详解
2014/12/08 PHP
php图片添加文字水印实现代码
2016/03/15 PHP
PHP实现的策略模式示例
2019/03/20 PHP
在html页面中包含共享页面的方法
2008/10/24 Javascript
锋利的jQuery 要点归纳(三) jQuery中的事件和动画(上:事件篇)
2010/03/24 Javascript
apycom出品的jQuery精美菜单破解方法
2011/02/18 Javascript
Extjs优化(一)删除冗余代码提高运行速度
2013/04/15 Javascript
jquery复选框checkbox实现删除前判断
2014/04/20 Javascript
js实现兼容IE和FF的上下层的移动
2015/05/04 Javascript
基于javascript简单实现对身份证校验
2021/01/25 Javascript
NODE.JS跨域问题的完美解决方案
2016/10/20 Javascript
ES2015 Symbol 一种绝不重复的值
2016/12/25 Javascript
数组Array的排序sort方法
2017/02/17 Javascript
iscroll动态加载数据完美解决方法
2017/07/18 Javascript
Canvas放置反弹效果随机图形(实例)
2017/08/17 Javascript
vue构建动态表单的方法示例
2018/09/22 Javascript
JS 自执行函数原理及用法
2019/08/05 Javascript
Layui数据表格之单元格编辑方式
2019/10/26 Javascript
Node.js实现批量下载图片简单操作示例
2020/01/18 Javascript
python微信跳一跳系列之色块轮廓定位棋盘
2018/02/26 Python
Python使用pyshp库读取shapefile信息的方法
2018/12/29 Python
Python3 串口接收与发送16进制数据包的实例
2019/06/12 Python
OpenCV 边缘检测
2019/07/10 Python
pycharm创建scrapy项目教程及遇到的坑解析
2019/08/15 Python
Django Form and ModelForm的区别与使用
2019/12/06 Python
jupyter 使用Pillow包显示图像时inline显示方式
2020/04/24 Python
一款利用纯css3实现的win8加载动画的实例分析
2014/12/11 HTML / CSS
新西兰第一的行李箱网站:luggage.co.nz
2019/07/22 全球购物
写求职信有哪些注意事项
2014/05/08 职场文书
保研推荐信范文
2015/03/25 职场文书
婚姻出轨保证书
2015/05/08 职场文书
2016同学毕业寄语大全
2015/12/04 职场文书
python 学习GCN图卷积神经网络
2022/05/11 Python