您的位置:首页 > 移动开发 > Objective-C

Javascript中Function,Object,Prototypes,__proto__等概念详解

2013-07-28 15:42 579 查看
转载来源:AnyKoro Blog » 《Javascript中Function,Object,Prototypes,__proto__等概念详解》

本文链接地址:http://anykoro.sinaapp.com/?p=256

Javascript中Function,Object,Prototypes,__proto__等概念是在JavaScript中很常用,但又总是不清不楚的概念。今天主要是解释他们之间的概念和关系,帮助我们更好的理解Javascript。

我们本次的解释,主要通过下图



粗看该图,估计你不一定能看明白。不过接下来让我逐行向你解释。

【第一行】



最左侧:意思是,有两个对象f1和f2,他们是通过new Foo()出来的。

中间:Foo()就是最左侧用到的Foo()

最右侧:表示,函数的prototype属性,对是函数的,不是对象的,站点要注意!

现在知道了各个区块的意思,接下来解释各条线是什么意思。

1、__proto__的虚线:该条线表示通过f1.__proto__可以访问到Foo.prototype,其实两者是等价的,我们可以通过以下代码验证。

?
2、prototype实线:表示通过Foo.prototype可以找到Foo.prototype。这里没有写错,这么写虽然看似有些废话,但是是要体现出流向的。

3、constructor实现:表示通过Foo.prototype.constructor可以找到Foo。验证代码如下:

?
其中的意义在于f1.__proto__.constructor等于Foo

至此第一行结束了。

【插播】

在讲解下面第二行和第三行前,有两个很重要的概念需要深刻理解。否则理解下面的内容是举步维艰的。

Function和Object

function Object(){[native code]}//Javascript自带,不是自定义的,可以近似认为是基类

function Function(){[native code]}//Javascript自带,不是自定义的,可以近似认为是基类

这里的这两个function,分别走两个方向,

Object作为了众多object(实例,new出来的)的基类型

Function作为众多function(主要是那些function出来的,就是定义出来的函数)的基类型

在开始下面更细致的解释先,我们约定一些内容,Object代表这里所说的Object,object代表实例对象

,Function代表这里说的Function,function是关键字。对于Object与object的区别很好理解,一个是function,一个是new出来。

现在让我们思考两个问题:

第一个,当我们扩展Object原型时,new出来的Function,是否会被扩展?

第二个,当我们扩展Function原型时,由于Object也是个Function,那么其实例object是否会被扩展?

先看第一个问题,上代码:

?
扩展Object原型

注释已经写得很清晰了,通过以上几点我们很容易发现以下几点:

1、Object扩展了所有的object(obj,foo)。

与object扩展自Object是相符的。在这里更加验证了。

2、Object扩展了Function

这点说明Function扩展自Object,说明Object比Function更底层些。

3、Object扩展了自身的属性,即Object.test4extend也是可以的。

这点说明,Object扩展了Function,又因为Object本身又是通过function定义出来的,所以会受到Function影响,所以,反过来Function又扩展了Object。

接下来看看第二个问题:

?
扩展Function原型

这说明Function只管没有被实例化得,被实例化的,他是没有办法管的。与Object不同,Object是无论是否实例化都管的。

有了上面的基础,我们来看看第二行和第三行

【第二行】



这里的Object就是我们前面插播的Object。

对于prototype实线和constructor实线和第一行的情况是一样的。这里主要要讲解虚线。

对于中间栏上部的__proto__(即function Object()上面的__proto__):此代表o1.__proto__可以找到Object.prototype,两者等价。我们前面说了这里的Object是泛指的,对应的关系式范式的,所以可以认为第一行中的__proto__是这个关系的实例。

对于右侧上面的__proto__虚线代表,Foo.prototype.__proto相当于Object.prototype(这里只是属性等相同,但并不是Object)

对于最右边侧面的__proto__虚线代表:f1.__proto__.__proto__.__proto__和Object.prototype.__proto__都是null的。如果直接是由Object,new出来的话,就会少一个__proto__为o1.__proto__.__proto__为null

第二行结束

【第三行】



同样实线就不说了,主要说虚线。

先看最左侧的__proto__虚线,表示Foo.__proto__相当于Function.prototype,这里和Object情况差不多,只是属性一致而已,并不是指真正的那个Function。

中间的下部的__proto__虚线,代表Function.__proto__等于Function.prototype,这里可是真的就是,和前面的相当于不同。

验证代码:

?
右侧左上的__proto__虚线,代表Object.__proto__等于Function.prototype,这里可是真的就是,和前面的相当于不同。

验证代码:

?
右侧右上的__proto__虚线,代表Function.prototype.__proto__相当于Object.prototype,只是属性一致而已,并不是真的。

上面的两行红字,也体现了,我们在插播中说的,Object和Function之间,你中有我,我中有你的关系的形成原因。

第三行结束。

看完上面的图,估计你差不多理清了。现在我们准备来做最后的总结。

只是这里又要插播一些了,先让我们总结下__proto__和prototype的区别和关系。

对于区别:

从实际效果上来说,可以认为__proto__是用来扩展Function的,扩展出来的函数,可以直接调用,不需要new出对象才能用,同时对象是不会扩展通过__proto__扩展的方法或属性的。

?
扩展__proto__

对于prototype来说,它是针对对象的,也就是Function是无法使用的,只有new出来的才能有效。

?
扩展prototype

简单来说就是__proto__扩展出来,只有函数可以直接访问,prototype扩展出来的,只有对象才能直接访问。

对于关系:

首先要明确

在Object中__proto__是Function,prototype是Object。

在Function中__proto__是Function,prototype也是Function。

现在让我们再来结合第三行的图看一看。有如下关系。

Function.__proto__就是(===)Function.prototype

Object.__proto__就是(===)Function.prototype

先看类型,等号两边都是一致的。

所以,我们可以有如下结论:

1、Function的__proto__和prototype就是一个,扩展任何一个都是相同的效果。

2、Object的__proto__就是Function.prototype。当我们扩展Object.__proto__时,就相当于扩展了Function.prototype和__proto__,反之亦然。

结合前面__proto__和prototype区别的分析,我们可以进一步的解释出,Object和Function之间关系的形成原因。

当Function.prototype.test4extend="123";扩展Function的原型时,因为Function.prototype=Object.__proto__,又因为Function.prototype=Function.__proto__。所以Object.test4extend就存在了。

而对于Object.prototype.test4extend="123"扩展Object的原型时Function.test4extend存在,则实实在在的说明了Function扩展自Object的。

同时下面补一段代码,这段代码,体现了使用Object.__proto__扩展原型的情况:

?
通过__proto__扩展Object

Ok。。。总算可以进入最终总结了。问题比较复杂,说的比较多,写得真累啊。

【总结】

Function扩展自Object,但是Function对Object又有影响,这是通过Object.__proto__就是(===)Function.prototype建立的联系。记住这个联系后,我们还要记住__proto__和prototype的区别,前者扩展的只可以被Function直接调用,后者扩展的只可以通过其实例调用。另外,还要注意__proto__和prototype的链的概念,这是因为,他们可以互相关联,访问到Function或Ojbect的内容。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: