关于__proto__和prototype的一些理解

源自:http://www.cnblogs.com/zzcflying/archive/2012/07/20/2601112.html

     关于__proto__和prototype的一些理解


     var Person = function (name) {
         this .name = name;
     }
     var p = new Person();
     new 操作符的操作是
     var p = {}
     p.__proto__ =  Person.prototype
     Person.call(p)

            var p={}; 也就是说,初始化一个对象p。

            p.__proto__ = Person.prototype;

            Person.call(p);也就是说构造p,也可以称之为初始化p。

            关键在于第二步,我们来证明一下:


     var Person = function () {}
     var p = new Person();
     alert(p.__proto__ =  Person.prototype)

           这段代码会返回true。说明我们步骤2的正确。

           那么__proto__是什么?我们在这里简单地说下。每个对象都会在其内部初始化一个属性,就是__proto__,当我们访问一个对象的属性时,如果这个对象内部不存在这个

           属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就这样一直找下去,也就是我们平时所说的原型链的概念。

           按照标准,__proto__是不对外公开的,也就是说是个私有属性,但是Firefox的引擎将他暴露了出来成为了一个共有的属性,我们可以对外访问和设置。

           好,概念说清了,让我们看一下下面这些代码:


     var Person = function () { };
     Person.prototype.Say = function () {
         alert( "Person say" );
     }
     var p = new Person();
     p.Say(); 

           这段代码很简单,相信每个人都这样写过,那就让我们看下为什么p可以访问Person的Say。

          首先var p=new Person();可以得出p.__proto__=Person.prototype。那么当我们调用p.Say()时,首先p中没有Say这个属性,于是,他就需要到他的__proto__中去找,也

          就是Person.prototype,而我们在上面定义了Person.prototype.Say=function(){}; 于是,就找到了这个方法。

          好,接下来,让我们看个更复杂的。    

       

    var Person = function () { };
    Person.prototype.Say = function () {
        alert( "Person say" );
    }
    Person.prototype.Salary = 50000;
    var Programmer = function () { };
    Programmer.prototype = new Person();
    Programmer.prototype.WriteCode = function () {
        alert( "programmer writes code" );
    };
    Programmer.prototype.Salary = 500;
    var p = new Programmer();
    p.Say();
    p.WriteCode();
    alert(p.Salary);  


           我们来做这样的推导:

           var p=new Programmer()可以得出p.__proto__=Programmer.prototype;

           而在上面我们指定了Programmer.prototype=new Person();我们来这样拆分,var p1=new Person();Programmer.prototype=p1;那么:

           p1.__proto__=Person.prototype;

           Programmer.prototype.__proto__=Person.prototype;

           由根据上面得到p.__proto__=Programmer.prototype。可以得到p.__proto__.__proto__=Person.prototype。

           好,算清楚了之后我们来看上面的结果,p.Say()。由于p没有Say这个属性,于是去p.__proto__,也就是Programmer.prototype,也就是p1中去找,由于p1中也没有

           Say,那就去p.__proto__.__proto__,也就是Person.prototype中去找,于是就找到了alert(“Person say”)的方法。

           其余的也都是同样的道理。

 

           再来一张stackoverflow上的图:

           个人认为prototype可以当成是一个指针,当new一个方法的时候,指向的都是一个内存区域。而__proto__指向的是原型对象。

           看完这些,感觉对原型链的了解应该差不多了吧。


           下面附上我根据本篇文章画的草图,方便理解:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值