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 相关文章推荐
类之Prototype.js学习
Jun 13 Javascript
解决jquery异步按一定的时间间隔刷新问题
Dec 10 Javascript
jquery 页眉单行信息滚动显示实现思路及代码
Jun 26 Javascript
很棒的Bootstrap选项卡切换效果
Jul 01 Javascript
Vue数据驱动模拟实现5
Jan 13 Javascript
JavaScript数据结构之二叉树的删除算法示例
Apr 13 Javascript
关于ES6箭头函数中的this问题
Feb 27 Javascript
vue路由懒加载的实现方法
Mar 12 Javascript
json字符串传到前台input的方法
Aug 06 Javascript
微信小程序基于canvas渐变实现的彩虹效果示例
May 03 Javascript
Node 模块原理与用法详解
May 13 Javascript
Node.js path模块,获取文件后缀名操作
Nov 07 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
建立动态的WML站点(二)
2006/10/09 PHP
php生成zip压缩文件的方法详解
2013/06/09 PHP
PHP实现阳历到农历转换的类实例
2015/03/07 PHP
Zend Framework教程之响应对象的封装Zend_Controller_Response实例详解
2016/03/07 PHP
Yii遍历行下每列数据的方法
2016/10/17 PHP
jQuery 跨域访问问题解决方法
2009/12/02 Javascript
js事件(Event)知识整理
2012/10/11 Javascript
JSON+JavaScript处理JSON的简单例子
2013/03/20 Javascript
javascript获取网页中指定节点的父节点、子节点的方法小结
2013/04/24 Javascript
jquery获取子节点和父节点的示例代码
2013/09/10 Javascript
jquery事件重复绑定的快速解决方法
2014/01/03 Javascript
JavaScript中的Math.LN2属性用法详解
2015/06/12 Javascript
浅谈JavaScript中的作用域和闭包问题
2015/07/07 Javascript
原生JavaScript编写canvas版的连连看游戏
2016/05/29 Javascript
微信小程序 缓存(本地缓存、异步缓存、同步缓存)详解
2017/01/17 Javascript
浅谈原生JS实现jQuery的animate()动画示例
2017/03/08 Javascript
NodeJS实现视频转码的示例代码
2017/11/18 NodeJs
js实现秒表计时器
2019/12/16 Javascript
vue实现树状表格效果
2020/12/29 Vue.js
python中合并两个文本文件并按照姓名首字母排序的例子
2014/04/25 Python
Python中让MySQL查询结果返回字典类型的方法
2014/08/22 Python
python3音乐播放器简单实现代码
2020/04/20 Python
Python多进程方式抓取基金网站内容的方法分析
2019/06/03 Python
解决Python3用PIL的ImageFont输出中文乱码的问题
2019/08/22 Python
Python有参函数使用代码实例
2020/01/06 Python
一文彻底解决HTML5页面中长按保存图片功能
2019/06/10 HTML / CSS
LUISAVIAROMA德国官网:时尚奢侈品牌购物网站
2020/11/12 全球购物
客服主管岗位职责
2013/12/13 职场文书
财务工作者先进事迹材料
2014/01/17 职场文书
学习十八届三中全会精神实施方案
2014/02/17 职场文书
参观接待方案
2014/03/17 职场文书
爱心捐助倡议书
2014/05/19 职场文书
实习介绍信模板
2015/01/30 职场文书
在Java中Collection的一些常用方法总结
2021/06/13 Java/Android
《Estab Life》4月6日播出 正式PV、主视觉图公开
2022/03/20 日漫
「玫瑰之王的葬礼」舞台剧主视觉图公开
2022/03/21 日漫