JavaScript基于原型链的继承


Posted in Javascript onJune 22, 2016

Javascript并不是一门面向对象的语言,没有提供传统的继承方式,但是它提供了一种原型继承的方式,利用自身提供的原型属性来实现继承。

原型链是JavaScript中继承的主要方法。

原型链的基本思想是:利用原型让一个引用类型继承另一个引用类型的属性和方法。

构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。

如果让原型对象等于另一个对象的实例,这样原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。

实现原型链的基本模式:

function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function () {
return this.property;
};
function SubType() {
this.subproperty = false;
}
// 继承SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function () {
return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue()); // true

SubType继承了SuperType,继承是通过创建SuperType的实例,并将该实例赋给SubType.prototype实现的。实现的本质是重写原型对象,换成一个新类型的实例。这样,原来存在于SuperType的实例中的属性和方法,也存在与SubType.prototype中了。然后给SubType.prototype添加一个方法,这样就继承了SuperType的属性和方法的基础上又添加了一个方法。

上例中的实例关系表示如下:

JavaScript基于原型链的继承

上面没有使用SubType默认提供的原型,而是给它换了一个新原型;这个新原型就是SuperType的实例。新原型内部还有一个执行SuperType的原型的指针。结果变成了instance指向SubType的原型,SubType的原型又指向SuperType的原型。getValue()方法仍然还在SuperType.prototype中,但prototype则位于SubType.prototype中。这是因为property是一个实例属性,而getSuperValue()则是一个原型方法。既然SubType.prototype现在是SuperType的实例,那么property自然位于该实例中。

注意:instance.constructor现在指向的是SuperType,因为SubType的原型指向了另一个对象——SuperType的原型,这个原型对象的constructor属性指向的是SuperType。

当以读取模式访问一个属性时,首先会在实例中搜索该属性。如果没有找到该属性。则会继续搜索实例的原型。通过原型链实现继承的情况下,搜索过程就得以沿着原型链继续向上。

默认的原型

所有引用类型都默认继承了Object,而这个继承也是通过原型链实现的。所有函数的默认原型都是Object的实例。因此默认原型都会包含一个内部指针,指向Object.prototype。这就是为什么自定义类型都会继承toString()、valueOf()等方法的原因。

完整的原型链:

JavaScript基于原型链的继承

在上面的继承体系中,SubType继承了SuperType,SuperType继承了Object。当调用了instance.toString()时,实际调用的是保存在Object.prototype中的那个方法。

确定实例和原型的关系

可以通过两种方式来确定原型和实例之间的关系:

使用instanceof操作符

alert(instance instanceof Object);
alert(instance instanceof SuperType);
alert(instance instanceof SubType);

由于原型链的关系,上面全部返回true。

使用isPrototypeOf()方法

alert(Object.prototype.isPrototypeOf(instance));
alert(SuperType.prototype.isPrototypeOf(instance));
alert(SubType.prototype.isPrototypeOf(instance));

谨慎定义方法

给原型添加方法的代码一定要放在替换原型的语句之后。

function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function () {
return this.property;
};
function SubType() {
this.subproperty = false;
}
SuperType.prototype = new SuperType();
// 添加方法
SubType.prototype.getSubValue = function () {
return this.subproperty;
};
// 覆盖超类中的方法
SubType.prototype.getSuperValue = function () {
return false;
};
var instance = new SubType();
alert(instance.getSuperValue()); // false

上面的例子必须注意的是,在用SuperType的实例替换原型之后,再定义那两个方法。

另外,在通过原型链实现继承时,不能使用该对象字面量创建原型方法。因为这样做会重写原型链:

function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function () {
return this.property;
};
function SubType() {
this.subproperty = false;
}
// 继承SuperType
SubType.prototype = new SuperType();
// 使用字面量添加新方法,导致上一行代码无效
SubType.prototype = {
getSubValue :function() {
return this.subproperty;
},
someOtherMethod: function () {
return false;
}
};
var instance = new SubType();
alert(instance.getSuperValue()); // error

上例将SuperType的实例赋值给原型,紧接着又将原型替换成一个对象字面量而导致的问题。现在的原型包含一个Object的实例,而非SuperType的实例,SubType和SuperType之间已经没有关系了。

原型链的问题

前面已经介绍过,包含引用类型值得原型属性会被所有实例共享;而这也正是为什么要在构造函数中,而不是在原型对象中定义属性的原因。

function SuperType() {
this.colors = ["red", "blue", "green"];
}
function SubType() {
}
SubType.prototype = new SuperType();
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); // "red", "blue", "green", "black"
var instance2 = new SubType();
alert(instance2.colors); // "red", "blue", "green", "black"

在上面的例子中,SuperType构造函数中定义了一个colors属性,该属性包含一个数组,SuperType的每个实例都会有各自包含自己数组的colors属性。当SubType通过原型链继承了SuperType之后,SubType.prototype就变成了SuperType的一个实例,所以它也拥有了一个它自己的colors属性。但是,SubType的所有实例都会共享这一个colors属性。

另一问题是,没有办法在不影响所有对象实例的情况下,给超类的构造函数传递参数。

以上所述是小编给大家介绍的JavaScript基于原型链的继承 的相关知识,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
你可能不再需要JQUERY
Mar 09 Javascript
火狐下input焦点无法重复获取问题的解决方法
Jun 16 Javascript
浅谈window对象的scrollBy()方法
Jul 15 Javascript
jquery实现的蓝色二级导航条效果代码
Aug 24 Javascript
AngularJS 中文API参考手册
Jul 28 Javascript
Spring shiro + bootstrap + jquery.validate 实现登录、注册功能
Jun 02 jQuery
js导出Excel表格超出26位英文字符的解决方法ES6
Nov 15 Javascript
基于jquery的on和click的区别详解
Jan 15 jQuery
vue富文本框(插入文本、图片、视频)的使用及问题小结
Aug 17 Javascript
微信小程序实现点击按钮后修改颜色
Dec 05 Javascript
JavaScript面试中常考的字符串操作方法大全(包含ES6)
May 10 Javascript
如何在vue 中引入使用jquery
Nov 10 jQuery
jQuery和hwSlider实现内容响应式可触控滑动切换效果附源码下载(二)
Jun 22 #Javascript
基于jQuery和hwSlider实现内容左右滑动切换效果附源码下载(一)
Jun 22 #Javascript
浅析jQuery Ajax通用js封装
Jun 22 #Javascript
Javascript如何判断数据类型和数组类型
Jun 22 #Javascript
最全的Javascript编码规范(推荐)
Jun 22 #Javascript
Javascript将数值转换为金额格式(分隔千分位和自动增加小数点)
Jun 22 #Javascript
Javascript将数字转化成为货币格式字符串
Jun 22 #Javascript
You might like
《雄兵连》系列首部大电影《烈阳天道》:可能是因为期望值太高了
2020/08/18 国漫
PHP 日,周,月点击排行统计
2012/01/11 PHP
ThinkPHP实现一键清除缓存方法
2014/06/26 PHP
js中scrollHeight,scrollWidth,scrollLeft,scrolltop等差别介绍
2012/05/16 Javascript
js实现三张图(文)片一起切换的banner焦点图
2015/08/25 Javascript
轻松实现JavaScript图片切换
2016/01/12 Javascript
jQuery内存泄露解决办法
2016/12/13 Javascript
jQuery+HTML5实现WebGL高性能烟花绽放动画效果【附demo源码下载】
2017/08/18 jQuery
基于vue组件实现猜数字游戏
2020/05/28 Javascript
vue-router实现组件间的跳转(参数传递)
2017/11/07 Javascript
浅谈webpack对样式的处理
2018/01/05 Javascript
Vue实现内部组件轮播切换效果的示例代码
2018/04/07 Javascript
微信小程序首页的分类功能和搜索功能的实现思路及代码详解
2018/09/11 Javascript
微信公众平台获取access_token的方法步骤
2019/03/29 Javascript
Net微信网页开发 使用微信JS-SDK获取当前地理位置过程详解
2019/08/26 Javascript
element跨分页操作选择详解
2020/06/29 Javascript
浅谈Ant Design Pro 菜单自定义 icon
2020/11/17 Javascript
[01:52]PWL S2开团时刻第四期——DOTA2成语故事
2020/12/03 DOTA
使用Python的内建模块collections的教程
2015/04/28 Python
python中使用正则表达式的连接符示例代码
2017/10/10 Python
为何人工智能(AI)首选Python?读完这篇文章你就知道了(推荐)
2019/04/06 Python
Pytho爬虫中Requests设置请求头Headers的方法
2020/09/22 Python
基于CSS3的CSS 多栏(Multi-column)实现瀑布流源码分享
2014/06/11 HTML / CSS
马来西亚网上购物平台:ezbuy
2018/02/13 全球购物
英国马匹装备和马术用品购物网站:Equine Superstore
2019/03/03 全球购物
Python面试题:如何用Python来发送邮件
2016/03/15 面试题
捐资助学倡议书
2014/04/15 职场文书
县级文明单位申报材料
2014/05/23 职场文书
幼儿园爱国卫生月活动总结
2014/06/30 职场文书
小学生教师节演讲稿
2014/09/03 职场文书
党员应该树立反腐倡廉的坚定意识思想汇报
2014/09/12 职场文书
学校副校长四风对照检查材料整改措施
2014/09/25 职场文书
2015年全国爱耳日活动总结
2015/02/27 职场文书
标枪加油稿
2015/07/22 职场文书
《黄山奇石》教学反思
2016/02/18 职场文书
测量JavaScript函数的性能各种方式对比
2021/04/27 Javascript