js prototype

JavaScript能够实现的面向对象的特征有:
·公有属性(public field)
·公有方法(public Method)
·私有属性(private field)
·私有方法(private field)
·方法重载(method overload)
·构造函数(constructor)
·事件(event)
·单一继承(single inherit)
·子类重写父类的属性或方法(override)
·静态属性或方法(static member)


例子一(JavaScript中允许添加行为的类型):可以在类型上使用proptotype来为类型添加行为。这些行为只能在类型的实例上体现。 JS中允许的类型有Array, Boolean, Date, Enumerator, Error, Function, Number, Object, RegExp, String

Js代码
  1. <script type="text/javascript">  
  2. Object.prototype.Property = 1;  
  3. Object.prototype.Method = function ()  
  4. {  
  5.     alert(1);  
  6. }  
  7.    
  8. var obj = new Object();  
  9. alert(obj.Property);  
  10. obj.Method();  
  11. </script>  
  12.          

例子二(prototype使用的限制):在实例上不能使用prototype,否则发生编译错误

Js代码
  1. <script type="text/javascript">  
  2. var obj = new Object();  
  3. obj.prototype.Property = 1; //Error 
  4. //Error 
  5. obj.prototype.Method = function()  
  6. {  
  7.     alert(1);  
  8. }  
  9. </script>  
  10.          

例子三(如何定义类型上的静态成员):可以为类型定义“静态”的属性和方法,直接在类型上调用即可

Js代码
  1. <script type="text/javascript">  
  2. Object.Property = 1;  
  3. Object.Method = function()  
  4. {  
  5.     alert(1);  
  6. }  
  7.    
  8. alert(Object.Property);  
  9. Object.Method();  
  10. </script>  
  11.          

例子五():这个例子演示了通常的在JavaScript中定义一个类型的方法

Js代码
  1. <script type="text/javascript">  
  2. function Aclass()  
  3. {  
  4. this.Property = 1;  
  5. this.Method = function()  
  6. {  
  7.     alert(1);  
  8. }  
  9. }  
  10. var obj = new Aclass();  
  11. alert(obj.Property);  
  12. obj.Method();  
  13. </script> 

例子六(JavaScript中允许添加行为的类型):可以在外部使用prototype为自定义的类型添加属性和方法。

Js代码
  1. <script type="text/javascript">  
  2. function Aclass()  
  3. {  
  4. this.Property = 1;  
  5. this.Method = function()  
  6. {  
  7.     alert(1);  
  8. }  
  9. }  
  10. Aclass.prototype.Property2 = 2;  
  11. Aclass.prototype.Method2 = function 
  12. {  
  13.     alert(2);  
  14. }  
  15. var obj = new Aclass();  
  16. alert(obj.Property2);  
  17. obj.Method2();  
  18. </script>  
  19.      

例子八():可以在对象上改变属性。(这个是肯定的)也可以在对象上改变方法。(和普遍的面向对象的概念不同)

Js代码
  1. <script type="text/javascript">  
  2. function Aclass()  
  3. {  
  4. this.Property = 1;  
  5. this.Method = function()  
  6. {  
  7.     alert(1);  
  8. }  
  9. }  
  10. var obj = new Aclass();  
  11. obj.Property = 2;  
  12. obj.Method = function()  
  13. {  
  14.     alert(2);  
  15. }  
  16. alert(obj.Property);  
  17. obj.Method();  
  18. </script> 

例子九():可以在对象上增加属性或方法

Js代码
  1. <script type="text/javascript">  
  2. function Aclass()  
  3. {  
  4. this.Property = 1;  
  5. this.Method = function()  
  6. {  
  7.     alert(1);  
  8. }  
  9. }  
  10. var obj = new Aclass();  
  11. obj.Property = 2;  
  12. obj.Method = function()  
  13. {  
  14.     alert(2);  
  15. }  
  16. alert(obj.Property);  
  17. obj.Method();  
  18. </script>  
  19.          

例子十(如何让一个类型继承于另一个类型):这个例子说明了一个类型如何从另一个类型继承。

Js代码
  1. <script type="text/javascript">  
  2. function AClass()  
  3. {  
  4.        this.Property = 1;  
  5.        this.Method = function()  
  6.        {  
  7.               alert(1);  
  8.        }  
  9. }  
  10.    
  11. function AClass2()  
  12. {  
  13.        this.Property2 = 2;  
  14.        this.Method2 = function()  
  15.        {  
  16.               alert(2);  
  17.        }  
  18. }  
  19. AClass2.prototype = new AClass();  
  20.    
  21. var obj = new AClass2();  
  22. alert(obj.Property);  
  23. obj.Method();  
  24. alert(obj.Property2);  
  25. obj.Method2();  
  26. </script>  
  27.          

例子十一(如何在子类中重新定义父类的成员):这个例子说明了子类如何重写父类的属性或方法。

Js代码

  1. <script type="text/javascript">  
  2. function AClass()  
  3. {  
  4.        this.Property = 1;  
  5.        this.Method = function()  
  6.        {  
  7.               alert(1);  
  8.        }  
  9. }  
  10.    
  11. function AClass2()  
  12. {  
  13.        this.Property2 = 2;  
  14.        this.Method2 = function()  
  15.        {  
  16.               alert(2);  
  17.        }  
  18. }  
  19. AClass2.prototype = new AClass();  
  20. AClass2.prototype.Property = 3;  
  21. AClass2.prototype.Method = function()  
  22. {  
  23.        alert(4);  
  24. }  
  25. var obj = new AClass2();  
  26. alert(obj.Property);  
  27. obj.Method();  
  28. </script>  

 

 

 再来看一遍。

 

JS里的对象在Ajax发展之后, 就跟着疯狂起来, 要玩好JS的对象, 就要搞清楚构造器(constructor), 指针(pointer), 原型(prototype)

这篇文章主要记录我对prototype的理解

prototype

最初的用法是, 为了避免方法在构造器里随机数据被实例化时而产生重复的副本
后来被用在"继承"上面了, 注意, JS语义上是没有继承的, 这里说的是人为的实现

总结, prototype其实也是指针, 默认是实例的指针, 当然也可以人为的改变,

父类A, 子类B

默认情况, B.prototype=A.prototype
这样, B可以访问A的所有原型方法, 这时, B的构造器也变成A了

改变一下, B.prototype=A
这样, B可以访问A的所有静态方法, 这时, B的构造器也变成类A的指针->类的指针->Function的指针->Function的构造器

  • function demo(){ 
  •     var A=function(name){ 
  •         this.name=name; 
  •     } 
  •     A.prototype.showName=function(){alert(this.name);} 
  •     var B=function(name, age){ 
  •         A.call(this, name); 
  •         this.age=age; 
  •     } 
  •     //B.prototype=new A();    //这里2行代码的效果是一样的 
  •     B.prototype=A.prototype;  //目的是返回A的"实例"的指针 
  •  
  •     B.prototype.showAge=function(){alert(this.age);} 
  •     var b=new B("david", 31); 
  •     b.showName(); 
  •     b.showAge(); 
  • 严重注意以上代码的备注, 是new之后的instance的指针, 不是Class的指针,
    下面改一下代码验证一下

    var A=function(name){ 

  •         this.name=name; 
  •         //return this; 这是隐式代码, JS会自动帮我们执行, 这里是关键 
  •     } 
  •  
  • 改为 
  •  
  •     var A=function(name){ 
  •         var o=new Object(); 
  •         o.name=name; 
  •         return o; 
  •     } 

    然后, 当执行到b.showName();时, 就会抛出异常了, 因为 showName是prototype方法, 是指定在A的实例指针下的, 给A添加方法pointer()以获取实例的指针, 然后把它赋予B.prototype

  • function demo(){ 
  •     var A=function(name){ 
  •         this.name=name; 
  •     } 
  •     A.prototype.showName=function(){alert(this.name);} //the function return this, "this" is the pointer of instance 
  •     A.prototype.pointer=function(){return this;} 
  •     var B=function(name, age){ 
  •         A.call(this, name); 
  •         this.age=age; 
  •     } 
  •     //B.prototype=new A(); 
  •     //B.prototype=A.prototype; 
  •     B.prototype=new A().pointer(); 
  •  
  •     B.prototype.showAge=function(){alert(this.age);} 
  •     var b=new B("david", 31); 
  •     b.showName(); 
  •     b.showAge(); 
  • 以上代码运行正常, 证明了prototype实质上就是指于实例的指针
    那么, 如果, 把prototype的指针指于类, 又会如何呢, 我的想法是, 会得到类的静态方法或属性

    以下代码, 给A添加静态方法showSex和静态属性city, 然后把A的类,
    结果应该是A的原型方法showName会报错, 而b.showSex和alert(b.city)会得到正确的执行

  • function demo(){ 
  •     var A=function(name){ 
  •         this.name=name; 
  •     } 
  •     A.prototype.showName=function(){alert(this.name);} //the function return this, "this" is the pointer of instance 
  •     A.prototype.pointer=function(){return this;} 
  •     A.showSex=function(){alert("male");} 
  •     A.city="shenzhen"
  •  
  •     var B=function(name, age){ 
  •         A.call(this, name); 
  •         this.age=age; 
  •     } 
  •     //B.prototype=new A(); 
  •     //B.prototype=A.prototype; 
  •     B.prototype=A; 
  •  
  •     B.prototype.showAge=function(){alert(this.age);} 
  •     var b=new B("david", 31); 
  •     try
  •         b.showName(); 
  •     } catch (exception) { 
  •         alert(exception); 
  •     } 
  •     b.showAge(); 
  •     b.showSex(); 
  •     alert(b.city); 
  • 代码执行正常, 验证无误

    再检验一下constructor

  • function demo(){ 
  •         var A=function(name){ 
  •             this.name=name; 
  •         } 
  •         A.prototype.showName=function(){alert(this.name);} //the function return this, "this" is the pointer of instance 
  •         A.prototype.showSex=function(){alert("male");} 
  •         A.prototype.city="shenzhen"
  •  
  •         var B=function(name, age){ 
  •             A.call(this, name); 
  •             this.age=age; 
  •         } 
  •         B.prototype=A.prototype; 
  •         B.prototype.showAge=function(){alert(this.age);} 
  •         var b=new B("david", 31); 
  •         try
  •             alert(b.constructor);   //output Class A construct 
  •             alert(b.constructor==A);//output true 
  •         } catch (exception) { 
  •             alert(exception); 
  •         } 
  •     } 

    结果表明
    alert(b.constructor), 连 B 的构造器都变成 A 的了
    alert(b.constructor==A), 再比较一次, 输出true, 没有悬念了

    继续挖掘, 把B.prototype=A, 即把A的类指针赋予B的prototype

  • function demo(){ 
  •         var A=function(name){ 
  •             this.name=name; 
  •         } 
  •         A.prototype.showName=function(){alert(this.name);} //the function return this, "this" is the pointer of instance 
  •         A.prototype.showSex=function(){alert("male");} 
  •         A.prototype.city="shenzhen"
  •  
  •         var B=function(name, age){ 
  •             A.call(this, name); 
  •             this.age=age; 
  •         } 
  •         B.prototype=A; 
  •         B.prototype.showAge=function(){alert(this.age);} 
  •         var b=new B("david", 31); 
  •         try
  •             alert(b.constructor==Function.constructor);//output true 
  •             alert(b.constructor);  //output Function's constructor 
  •         } catch (exception) { 
  •             alert(exception); 
  •         } 
  •     } 

    结果表明, B.prototype指到类A的指针去了, 而类的指针, 又指向类的构造器了

    再看看A, 被B"继承"后的样子, 在B.prototype=A的时候, this就已经是指向A了, showAge是不是也应该存在于A的实例呢? 在做个实验, 一个是A被继承前, 一个是A被继承后

  • function demo(){ 
  •         var A=function(name){ 
  •             this.name=name; 
  •         } 
  •         A.prototype.showName=function(){alert(this.name);} //the function return this, "this" is the pointer of instance 
  •         A.prototype.showSex=function(){alert("male");} 
  •         A.prototype.city="shenzhen"
  •  
  •         var a=new A("mochacoffee"); 
  •  
  •         var B=function(name, age){ 
  •             A.call(this, name); 
  •             this.age=age; 
  •         } 
  •         B.prototype=A.prototype; 
  •         B.prototype.showAge=function(){alert(this.age);} 
  •         B.prototype.post="518000"//add property for test 
  •          
  •         var c=new A("reno"); 
  •         a.showAge();        //*1 
  •         alert(a.showAge);   //*2 
  •         c.showAge();        //*3 
  •         alert(c.showAge);   //*4 
  •         alert(a.post);      //*5 
  •         alert(c.post);      //*6 
  •     } 

    结果为: 
    1: undefined
    2: function showAge(){...}
    3: undefined
    4: function showAge(){...}
    5: 518000
    6: 518000

    可以看出, expend之前之后的A, 其实已经是一样了,
    undefined, 是因为没有给变量赋值, 但函数指针已经正确指到B的showAge了
    关于prototype也是, 对于a, 在被B继承后, 也可以获取了518000了, 用java语言来说, prototype只是实例指针而已, 而不论showAge还是post, 都是一个对象, 所以当a的指针指向这个"后来"加上的对象时, 当然也就可以得到518000了

    但这样的话, B被继承A之后, A也得到了B的prototype了, 对于继承机制来说, 这样还算是继承吗? A和B的区别, 仅仅是静态方法和属性而已 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值