JavaScript中的几个关键概念的理解-原型链的构建


Posted in Javascript onMay 12, 2011

Javascript中所有function中都有一个prototype属性,并且这个prototype属性是一个object类型的对象,所有由该function构造出来的对象都具有这个prototype上的特性,也就是说可以用构造出来的对象直接访问prototype上的属性和方法。
下面一段代码演示prototype的使用方法:

function Staff(name) { 

this.name = name; 

} 

Staff.prototype.say = function() { 

alert(this.name + " say hello"); 

} 

var staff1 = new Staff("hunter"); 

var staff2 = new Staff("dangjian"); 

staff1.say(); 

staff2.say();

运行如上的程序,可知prototype上的属性和方法可以通过创建的对象之间调用,更重要的是prototype中的属性和方法是在同类型的对象中是共享的
alert( staff1.say == staff2.say);

prototype另外一个常用的特性是通过prototype构建对象的继承关系,通过把基类对象赋给子类的prototype的方式可以模拟面向对象中的继承关系,这就是大家经常说的JavaScript的面向对象机制。如下的代码段演示了利用这一特性构建对象的继承关系:

function Staff(name) { // 基类 

this.name = name; 

} 

Staff.prototype.say = function() { 

alert(this.name + " say hello"); 

} 

function ManStaff(name, age) { // 子类 

this.name = name; 

this.age = age; 

} 

ManStaff.prototype = new Staff(); // 建立继承关系 

var manStaff1 = new ManStaff("hunter", 22); 

var manStaff2 = new ManStaff("dangjian", 32); 

manStaff1.say(); 

manStaff2.say();

运行代码可知,ManStaff对象中具有了基类Staff中的Say方法,这种继承方式在JavaScript中是通过prototype链来实现的。大家可能熟悉以上的prototype用法,可是作为程序员,我们不光要知道其用法,我们更应该理解其可是prototype的内部机制。下面我们来分析prototype的原理以及prototype链的实现。
要理解prototype的机制就必须要了解JavaScript中function的创建方式。
当代码执行到function Staff(name) {this.name = name;}时,相当于执行var Staff = new Function(“name”, "this.name = name”)解释器将使用预定义好的Function() constructor,来创建一个function类型的object出来,即Staff。

随后给创建好的Staff对象添加__proto__属性,并赋值为Function的构造器的prototype,这一步是所有对象创建过程中都有的步骤,在执行类似var x = new X()方式是,都会把X的prototype赋值给x的__proto__,类似如下的赋值:

Staff.__proto__ = Function.prototype;

接下来给Staff创建prototype属性,这一步是创建function类型的对象具有的步骤,创建的过程如下伪代码:
var o = new Object(); 

o.constructor = Base; 

Staff.prototype = o;

如上的分析我们可知,当创建对象时,会创建一个私有属性__proto__,当创建function是会创建一个prototype属性。因为Staff是一个function类型的对象,所以会同时具有这两个属性。
这两个属性是构建原型链的关键属性。我们来分析执行代码 var staff1 = new Staff(“hunter”)时,原型是如何传递的。
根据如上分析,staff1.__proto__ = Staff.prototype,而Staff.prototype又是一个由Object创建的对象,即Staff.prototype.__proto__ = Object.prototype,所以staff1.__proto__ .__proto__ 指向的是Object.prototype,即staff1.__proto__ .__proto__ == Object.prototype,这就是原型链,当要读取某个对象的属性时,JS首先找对象本身是否有这个属性,如果没有就会顺着原型链一直寻找这个属性。
知道了原型链的原理,那么就很容易根据这个原理来构建Javascript中的对象继承。
由如上的分析,我们可知原型链的顶端都是Object.prototype,这就意味着在构建的继承关系中Object是所有对象的基类,可以运行如下的代码验证。
Object.prototype.location = "China"; 

function Staff(name) { // 基类 

this.name = name; 

} 

Staff.prototype.say = function() { 

alert(this.name + " say hello"); 

} 

var ManStaff1 = new Staff("hunter"); 

var ManStaff2 = new Staff("dangjian"); 

alert(ManStaff1.location); 

alert(ManStaff2.location);

运行结果知道,Object是Staff的基类,那么要如何构建一个Staff的子类呢?
理解了上面函数的建立原理,我们很容易写出如下的代码:
function Staff(name) { // 基类 

this.name = name; 

} 

Staff.prototype.say = function() { 

alert(this.name + " say hello"); 

} 

function ManStaff(name, age) { // 子类 

Staff.call(this,name); 

this.age = age; 

} 

ManStaff.prototype = new Staff(); // 建立继承关系 

var ManStaff1 = new ManStaff("hunter", 22); 

var ManStaff2 = new ManStaff("dangjian", 32); 

ManStaff1.say(); 

ManStaff2.say();

建立继承关系的就是这句:ManStaff.prototype = new Staff(); ,继承关系推算如下:ManStaff1.__proto__ = =ManStaff.prototype, ManStaff.prototype.__proto__ = Staff.prototype, Staff.prototype.__proto__ == Object.prototype;则ManStaff1.__proto__.__proto__.__proto__ == Object.prototype。
javascript中的这种继承关系比较传统面向对象的继承关系更松散,构建方式也比较难以理解,但是作为脚本语言,其功能已经是非常强大了。
Javascript 相关文章推荐
javascript实现的图片切割多块效果实例
May 07 Javascript
jquery获取当前元素索引值用法实例
Jun 10 Javascript
jQuery的实例及必知重要的jQuery选择器详解
May 20 Javascript
json对象与数组以及转换成js对象的简单实现方法
Jun 24 Javascript
AngularJS实现星星等级评分功能
Sep 24 Javascript
Bootstrap基本组件学习笔记之按钮组(8)
Dec 07 Javascript
JavaScript组成、引入、输出、运算符基础知识讲解
Dec 08 Javascript
bootstrap常用组件之头部导航实现代码
Apr 20 Javascript
JQuery Ajax 异步操作之动态添加节点功能
May 24 jQuery
详解vue项目首页加载速度优化
Oct 18 Javascript
springmvc接收jquery提交的数组数据代码分享
Oct 28 jQuery
JS和Canvas实现图片的预览压缩和上传功能
Mar 30 Javascript
Jqyery中同等与js中windows.onload的应用
May 10 #Javascript
JQuery 1.6发布 性能提升,同时包含大量破坏性变更
May 10 #Javascript
JavaScript中为元素加上name属性的方法
May 09 #Javascript
JavaScript 放大镜 移动镜片效果代码
May 09 #Javascript
JavaScript 放大镜 放大倍率和视窗尺寸
May 09 #Javascript
关于JavaScript的with 语句的使用方法
May 09 #Javascript
JavaScript的parseInt 取整使用
May 09 #Javascript
You might like
php通过ajax实现双击table修改内容
2014/04/28 PHP
PHP随手笔记整理之PHP脚本和JAVA连接mysql数据库
2015/11/25 PHP
ThinkPHP5.0框架结合Swoole开发实现WebSocket在线聊天案例详解
2019/04/02 PHP
用脚本调用样式的几种方法
2006/12/09 Javascript
jquery简单体验
2007/01/10 Javascript
Extjs学习笔记之五 一个小细节renderTo和applyTo的区别
2010/01/07 Javascript
jquery ajax请求实例深入解析
2012/11/26 Javascript
浅谈javascript基础之客户端事件驱动
2016/06/10 Javascript
详解微信开发中snsapi_base和snsapi_userinfo及静默授权的实现
2017/03/11 Javascript
深入理解 JavaScript 中的 JSON
2017/04/06 Javascript
jQuery实现可兼容IE6的遮罩功能详解
2017/09/19 jQuery
Angular实现预加载延迟模块的示例
2017/10/12 Javascript
react-native 圆弧拖动进度条实现的示例代码
2018/04/12 Javascript
JS使用遮罩实现点击某区域以外时弹窗的弹出与关闭功能示例
2018/07/31 Javascript
深入理解Vue父子组件生命周期执行顺序及钩子函数
2018/08/12 Javascript
配置一个vue3.0项目的完整步骤
2019/04/26 Javascript
vux-scroller实现移动端上拉加载功能过程解析
2019/10/08 Javascript
基于JavaScript判断两个对象内容是否相等
2020/01/10 Javascript
JS浏览器BOM常见操作实例详解
2020/04/27 Javascript
Vue 中使用lodash对事件进行防抖和节流操作
2020/07/26 Javascript
Python3 修改默认环境的方法
2019/02/16 Python
python实现自动化上线脚本的示例
2019/07/01 Python
Pytorch 实现自定义参数层的例子
2019/08/17 Python
如何在python开发工具PyCharm中搭建QtPy环境(教程详解)
2020/02/04 Python
在Ubuntu 20.04中安装Pycharm 2020.1的图文教程
2020/04/30 Python
python如何提升爬虫效率
2020/09/27 Python
html5指南-6.如何创建离线web应用程序实现离线访问
2013/01/07 HTML / CSS
Myprotein荷兰官网:欧洲第一运动营养品牌
2020/07/11 全球购物
九年级英语教学反思
2014/01/31 职场文书
自主招生自荐信怎么写
2015/03/24 职场文书
不同意离婚答辩状
2015/05/22 职场文书
美容院员工规章制度
2015/08/05 职场文书
Python控制台输出俄罗斯方块的方法实例
2021/04/17 Python
pytorch锁死在dataloader(训练时卡死)
2021/05/28 Python
【海涛教你打DOTA】剑圣第一人称视角解说
2022/04/01 DOTA
MySQL性能指标TPS+QPS+IOPS压测
2022/08/05 MySQL