关于JS中的constructor与prototype

奋斗吧
奋斗吧
擅长邻域:未填写

标签: 关于JS中的constructor与prototype 博客 51CTO博客

2023-05-11 18:24:16 41浏览

关于JS中的constructor与prototype,

在学习JS的面向对象过程中,一直对constructor与prototype感到很迷惑,看了一些博客与书籍,觉得自己弄明白了,现在记录如下:

     我们都知道,在JS中有一个function的东西。一般人们叫它函数。比如下面的代码

js代码:

 

[javascript] view plaincopyprint?

    1. function Person(name)  
    2. {  
    3.   alert(name);  
    4. }  
    5. Person('js');//js  
    function Person(name)
    {
      alert(name);
    }
    Person('js');//js

     

    上面的代码中,Person的表现的确跟一般的函数没有什么区别,接着看下面的代码

     


    [javascript] view plaincopyprint?

      1. function Person(name)  
      2. {  
      3. this.name=name;  
      4. this.showMe=function()  
      5.         {  
      6. this.name);  
      7.         }  
      8. };  
      9. var one=new Person('JavaScript');  
      10. one.showMe();//JavaScript  
      function Person(name)
      {
         this.name=name;
         this.showMe=function()
              {
                 alert(this.name);
              }
      };
      var one=new Person('JavaScript');
      one.showMe();//JavaScript

      很多人见到了久违的new操作符,于是就叫Person为“类”,可是又没有关键字class的出现,觉得叫“类”有点勉强。于是退而求其次叫Person为类的构造函数。这些概念好像都没有错,之所以出现这样的情况,可能是因为大家都学习了传统的面向对象语言(c++,c#,java等),还有一种思维定势吧。为了让javascript也面向对象,要在javascript中找到与传统面向对象语言的影子。可是按照javascript的说法,function定义的这个Person就是一个Object(对象),而且还是一个很特殊的对象,这个使用function定义的对象与使用new操作符生成的对象之间有一个重要的区别。这个区别就是function定义的对象有一个prototype属性,使用new生成的对象就没有这个prototype属性。

      prototype属性又指向了一个prototype对象,注意prototype属性与prototype对象是两个不同的东西,要注意区别。在prototype对象中又有一个constructor属性,这个constructor属性同样指向一个constructor对象,而这个constructor对象恰恰就是这个function函数本身。

      有点头晕,看下图吧:

       

       

      不相信可以看下面的代码:


      [javascript] view plaincopyprint?

        1. function Person(name)  
        2. {  
        3. this.name=name;  
        4. this.showMe=function()  
        5.         {  
        6. this.name);  
        7.         }  
        8. };  
        9.   
        10. var one=new Person('js');  
        11.   
        12. alert(one.prototype)//undefined  
        13. alert(typeof Person.prototype);//object  
        14. alert(Person.prototype.constructor);//function Person(name) {...};  
        function Person(name)
        {
           this.name=name;
           this.showMe=function()
                {
                   alert(this.name);
                }
        };
        
        var one=new Person('js');
        
        alert(one.prototype)//undefined
        alert(typeof Person.prototype);//object
        alert(Person.prototype.constructor);//function Person(name) {...};

         

        上面的代码证明了one这个对象没有prototype属性。

        我们接着看代码:


        [javascript] view plaincopyprint?

          1. function Person(name)  
          2. {  
          3. this.name=name;  
          4. this.showMe=function()  
          5.         {  
          6. this.name);  
          7.         }  
          8. };  
          9.   
          10. Person.prototype.from=function()  
          11. {  
          12. 'I come from prototype.');  
          13. }  
          14.   
          15. var one=new Person('js');  
          16.   
          17. one.showMe();//js,这个结果没有什么好奇怪的  
          18. one.from();//I come from prototype.,这个结果有一点奇怪吧  
          function Person(name)
          {
             this.name=name;
             this.showMe=function()
                  {
                     alert(this.name);
                  }
          };
          
          Person.prototype.from=function()
          {
            alert('I come from prototype.');
          }
          
          var one=new Person('js');
          
          one.showMe();//js,这个结果没有什么好奇怪的
          one.from();//I come from prototype.,这个结果有一点奇怪吧

           

          要解释这个结果就要仔细研究一下new这个操作符了.var one=new Person('js');这个语句执行的过程可以分成下面的语句:


          [javascript] view plaincopyprint?

            1. var one={};  
            2. Person.call(one,'js');  
            var one={};
            Person.call(one,'js');

            按照《悟透javascript》书中说的,new形式创建对象的过程实际上可以分为三步:
            第一步是建立一个新对象(叫A吧);

            第二步将该对象(A)内置的原型对象设置为构造函数(就是Person)prototype 属性引用的那个原型对象;

            第三步就是将该对象(A)作为this 参数调用构造函数(就是Person),完成成员设置等初始化工作。

            其中第二步中出现了一个新名词就是内置的原型对象,注意这个新名词跟prototype对象不是一回事,为了区别我叫它inobj,inobj就指向了函数Person的prototype对象。在person的prototype对象中出现的任何属性或者函数都可以在one对象中直接使用,这个就是javascript中的原型继承了。

            又头晕了,上图吧!

            这样one对象通过内置的原型对象inobj就可以直接访问Person的prototype对象中的任何属性与方法了。这也就解释了上面的代码中为什么one可以访问form函数了。因为prototype对象中有一个constructor属性,那么one也可以直接访问constructor属性。

            代码:

             

             

             

             

             

             

            [javascript] view plaincopyprint?

              1. function Person(name)  
              2. {  
              3. this.name=name;  
              4. this.showMe=function()  
              5.         {  
              6. this.name);  
              7.         }  
              8. };  
              9.   
              10. Person.prototype.from=function()  
              11. {  
              12. 'I come from prototype.');  
              13. }  
              14.   
              15. var one=new Person('js');  
              16.   
              17. one.showMe();//js,这个结果没有什么好奇怪的  
              18. one.from();//I come from prototype.,这个结果有一点奇怪吧  
              19. alert(one.constructor);//function Person(name) {...}  
              20. alert(Person.prototype.constructor);//function Person(name) {...}  
              function Person(name)
              {
                 this.name=name;
                 this.showMe=function()
                      {
                         alert(this.name);
                      }
              };
              
              Person.prototype.from=function()
              {
                alert('I come from prototype.');
              }
              
              var one=new Person('js');
              
              one.showMe();//js,这个结果没有什么好奇怪的
              one.from();//I come from prototype.,这个结果有一点奇怪吧
              alert(one.constructor);//function Person(name) {...}
              alert(Person.prototype.constructor);//function Person(name) {...}


               接着看继承是如何实现的。

              [javascript] view plaincopyprint?

                1. function Person(name)  
                2. {  
                3. this.name=name;  
                4. this.showMe=function()  
                5.         {  
                6. this.name);  
                7.         }  
                8. };  
                9.   
                10. Person.prototype.from=function()  
                11. {  
                12. 'I come from prototype.');  
                13. }  
                14.   
                15. function SubPerson()  
                16. {  
                17. }  
                18. SubPerson.prototype=new Person();  
                19.   
                20. var subOne=new SubPerson();  
                21. subOne.from();//I come from prototype.  
                22. alert(subOne.constructor);//function Person(name) {...};  
                23. alert(SubPerson.prototype.constructor);//function Person(name) {...};  
                function Person(name)
                {
                   this.name=name;
                   this.showMe=function()
                        {
                           alert(this.name);
                        }
                };
                
                Person.prototype.from=function()
                {
                  alert('I come from prototype.');
                }
                
                function SubPerson()
                {
                }
                SubPerson.prototype=new Person();
                
                var subOne=new SubPerson();
                subOne.from();//I come from prototype.
                alert(subOne.constructor);//function Person(name) {...};
                alert(SubPerson.prototype.constructor);//function Person(name) {...};

                继承的实现很简单,只需要把子类的prototype设置为父类的一个对象即可。注意这里说的可是对象哦!

                 那么通过prototype属性实现继承的原理是什么呢?还是先看图形说明,然后编写代码进行验证。

                 

                注意:红色的方框就是把子类与父类链接起来的地方。这个就应该是传说中的prototype链了吧。下面有代码进行验证。

                js代码:


                [javascript] view plaincopyprint?

                  1. function Person(name)  
                  2. {  
                  3. this.name=name;  
                  4. this.showMe=function()  
                  5.         {  
                  6. this.name);  
                  7.         }  
                  8. };  
                  9.   
                  10. Person.prototype.from=function()  
                  11. {  
                  12. 'I come from prototype.');  
                  13. }  
                  14. var father=new Person('js');//为了下面演示使用showMe方法,采用了js参数,实际多采用无参数  
                  15. alert(father.constructor);//查看构造函数,结果是:function Person(name) {...};  
                  16. function SubPer()  
                  17. {  
                  18. }  
                  19. SubPer.prototype=father;//注意这里  
                  20. SubPer.prototype.constructor=SubPer;  
                  21.   
                  22. var son=new SubPer();  
                  23. son.showMe();//js  
                  24. son.from();//I come from prototype.  
                  25. alert(father.constructor);//function SubPer(){...}  
                  26. alert(son.constructor);//function SubPer(){...}  
                  27. alert(SubPer.prototype.constructor);//function SubPer(){...}  
                  function Person(name)
                  {
                     this.name=name;
                     this.showMe=function()
                          {
                             alert(this.name);
                          }
                  };
                  
                  Person.prototype.from=function()
                  {
                    alert('I come from prototype.');
                  }
                  var father=new Person('js');//为了下面演示使用showMe方法,采用了js参数,实际多采用无参数
                  alert(father.constructor);//查看构造函数,结果是:function Person(name) {...};
                  function SubPer()
                  {
                  }
                  SubPer.prototype=father;//注意这里
                  SubPer.prototype.constructor=SubPer;
                  
                  var son=new SubPer();
                  son.showMe();//js
                  son.from();//I come from prototype.
                  alert(father.constructor);//function SubPer(){...}
                  alert(son.constructor);//function SubPer(){...}
                  alert(SubPer.prototype.constructor);//function SubPer(){...}

                   

                   根据上图的prototype链,还有代码的结果,我想应该明白为什么使用prototype能够实现

                  JS中的继承了吧。



                  好博客就要一起分享哦!分享海报

                  此处可发布评论

                  评论(0展开评论

                  暂无评论,快来写一下吧

                  展开评论

                  您可能感兴趣的博客

                  客服QQ 1913284695