Javascript原型链式模型分析
2014-06-17 17:20
169 查看
javascript中最难理解的就是原型链式模型,在写这篇文章前我也找过一些文章,发现都没有写的特别清晰,所以自己做了一些实践,有了一些更加清晰的理解,于是有了这篇文章。
基于类的OOP很好理解,类可以是一段描述块,也可以是其他类似的东西,但不需要有属性和方法,类可以产生实例,而实例拥有类中描述块描述的属性和方法。由于这种方式中类、对象、方法三者是区分的很开的,类不是对象,方法也不是对象。类中的继承关系通过某些关键字指定,例如java中的extends,非常明确并且简单。因此很好理解
基于原型的OOP理解起来相对困难,因为javascript中函数也是对象,实例也是对象。并且javascript中的继承是基于对象的。
原型链通过__proto__属性完成链接,例如
这段代码其实完成了一个继承过程,需要注意的一句就是MyBase.prototype = new Base(); 这句话的意思是MyBase的父对象是通过new关键字实例化的Base对象,
而new其实做了四件事:
1) 如果该函数对象的prototype为null,则生成一个新的原型对象,默认新的原型对象的都是通过new Object()生成的一个Object实例,并将prototype属性设置为该新原型对象,否则使用已有的原型对象;
2)将生成的原型对象的constructor属性设置为this,这里的this即代表该函数对象
3)生成一个空实例对象,将该对象的__proto__属性设置为函数对象的prototype属性指向的对象。
4)将该空实例对象作为this,去调用constructor
这段代码中,MyBase访问a,c的时候直接在底层的MyBase中找到了,所以输出分别是a = 3, c = 5,而访问b时在底层的MyBase中找不到该属性,因此沿着__proto__属性指向的对象进行搜索,由3)可知__proto__属性指向MyBase.prototype,而MyBase.prototype是new Base()得到的Base实例对象,因此在Base实例对象中寻找,找到,故返回b=2
上图很好的说明了Function函数对象和Object对象在原型链中的关系,首先很多博客经常提到如下问题:
1、原型链中的Function和Object,并且说Object在更底层,因为在扩展了Object.prototype扩展了某属性之后,Function也拥有了该属性
2、Object instanceof Function为true和Function instanceof Object都成立,怎么理解?
其实看了上图就不难理解了。
第一,关于谁在最底层的问题,由于Function和Object在链式关系中是相互联系的,如果可以看出谁是根据谁生成的自己这个函数对象,那么可以说后者是前者的底层对象。
对于这个问题,通过观察上体,只提供了一条线索,那就是Object.__proto__ = ==Function.prototype,而Function.__proto__===Empty function !== Object.prototype
所以可以大概猜测,Object函数对象的生成是通过new Function(),此时新对象的prototype还是undefined,没有定义,所以需要为新对象指定prototype为内置生成的顶层对象(root),而顶层对象是构造器为Object函数对象的空的对象。这样Object函数对象变产生了。但是这只是一种推测可能的情况,具体实现和javascript引擎有关。
第二,Object instanceof Function 为true是因为 A instanceof B返回true当且仅当A的原型链中包含了B.prototype,这也是根据原型链来进行判断的,而上图中,很显然,有Object.__proto__==function Empty(){} == Function.prototype;而Function instanceof Object,也同样的从上图中可以看出,Function.__proto__==function Empty(){}.
function Empty(){}.__proto__==Object.prototype,因此满足。
终于写完了,畅快!
一、基于原型OOP和基于类的OOP
在面向对象的编程中我们经常见到的是基于类的OOP,例如一些静态语言像C++,java,以及多数的动态语言,例如Python,PHP等等,据说javascript是唯一采用原型链式模型来实现OOP编程的。基于类的OOP很好理解,类可以是一段描述块,也可以是其他类似的东西,但不需要有属性和方法,类可以产生实例,而实例拥有类中描述块描述的属性和方法。由于这种方式中类、对象、方法三者是区分的很开的,类不是对象,方法也不是对象。类中的继承关系通过某些关键字指定,例如java中的extends,非常明确并且简单。因此很好理解
基于原型的OOP理解起来相对困难,因为javascript中函数也是对象,实例也是对象。并且javascript中的继承是基于对象的。
二、原型链
在javascript中,原型链其实就是一条访问成员或者方法的搜索链式路径。从原型链的最底层一直向上搜索直到原型链的顶层也就是基于类的OOP中的基类。原型链通过__proto__属性完成链接,例如
<script type="text/javascript"> function Base(){ this.a = 1; this.b = 2; } function MyBase(){ this.a = 3; this.c =5; } MyBase.prototype = new Base(); mb = new MyBase(); console.log(mb.a); console.log(mb.b); console.log(mb.c); </script> Hello World!
这段代码其实完成了一个继承过程,需要注意的一句就是MyBase.prototype = new Base(); 这句话的意思是MyBase的父对象是通过new关键字实例化的Base对象,
而new其实做了四件事:
1) 如果该函数对象的prototype为null,则生成一个新的原型对象,默认新的原型对象的都是通过new Object()生成的一个Object实例,并将prototype属性设置为该新原型对象,否则使用已有的原型对象;
2)将生成的原型对象的constructor属性设置为this,这里的this即代表该函数对象
3)生成一个空实例对象,将该对象的__proto__属性设置为函数对象的prototype属性指向的对象。
4)将该空实例对象作为this,去调用constructor
这段代码中,MyBase访问a,c的时候直接在底层的MyBase中找到了,所以输出分别是a = 3, c = 5,而访问b时在底层的MyBase中找不到该属性,因此沿着__proto__属性指向的对象进行搜索,由3)可知__proto__属性指向MyBase.prototype,而MyBase.prototype是new Base()得到的Base实例对象,因此在Base实例对象中寻找,找到,故返回b=2
三、 Function函数对象和Object函数对象
上图很好的说明了Function函数对象和Object对象在原型链中的关系,首先很多博客经常提到如下问题:
1、原型链中的Function和Object,并且说Object在更底层,因为在扩展了Object.prototype扩展了某属性之后,Function也拥有了该属性
2、Object instanceof Function为true和Function instanceof Object都成立,怎么理解?
其实看了上图就不难理解了。
第一,关于谁在最底层的问题,由于Function和Object在链式关系中是相互联系的,如果可以看出谁是根据谁生成的自己这个函数对象,那么可以说后者是前者的底层对象。
对于这个问题,通过观察上体,只提供了一条线索,那就是Object.__proto__ = ==Function.prototype,而Function.__proto__===Empty function !== Object.prototype
所以可以大概猜测,Object函数对象的生成是通过new Function(),此时新对象的prototype还是undefined,没有定义,所以需要为新对象指定prototype为内置生成的顶层对象(root),而顶层对象是构造器为Object函数对象的空的对象。这样Object函数对象变产生了。但是这只是一种推测可能的情况,具体实现和javascript引擎有关。
第二,Object instanceof Function 为true是因为 A instanceof B返回true当且仅当A的原型链中包含了B.prototype,这也是根据原型链来进行判断的,而上图中,很显然,有Object.__proto__==function Empty(){} == Function.prototype;而Function instanceof Object,也同样的从上图中可以看出,Function.__proto__==function Empty(){}.
function Empty(){}.__proto__==Object.prototype,因此满足。
终于写完了,畅快!
相关文章推荐
- JavaScript原型继承之基础机制分析
- JavaScript__proto__原型链深入分析
- javascript 原型、原型链、对象复制等原理和示例分析(下)
- 结对项目之需求分析及原型模型设计
- 第二次作业 —— 结对项目之需求分析与原型模型设计
- Javascript文档对象模型(DOM)实例分析 - 爵士的舞步 - JavaEye技术网站
- 第二次作业——结对项目之需求分析与原型模型设计
- javascript事件模型实例分析
- javascript事件模型实例分析
- 第二次作业——结对项目之需求分析与原型模型设计
- javascript中创建自定义类型的最常见的方式_组合使用构造函数模型和原型模式,动态原型模式
- javascript原型继承分析(prototype)
- 深入浅出JavaScript (六)分析DOM模型
- Javascript 链式运动框架——逐行分析代码,让你轻松了解运动的原理
- javascript原型继承分析(prototype)(补充版)
- JavaScript原型继承之基础机制分析
- 深入浅出JavaScript (六)分析DOM模型
- “瀑布模型”和“原型模型”的基本原理和特点的对比分析
- 简单分析javascript面向对象与原型
- 第二次作业——结对项目之需求分析与原型模型设计