javascript学习笔记(九)javascript中的原型(prototype)及原型链的继承方式


Posted in Javascript onApril 12, 2011

在使用面向对象编程时,对象间的继承关系自然少不了!而原型正是实现javascript继承的很重要的一种方法!
我们首先来看以下代码:

function person(name, age) { 
this.name = name; 
this.age = age; 
} 
person.prototype.getInfo = function() { 
alert("My name is "+this.name+", and I have "+this.age+" years old"); 
} 
var zhangchen = new person("zhangchen", 23); 
zhangchen.getInfo(); //output My name is zhangchen, and I have 23 years old;

从运行的结果我们可以看出,通过关键字new创建的zhangchen这个对象继承了person中通过原型定义的getInfo()方法。下面我们具体来看新建的zhangchen这个对象是如何继承person对象的属性和方法的。
原型:在使用 JavaScript 的面向对象编程中,原型对象是个核心概念。在 JavaScript 中对象是作为现有示例(即原型)对象的副本而创建的,该名称就来自于这一概念。此原型对象的任何属性和方法都将显示为从原型的构造函数创建的对象的属性和方法。可以说,这些对象从其原型继承了属性和方法。当创建zhangchen对象时:
var zhangchen = new company("zhangchen", 23);

zhangchen 所引用的对象将从它的原型继承属性和方法,对象 zhangchen 的原型来自构造函数(在这里是函数 person)的属性。

在 JavaScript 中,每个函数都有名为prototype的属性,用于引用原型对象。此原型对象又有名为constructor的属性,它反过来引用函数本身。这是一种循环引用, 下图更好地说明了这种循环关系。

javascript学习笔记(九)javascript中的原型(prototype)及原型链的继承方式

图1 循环关系

现在,通过new运算符用函数(上面示例中为 person)创建对象时,所获得的对象将继承 person.prototype 的属性。在上图,可以看到 person.prototype 对象有一个回指 person 函数的构造函数属性。这样,每个 person对象(从 person.prototype 继承而来)都有一个回指 person 函数的构造函数属性。

我们可以用以下代码来验证这种循环是否正确:

function person(name, age) { 
this.name = name; 
this.age = age; 
} person.prototype.getInfo = function() { 
alert("My name is "+this.name+", and I have "+this.age+" years old"); 
} 
var zhangchen = new person("zhangchen", 23); 
alert(zhangchen.constructor == person.prototype.constructor); //output true 
alert(zhangchen.constructor == person);// output true 
alert(person.prototype.isPrototypeOf(zhangchen)); //output true

以上代码中的对"isPrototypeOf()"方法的调用来自哪里呢?是来自person.prototype对象吗?不对,实际上,在 person.prototype 和 person 实例中还可以调用其他方法,比如 toString、toLocaleString 和 valueOf,但它们都不来自 person.prototype。而是来自于JavaScript 中的 Object.prototype ,它是所有原型的最终基础原型。(Object.prototype 的原型是 null。)

在以上例中,zhangchen.prototype 是对象。它是通过调用 Object 构造函数创建的(尽管它不可见)相当于执行子以下代码:

zhangchen.prototype = new Object();

因此,正如 person实例继承person.prototype 一样,zhangchen.prototype 继承 Object.prototype。这使得所有 zhangchen 实例也继承了 Object.prototype 的方法和属性。

原型链:每个 JavaScript 对象都继承一个原型链,而所有原型都终止于 Object.prototype。注意,这种继承是活动对象之间的继承。它不同于继承的常见概念,后者是指在声明类时类之间的发生的继承。因此,JavaScript 继承动态性更强。它使用简单算法实现这一点,如下所示:当您尝试访问对象的属性/方法时,JavaScript 将检查该属性/方法是否是在该对象中定义的。如果不是,则检查对象的原型。如果还不是,则检查该对象的原型的原型,如此继续,一直检查到 Object.prototype。下图说明了此解析过程:

javascript学习笔记(九)javascript中的原型(prototype)及原型链的继承方式
图2 toString()方法的解析过程

从以上解析过程中,如果在对象中定义了属性/方法 X,则该对象的原型中将隐藏同名的属性/方法。例如,通过在 person.prototype 中定义 toString 方法,可以改写 Object.prototype 的 toString 方法。

再看以下代码:

function person(name, age) { 
this.name = name; 
this.age = age; 
} 
person.prototype.getInfo = function() { 
alert("My name is "+this.name+", and I have "+this.age+" years old"); 
} 
var zhangchen = new person("zhangchen", 23); 
var luomi = new person("luomi", 23); 
zhangchen.getInfo(); // output My name is zhangchen, and I have 23 years old; 
luomi.getInfo(); // output My name is luomi, and I have 23 years old; 
luomi.getInfo = function() { 
alert("here can rewrite the function of getInfo!"); 
} 
luomi.getInfo(); //here can rewrite the function of getInfo! 
zhangchen.getInfo(); // output My name is zhangchen, and I have 23 years old;

从运行结果可以看到,虽然person的每个实例都继承了person.prototype中的方法,但是我们也可以在实例化的对象中重新定义原型对象中的方法,而且也不会影响到其它的实例!

以上是自己对原型及原型链继承方式的认识,参考( JavaScript: 使用面向对象的技术创建高级 Web 应用程序),希望大家共同讨论!

Javascript 相关文章推荐
JavaScript 注册事件代码
Jan 27 Javascript
读jQuery之五(取DOM元素)
Jun 20 Javascript
从数据库读取数据后将其输出成html标签的三种方法
Oct 13 Javascript
JQuery中attr属性和jQuery.data()学习笔记【必看】
May 18 Javascript
Js 获取当前函数参数对象的实现代码
Jun 20 Javascript
JavaScript学习笔记整理_用于模式匹配的String方法
Sep 19 Javascript
vue一步步实现alert功能
Jul 05 Javascript
Angular 4根据组件名称动态创建出组件的方法教程
Nov 01 Javascript
angular 组件通信的几种实现方式
Jul 13 Javascript
小程序封装路由文件和路由方法(5种全解析)
May 26 Javascript
JS实现动态添加外部js、css到head标签的方法
Jun 05 Javascript
vue接口请求加密实例
Aug 11 Javascript
javascript 学习笔记(八)javascript对象
Apr 12 #Javascript
jQuery的初始化与对象构建之浅析
Apr 12 #Javascript
避免回车键导致的页面无意义刷新的解决方法
Apr 12 #Javascript
基于jquery实现的上传图片及图片大小验证、图片预览效果代码
Apr 12 #Javascript
javascript实现上传图片并预览的效果实现代码
Apr 11 #Javascript
window.dialogArguments 使用说明
Apr 11 #Javascript
30个最佳jQuery Lightbox效果插件分享
Apr 11 #Javascript
You might like
php对xml文件的增删改查操作实现方法分析
2017/05/19 PHP
PHP基于socket实现的简单客户端和服务端通讯功能示例
2017/07/10 PHP
数组方法解决JS字符串连接性能问题有争议
2011/01/12 Javascript
javascript 函数及作用域总结介绍
2013/11/12 Javascript
JavaScript中0和""比较引发的问题
2016/05/26 Javascript
Bootstrap学习笔记之css样式设计(2)
2016/06/07 Javascript
AngularJS 遇到的小坑与技巧小结
2016/06/07 Javascript
JS HTML5实现拖拽移动列表效果
2020/08/27 Javascript
微信小程序 MINA文件结构
2016/10/17 Javascript
js基础之DOM中元素对象的属性方法详解
2016/10/28 Javascript
详解用webpack把我们的业务模块分开打包的方法
2017/07/20 Javascript
聊聊那些使用前端Javascript实现的机器学习类库
2017/09/18 Javascript
用js实现每隔一秒刷新时间的实例(含年月日时分秒)
2017/10/25 Javascript
vue获取当前激活路由的方法
2018/03/17 Javascript
Vue实现移动端左右滑动效果的方法
2018/11/27 Javascript
微信小程序bindinput与bindsubmit的区别实例分析
2019/04/17 Javascript
通过javascript实现段落的收缩与展开
2019/06/26 Javascript
nodejs中各种加密算法的实现详解
2019/07/11 NodeJs
Auto.JS实现抖音刷宝等刷视频app,自动点赞,自动滑屏,自动切换视频功能
2020/05/08 Javascript
Vue绑定用户接口实现代码示例
2020/11/04 Javascript
python实现颜色rgb和hex相互转换的函数
2015/03/19 Python
python 获取list特定元素下标的实例讲解
2018/04/09 Python
Python检查ping终端的方法
2019/01/26 Python
python单线程文件传输的实例(C/S)
2019/02/13 Python
Python切片操作去除字符串首尾的空格
2019/04/22 Python
pycharm中如何自定义设置通过“ctrl+滚轮”进行放大和缩小实现方法
2020/09/16 Python
Python之qq自动发消息的示例代码
2021/02/18 Python
处理HTML5新标签的浏览器兼容版问题
2017/03/13 HTML / CSS
WoolOvers爱尔兰:羊绒、羊毛和棉针织品
2017/01/04 全球购物
董事长秘书工作职责
2014/06/10 职场文书
2014年大学生预备党员思想汇报1000字
2014/09/13 职场文书
2015试用期转正工作总结
2014/12/12 职场文书
2014年底工作总结
2014/12/15 职场文书
redis实现排行榜功能
2021/05/24 Redis
html+css实现文字折叠特效实例
2021/06/02 HTML / CSS
使用MybatisPlus打印sql语句
2022/04/22 SQL Server