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 相关文章推荐
编写跨浏览器的javascript代码必备[js多浏览器兼容写法]
Oct 29 Javascript
Javascript 判断Flash是否加载完成的代码
Apr 12 Javascript
js导出格式化的excel 实例方法
Jul 17 Javascript
javascript实例--教你实现扑克牌洗牌功能
May 15 Javascript
网站接入QQ登录的两种方法
Jul 22 Javascript
node.js中的http.createServer方法使用说明
Dec 14 Javascript
javascript巧用eval函数组装表单输入项为json对象的方法
Nov 25 Javascript
详解Javascript 中的 class、构造函数、工厂函数
Dec 20 Javascript
轻量级JS Cookie插件js-cookie的使用方法
Mar 22 Javascript
浅谈Vue.js之初始化el以及数据的绑定说明
Nov 14 Javascript
node.js使用zlib模块进行数据压缩和解压操作示例
Feb 12 Javascript
vue3如何优雅的实现移动端登录注册模块
Mar 29 Vue.js
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
几个php应用技巧
2008/03/27 PHP
保存到桌面、设为桌面且带图标的PHP代码
2013/11/19 PHP
PHP简单获取随机数的常用方法小结
2017/06/07 PHP
jQuery html()等方法介绍
2009/11/18 Javascript
Draggable Elements 元素拖拽功能实现代码
2011/03/30 Javascript
探讨javascript是不是面向对象的语言
2013/11/21 Javascript
通过url查找a元素并点击
2014/04/09 Javascript
关于JavaScript作用域你想知道的一切
2016/02/04 Javascript
JavaScript sort数组排序方法和自我实现排序方法小结
2016/06/06 Javascript
Javascript将字符串日期格式化为yyyy-mm-dd的方法
2016/10/27 Javascript
js实现悬浮窗效果(支持拖动)
2017/03/09 Javascript
bootstrap实现的自适应页面简单应用示例
2017/03/09 Javascript
关于vue.js组件数据流的问题
2017/07/26 Javascript
基于node.js之调试器详解
2017/08/22 Javascript
React Native 通告消息竖向轮播组件的封装
2020/08/25 Javascript
原生JS写Ajax的请求函数功能
2017/12/22 Javascript
Vue使用vux-ui自定义表单验证遇到的问题及解决方法
2018/05/10 Javascript
layui实现鼠标移动到单元格上显示数据的方法
2019/09/11 Javascript
jQuery实现倒计时功能完整示例
2020/06/01 jQuery
详解微信小程序动画Animation执行过程
2020/09/23 Javascript
Python实现的多线程端口扫描工具分享
2015/01/21 Python
python 捕获 shell/bash 脚本的输出结果实例
2017/01/04 Python
解决PyCharm中光标变粗的问题
2017/08/05 Python
Pycharm代码无法复制,无法选中删除,无法编辑的解决方法
2018/10/22 Python
机器学习实战之knn算法pandas
2019/06/22 Python
python 元组和列表的区别
2020/12/30 Python
python正则表达式re.match()匹配多个字符方法的实现
2021/01/27 Python
HTML5制作表格样式
2016/11/15 HTML / CSS
联想马亚西亚官方网站:Lenovo Malaysia
2018/09/19 全球购物
Miller Harris官网:英国小众香水品牌
2020/09/24 全球购物
程序员岗位职责
2013/11/11 职场文书
区域总监的岗位职责
2013/11/21 职场文书
优秀学生干部推荐材料
2014/02/03 职场文书
马云北大演讲完整版:真心话,什么才是阿里的核心竞争力?
2014/04/04 职场文书
2014幼儿园卫生保健工作总结
2014/12/05 职场文书
《文化苦旅》读后感:阅读,让人诗意地栖居在大地上
2019/12/24 职场文书