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 相关文章推荐
动态刷新 dorado树的js代码
Jun 12 Javascript
基于jquery的tab切换 js原理
Apr 01 Javascript
C#中TrimStart,TrimEnd,Trim在javascript上的实现
Jan 17 Javascript
EXTJS记事本 当CompositeField遇上RowEditor
Jul 31 Javascript
JS 实现Json查询的方法实例
Apr 12 Javascript
jQuery实现DIV层淡入淡出拖动特效的方法
Feb 13 Javascript
Bootstrap风格的WPF样式
Dec 07 Javascript
ES6中Iterator与for..of..遍历用法分析
Mar 31 Javascript
小程序云开发初探(小结)
Oct 24 Javascript
20个必会的JavaScript面试题(小结)
Jul 02 Javascript
微信小程序 wxParse插件显示视频问题
Sep 27 Javascript
Vue简单封装axios之解决post请求后端接收不到参数问题
Feb 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
PHP session常见问题集锦及解决办法总结
2007/03/18 PHP
yum命令安装php7和相关扩展
2016/07/04 PHP
php正则判断是否为合法身份证号的方法
2017/03/16 PHP
jquery $.ajax()取xml数据的小问题解决方法
2010/11/20 Javascript
整理一些JavaScript的IE和火狐的兼容性注意事项
2011/03/17 Javascript
js toFixed()方法的重写实现精度的统一
2014/03/06 Javascript
JQuery 实现在同一页面锚点链接之间的平滑滚动
2014/10/29 Javascript
Javascript基础教程之while语句
2015/01/18 Javascript
理解JavaScript的变量的入门教程
2015/07/07 Javascript
jquery判断复选框是否被选中的方法
2015/10/16 Javascript
Nodejs 复制文件/文件夹的方法
2017/08/24 NodeJs
Vue实现左右菜单联动实现代码
2018/08/12 Javascript
JavaScript实现简单的隐藏式侧边栏功能示例
2018/08/31 Javascript
使用vue-cli3新建一个项目并写好基本配置(推荐)
2019/04/24 Javascript
Javascript通过控制类名更改样式
2019/05/24 Javascript
微信小程序自定义弹窗实现详解(可通用)
2019/07/04 Javascript
vue-router的hooks用法详解
2020/06/08 Javascript
[02:08]DOTA2英雄基础教程 马格纳斯
2014/01/17 DOTA
[02:28]DOTA2 2017国际邀请赛小组赛回顾
2017/08/09 DOTA
[03:06]2018年度CS GO最具人气解说-完美盛典
2018/12/16 DOTA
Python正则表达式的使用范例详解
2014/08/08 Python
详解TensorFlow在windows上安装与简单示例
2018/03/05 Python
使用TensorFlow实现简单线性回归模型
2019/07/19 Python
Python Django Vue 项目创建过程详解
2019/07/29 Python
Python实现微信机器人的方法
2019/09/06 Python
vue学习笔记之动态组件和v-once指令简单示例
2020/02/29 Python
python中zip()函数遍历多个列表方法
2021/02/18 Python
Html5百叶窗效果的示例代码
2017/12/11 HTML / CSS
Foot Locker澳洲官网:美国运动服和鞋类零售商
2019/10/11 全球购物
广州御银科技股份有限公司试卷(C++)
2016/11/04 面试题
校长竞聘演讲稿
2014/05/16 职场文书
红色旅游心得体会
2014/09/03 职场文书
小学公民道德宣传日活动总结
2015/03/23 职场文书
房租涨价通知
2015/04/23 职场文书
推荐六本经典文学奖书籍:此生必读
2019/08/22 职场文书
解析探秘fescar分布式事务实现原理
2022/02/28 Java/Android