Javascrpt 原型,对象 深入详解

来源:互联网 发布:网络作家船长写的小说 编辑:程序博客网 时间:2024/06/06 00:16

Javascrpt 原型,对象 深入详解在学习javascript的过程中经常遇到Function、Object、prototype、__proto__等概念,通常都是一知半解。自己也从网上查找过这方面的资料,通常讲的都是不够全面,断章取义,以偏概全,搞的我是稀里糊涂,到头来啥也没搞懂。对此我很恼火,今天我发了一天的时间看了几十篇这方面的资料后,终于彻底高清楚了其中的缘由,有一种拨云见日的感觉!!

         言归正传,下面来对我的学习做个总结,主要是讲解Function、Object、Prototype和__proto__。

         故事先从一段简单的脚本代码说起(这是一段神奇的代码):

        

         这段代码神奇之处是其背后有一张复杂的关系图,如下:

        

         这张复杂的关系图,刚开始一看可能有点蒙,不过没有关系,下面要聊的就是这张关系图了。

         foo 是通过new Foo()出来的,

obj 是通过new Object()出来的;

通过foo.__proto__可以访问到Foo.prototype,这两者是等价的,我们可以通过代码证明:

 

    通过debug也可以看到:

        

故事结论1:无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,默认情况下prototype属性会默认获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针;

当调用构造函数创建一个实例的时候,实例内部将包含一个内部指针(很多浏览器这个指针名字为__proto__)指向构造函数的prototype,这个连接存在于实例和构造函数的prototype之间,而不是实例与构造函数之间。

 

在这个故事(javascript)中还有两个很重要的主人公:Object和Function (故事回忆情节)

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

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

这里的两个对象分别代表两个方向:

1、  Object作为众多object(实例,new出来的)的基础类型。

2、  Function作为众多function(主要指function出来的,也可说用户自定义的函数)的基础类型。

下面我们做一些约定内容:Object代表这里说的Object,object代表实例对象;Function代表这里说的Function,function是关键字。对Object和object的区别是,一个是function,一个是new出的对象。

下面我们在看两个问题:

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

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

验证第一个问题(扩展Object原型):

       

故事结论2:

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

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

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

2、Object扩展了Function

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

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

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

验证第二个问题(扩展Function原型):

         

故事结论3:

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

                                                                              

故事结论4:

obj.__proto__可以找到Object.prototype,两者等价。Foo.prototype.__proto__相当于Object.prototype(这里只是属性等相同,但并不是Object)。对于 foo.__proto__.__proto__.__proto__和Object.prototype.__proto__都是null的。如果直接是由Object  new出来的话,就会少一个__proto__为obj.__proto__.__proto__为null

 

Function.__proto__等于Function.prototype,这里是恒等于。

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

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

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

        上述说明,表达了ObjectFunction之间,你中有我,我中有你的关系的形成原因。

  扩展__proto__

   

扩展prototype

    

 

故事结论5:

简单来说就是__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区别的分析,我们可以进一步的解释出,ObjectFunction之间关系的形成原因。当Function.prototype.extendTemp="123";扩展Function的原型时,因为Function.prototype=Object.__proto__,又因为Function.prototype=Function.__proto__。所以Object. extendTemp就存在了。

而对于Object.prototype.extendTemp="123"扩展Object的原型时Function.test4extend存在,则实实在在的说明了Function扩展自Object的。同时下面补一段代码,这段代码,体现了使用Object.__proto__扩展原型的情况:

大结局:

Function扩展自Object,但是Function对Object又有影响,这是通过Object.__proto__就是(===)Function.prototype建立的联系。记住这个联系后,我们还要记住__proto__和prototype的区别,前者扩展的只可以被Function直接调用,后者扩展的只可以通过其实例调用。另外,还要注意__proto__和prototype的链的概念,这是因为,他们可以互相关联,访问到Function或Ojbect的内容。

0 0
原创粉丝点击