http://anykoro.sinaapp.com/2012/01/31/javascript%E4%B8%ADfunctionobjectprototypes__proto__%E7%AD%89%E6%A6%82%E5%BF%B5%E8%AF%A6%E8%A7%A3/

http://www.cnblogs.com/youxin/p/3219175.html

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

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

  • 最左侧:意思是,有两个对象f1和f2,他们是通过new Foo()出来的。
  • 中间:Foo()就是最左侧用到的Foo()
  • 最右侧:表示,函数的prototype属性,对是函数的,不是对象的,站点要注意!

现在知道了各个区块的意思,接下来解释各条线是什么意思。
1、__proto__的虚线:该条线表示通过f1.__proto__可以访问到Foo.prototype,其实两者是等价的,我们可以通过以下代码验证。

1
2
3
4
5
6
7
function Foo(){
 
}
 
var f1=new Foo();
 
alert(f1.__proto__==Foo.prototype);//true

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

1
2
3
4
5
function Foo(){
 
}
 
alert(Foo==Foo.prototype.constructor);//true

其中的意义在于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原型
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
Object.prototype.test4extend="123";//扩展Object的原型
 
alert("Function:"+Function.test4extend);//在Function中出现了test4extend属性
 
alert("Object:"+Object.test4extend);//在Object中出现了test4extend属性,此时Object还是个Function
 
var obj=new Object;
alert("Object instance:"+obj.test4extend);//在obj中扩展了test4extend,此时的obj是object
 
function Foo()
{
 
}
 
var foo = new Foo;
alert("foo object:"+foo.test4extend);//foo对象上扩展上了test4extend属性
 
alert("Foo Function:"+Foo.test4extend);//函数上也扩展上了test4extend属性

注释已经写得很清晰了,通过以上几点我们很容易发现以下几点:
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原型
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
Function.prototype.test4extend="123";//扩展Function的原型
 
alert("Function:"+Function.test4extend);//在Function中出现了test4extend属性
 
alert("Object:"+Object.test4extend);//在Object中出现了test4extend属性,注意此时Object是个Function
 
var obj=new Object;
alert("Object instance:"+obj.test4extend);//在obj中没有扩展上test4extend,此时的obj是object
 
function Foo()
{
 
}
 
var foo = new Foo;
alert("foo object:"+foo.test4extend);//foo对象上没有扩展上test4extend
 
alert("Foo Function:"+Foo.test4extend);//Function扩展上了test4extend属性

这说明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,这里可是真的就是,和前面的相当于不同。
验证代码:

1
alert(Function.__proto__===Function.prototype);//true

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

1
alert(Object.__proto__===Function.prototype);//true

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

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

第三行结束。

看完上面的图,估计你差不多理清了。现在我们准备来做最后的总结。
只是这里又要插播一些了,先让我们总结下__proto__和prototype的区别和关系。
对于区别:
从实际效果上来说,可以认为__proto__是用来扩展Function的,扩展出来的函数,可以直接调用,不需要new出对象才能用,同时对象是不会扩展通过__proto__扩展的方法或属性的。

扩展__proto__
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
//Object.prototype.test="prototype test property found";
//alert("Object:"+Object.test);
//上面两句不能用,因为他们会影响Function,Function又会影响Object。前文已经说明
 
function Foo()
{
 
}
 
Foo.__proto__.test="__proto__ test property found";//通过__proto__扩展
Foo.__proto__.addextend=function(){alert("Foo add extend by __proto__");}
 
Foo.addextend();//可以执行
 
var foo=new Foo;
alert("Foo:"+Foo.test);//可以访问
alert(foo.addextend);//未定义
alert("Foo instance:"+foo.test);//未定义

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

扩展prototype
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
//Object.prototype.test="prototype test property found";
//alert("Object:"+Object.test);
//上面两句不能用,因为他们会影响Function,这样就会影响测试Function。前文已经说明
 
function Foo()
{
 
}
Foo.prototype.test="prototype test property found";
Foo.prototype.addextend=function(){alert("Foo add extend by prototype");}
 
alert(Foo.addextend());//未定义
 
var foo=new Foo;
alert("Foo:"+Foo.test);//无法访问
foo.addextend();//可以执行
alert("Foo instance:"+foo.test);//找到了

简单来说就是__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
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
Object.__proto__.test4extend="123";//扩展Object的原型
 
alert("Function:"+Function.test4extend);//在Function中出现了test4extend属性
 
alert("Object:"+Object.test4extend);//在Object中出现了test4extend属性,此时Object还是个Function
 
var obj=new Object;
alert("Object instance:"+obj.test4extend);//未定义
 
function Foo()
{
 
}
 
var foo = new Foo;
alert("foo object:"+foo.test4extend);//未定义
 
alert("Function:"+Foo.test4extend);//函数上也扩展上了test4extend属性

Ok。。。总算可以进入最终总结了。问题比较复杂,说的比较多,写得真累啊。
【总结】
Function扩展自Object,但是Function对Object又有影响,这是通过Object.__proto__就是(===)Function.prototype建立的联系。记住这个联系后,我们还要记住__proto__和prototype的区别,前者扩展的只可以被Function直接调用,后者扩展的只可以通过其实例调用。另外,还要注意__proto__和prototype的链的概念,这是因为,他们可以互相关联,访问到Function或Ojbect的内容。

收工!!好累

 

Javascript中Function,Object,Prototypes,__proto__等概念详解的更多相关文章

  1. javascript中的Base64.UTF8编码与解码详解

    javascript中的Base64.UTF8编码与解码详解 本文给大家介绍的是javascript中的Base64.UTF8编码与解码的函数源码分享以及使用范例,十分实用,推荐给小伙伴们,希望大家能 ...

  2. javascript中的apply,call,bind详解

    apply.call 在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向. Jav ...

  3. GOF提出的23种设计模式是哪些 设计模式有创建形、行为形、结构形三种类别 常用的Javascript中常用设计模式的其中17种 详解设计模式六大原则

    20151218mark 延伸扩展: -设计模式在很多语言PHP.JAVA.C#.C++.JS等都有各自的使用,但原理是相同的,比如JS常用的Javascript设计模式 -详解设计模式六大原则 设计 ...

  4. javascript中的字符串编码、字符串方法详解

    js中的字符串是一种类数组,采用UTF-16编码的Unicode字符集,意味字符串的每个字符可用下标方式获取,而每个字符串在内存中都是一个16位值组成的序列.js对字符串的各项操作均是在对16位值进行 ...

  5. javascript中函数的四种调用模式详解

    介绍函数四种调用模式前,我们先来了解一下函数和方法的概念,其实函数和方法本质是一样,就是称呼不一样而已.函数:如果一个函数与任何对象关系,就称该函数为函数.方法:如果一个函数作为一个对象属性存在,我们 ...

  6. Javascript中call和apply的区别与详解

    在js中call和apply它们的作用都是将函数绑定到另外一个对象上去运行,两者仅在定义参数方式有所区别,下面我来给大家介绍一下call和apply用法: 在web前端开发过程中,我们经常需要改变th ...

  7. JavaScript中数组的两种排序方法详解(冒泡排序和选择排序)

    一.冒泡排序的原理(从小到大) 相邻两个数进行比较,如果前一个数大于后一个数,那么就交换,否则不交换 原理剖析 比如有一组含有6个数字的数:5.3.7.2.1.6一共6个数字,做5次循环,每次循环相邻 ...

  8. ExtJS学习-----------Ext.Object,ExtJS对javascript中的Object的扩展

    关于ExtJS对javascript中的Object的扩展.能够參考其帮助文档,文档下载地址:http://download.csdn.net/detail/z1137730824/7748893 以 ...

  9. 关于ExtJS对javascript中的Object的扩展

    关于ExtJS对javascript中的Object的扩展,可以参考其帮助文档,文档下载地址:http://download.csdn.net/detail/z1137730824/7748893 下 ...

随机推荐

  1. Powershell Switch 条件

    Powershell Switch 条件 6 21 1月, 2012  在 Powershell tagged Powershell教程/ 分支/ 字符串/ 数字/ 条件by Mooser Lee 本 ...

  2. Linux企业级项目实践之网络爬虫(18)——队列处理

    所有的URL都接受管理,并在此进行流动.URL从管理模块的存储空间开始,一直到最后输出给磁盘上的URL索引,都由此部分调度.首先,给出URL调度的一般过程,如图所示.其流程的各个具体操作,后面详述.要 ...

  3. 【转】Win7系统下安装Ubuntu12.04(EasyBCD硬盘安装)--不错

    原文网址:http://blog.csdn.net/lengbuleng1107/article/details/14532177 需要的东西有: 1,ubuntu系统镜像,下载地址:http://w ...

  4. Delphi 把字符串读到流中的操作。

    var FReQuestM := TMemoryStream FReQuestM.Write(PChar(FcVoucherXML)^, Length(FcVoucherXML)); 这样就读到流中了 ...

  5. 在OCX初始化时获取其在网页中的DOM对象

    OCX初始化的时候会调用SetClientSite,会传入IOleClientSite对象. CComQIPtr<IOleControlSite, &IID_IOleControlSit ...

  6. C++ int 转换成 string intToString

    string intToString(int num) { stringstream ss; ss<<num; return ss.str(); } 一个简单的小例子. #include ...

  7. VS2012/2013编辑器问题

    1. Visual Studio 2013 'Could not evaluate Expression' Debugger Abnormality 解决办法:http://weblog.west-w ...

  8. [原创作品]html css改变浏览器选择文字的背景和颜色

    又很久没有'剥壳'了,最近在为一家公司做一个生产管理解决方案.所以都很忙.今天的话题很简单,就做一个很简单的网页特效.今天偶然浏览到一个网站,他们在选择文字时,样子不是蓝背景和白色字体那么单调,感觉这 ...

  9. JSF和Struts的区别概述

    JSF和Struts的区别概述,都采用taglib来处理表示层:在jsp页面中,二者都是采用一套标记库来处理页面的表示和model层的交互. 据说JSF的主要负责人就是struts的主要作者,所以二者 ...

  10. spring-data-mongodb必须了解的操作

    http://docs.spring.io/spring-data/data-mongo/docs/1.0.0.M5/api/org/springframework/data/mongodb/core ...