04JavaScript构造函数

js面向(基于)对象编程——类(原型对象)与对象

对象—对象(成员)函数的初步介绍
在某些情况下,我们要需要定义对象函数。比如人对象:除了有一些属性外(成员变量表示的年龄,姓名……),我们人对象还有一些行为比如:可以说话,跑步……,通过学习,我们人还可以做算术题。这是就要用函数才能完成。现在要对Person对象完善:
①添加speak函数,输出我是一个好人
②添加jisuan函数,可以计算从1+...+1000的结果
③修改jisuan函数,该方法可以接收一个数n,计算从1+...+n的结果
④添加add成员函数,可以计算两个数的和

对象——成员函数(方法)
比如:我们希望对象不但有属性,还希望他有行为。(行为在程序中要靠函数来体现)

demo1.html

<html>    
  <head>    
      <script language="javascript">    
        function Person(name,age){    
            //这个就是使用传入的实际参数,去初始化属性。    
            this.name=name;    
            this.age=age;    
            //输出自己的名字    
            //这里this.show就是一个公开的函数,函数名是show    
            //有一个麻烦事,先点出来。这样的方式有一个弊病,  
            //你用这样的方式分配一个函数,那么每个对象都有show这段函数代码。  
            //如p1有,p2也有等等,在一定程度上效率会有以一点影响,  
            //这个问题怎么解决,在后面讲解。  
            //这样去分配函数,会使每一个Person对象实例,都有一段这样的show函数代码,  
            //也就是show这个函数不会放在一个所谓的代码区让所有对象共享,  
            //而是每一个对象都会有一段这样的代码,这就造成一种浪费了,  
            //当然在对象不多的情况下,也无所谓,一旦对象用完了就会被垃圾回收给回收了。  
            //如果连这点浪费也要避免的话,就要用原型的方式来解决。  
            //在后面会讲解。当然,this.show类似的方法在开发中也有用到。    
            this.show=function(){    
                document.writeln("名字="+this.name); //this要带上,如果不带this,就会认为name是另外一个变量了    
            }    

            //添加jisuan函数,可以计算从1+...+1000的结果    
            this.jisuan=function(){    
                var res=0;    
                for(var i=1;i<=1000;i++){    
                    res+=i;    
                }    
                return res;    
            }    
              
            //改进jisuan函数,可以计算从1+...+n的结果    
            this.jisuan2=function(n){    
                var res=0;    
                for(var i=1;i<=n;i++){    
                    res+=i;    
                }    
                return res;    
            }    
        }    

        var p1=new Person("宋江",90);    
        p1.show();    

        document.writeln("<br/> res="+p1.jisuan());    
        document.writeln("<br/> res="+p1.jisuan2(10));    
      </script>    
  </head>    
    <body></body>    
</html>    

给一个对象添加(指定)函数的几种方式

上面的方法,是在对象的里面定义了函数,下面的两种方法写在对象的外面

给对象添加方法的两种方式

第一种:

 function 类名(){  
      this.属性;  
 }  
 var 对象名=new 类名();  
 function 函数名(){  
     //执行  
 }  
 对象名.属性名=函数名;  //这样就相当于把 函数赋给 对象名.属性名,此时这个属性名就表示一个函数了  
 对象名.属性名(); //调用  

第二种:
 

对象名.属性名=function 函数名(参数列表){ 

           //代码 

    }  

对象名.属性名(实际参数); //调用  

这两种方法的案例 ,看上面图片中的案例。

<html>    
  <head>    
    <script language="javascript">    
      
            function Person(){    
                this.name="abc";    
                this.age=900;    
            }    
            function show1(){    
                window.alert("hello"+this.name);    
            }    
            //创建一个p1对象    
            var p1=new Person();    
            //把show1函数,给p1.abc    
            p1.abc=show1; //这样就相当于把show1的函数指针给它了,  
            //这个时候大家是共享的一个了,不是每个对象都有这个show1,不是每个对象都指向show1了,  
            //对比上一段代码    
            //把原来写在里面的show1函数,写在外面了,仅此而已    
            //带括号和不带括号的区别:如果是p1.abc=show1();就是把show1函数的返回值交给p1.abc这个属性,即hello;  
            //如果是p1.abc=show1;就是把函数本身交给p1.abc这个属性值,this会起作用,即helloabc。    
            p1.abc(); //调用    
    </script>    
  </head>    
    <body></body>    
</html>   

带括号和不带括号的区别:如果是p1.abc=show1();就是把show1函数的返回值交给p1.abc这个属性,即hello;

 如果是p1.abc=show1;就是把函数本身交给p1.abc这个属性值,this会起作用,即helloabc。  

p1.abc=show1;  

p1.abc=show1();  

javascript的语法特别灵活,不在里面写,而是在外面写了函数,然后再分配给他,就好像动态分配一个对象属性一样,动态分配一个函数,这是允许的。
但是同样记住灵活是把双刃剑。

在上面的图片中,还有两个思考题:

<html>    
    <head>    
        <script language="javascript">    
            function Person(){    
                this.name="abc";    
                this.age=900;    
            }    
            function show1(){    
                window.alert("hello"+this.name);    
            }    
            var p1=new Person();    
            p1.abc=show1; //把show1本身给了p1.abc属性,相当于在Person类中定义的    
            p1.abc(); //输出helloabc    
    
            window.alert(p1.abc);//没有括号,不是p1.abc()这样的,输出function show1这个整个函数,打印函数本身    
            window.alert(show1);//同理和上面一样,同样没有括号,把整个function show1整个函数打印出来    
            window.alert(p1.abc()); //输出helloabc,再输出undefined,这里是调用了,abc后面跟括号了。  
                                    //★★★为什么还会输出undefined★★★ ,  
                                    //因为abc()函数没有返回值,也就是说show1()函数没有定义返回值,所以输出undefined  
            window.alert(show1());//先输出hello,这里的name是属于window对象,再输出undefined,show1()函数没有返回值,所以输出undefined。    
    
            p1.bcd=show1();  //把show1函数的返回值给P1.bcd属性,  
                            //为什么没有this.name呢了,此时show1函数仅仅传递结果,对于show1函数来讲,它不知道this是指向谁    
            window.alert(p1.bcd); //输出undefined ,show1没有放回值。
        </script>    
    </head>    
    <body></body>    
</html>

再看下面的思考问题:

看下面的代码:

<html>    
  <head>    
   <script language="javascript">    
      function Person(){    
          this.name="abc1";    
          this.age=900;    
      }    
      function show1(){    
          window.alert("hello"+this.name); //这个this是谁在调用它,一定要看清楚了    
      }    
      var p1=new Person();    
      p1.abc=show1;    
      show1();//输出hello,在这里,this是window在调用,那么this就是window,但window的name没有值    
   </script>    
  </head>    
    <body></body>    
 </html>  

针对这个问题,再看下面的代码:

<html>    
  <head>    
    <script language="javascript">    
     function Person(){    
         this.name="abc1"    
         this.age=900;    
     }    
     function show1(){    
         window.alert("hello"+this.name);    
     }    
     var p1=new Person();    
     p1.abc=show1;    
     show1(); //输出hello,这样直接调用的话,虽然没有找到this.name她也不再输出了,js引擎一看this.name什么都没有就不输出了。  
              //想看输出undefined,请看下面的语句,更好理解。document.writeln在调试打印很重要    
     document.writeln(show1());//先输出hello,然后又输出undefined,此时的this指的是window,而window的name属性没有,没有放回值    
    </script>    
  </head>    
    <body></body>    
</html>

再来看第二段代码输出什么:

<html>    
 <head>    
   <script language="javascript">    
     function Person(){    
         this.name="abc1";    
         this.age=900;    
     }    
     var name="北京";    
     function show1(){    
         window.alert("hello"+this.name);    
     }    
     var p1=new Person();    
     p1.abc=show1;    
     show1();//输出hello北京,window的name属性的值定义了,var name="北京";    
 </script>    
 </head>    
    <body></body>    
</html>  

 

从上面可以更加深刻的认识 this,谁调用的this

<html>    
  <head>    
    <script language="javascript">    
        function Person(){    
            this.name="abc";    
            this.age=900;    
            this.abc=function(v1,v2){    
                window.alert(this.name+" "+this.age+" "+v1+" "+v2);    
            }    
        }    
        var p1=new Person();    
        p1.abc(); //输出 abc 900 undefined undefined;虽然没有传入参数,但是函数是可以调用起来的,只是遇到 v1和v2会undefined    
        p1.abc("北京","天津"); //输出 abc 900 北京 天津    
        var p2=new Person();    
        p2.abc(); //输出 abc 900 undefined undefined    
        p2.abc("南京","东京"); //输出 abc 900 南京 东京    
        //p1 p2 每个对象创建的对象属性和函数是不一样的   
    </script>    
  </head>    
    <body></body>    
</html>   

这里主要是看p1.name会不会把this.name冲掉

<html>    
  <head>    
    <script language="javascript">    
        function Person(){    
            this.name="abc";    
            this.age=900;    
            this.abc=function(v1,v2){    
                window.alert(this.name+" "+this.age+" "+v1+" "+v2);    
            }    
        }    
        var p1=new Person();    
        p1.name="中国";    
        p1.abc("北京","天津");    
        var p2=new Person();   
 

 
        p2.abc("南京","东京");    
        //这里主要是看p1.name会不会把this.name冲掉   
    </script>    
  </head>    
    <body></body>    
</html>

这里会把p1中的name属性冲掉。类中的this.name是一个公开的属性,p1.name确实是访问这个属性了,原先 确实是abc,但是给你赋了一个新值过后,abc就会被冲掉了,变成了中国。p1.name的的确确是动态添加了,js引擎会首先检测下,p1里面是否已 经有了name这个属性值,如果有的话,就在p1这个对象中,把原来的值冲掉,用新值代替,这样更容易理解。

下面是错误的代码:

<html>    
  <head>    
    <script language="javascript">    
        function Dog(){    
        }    
        var dog1=new Dog();    
        dog1.shout=function(){    
            window.alert("小狗");    
        }    
        dog1.shout();    
        var dog2=new Dog();    
        dog2.shout(); //这里会报错   
    </script>    
  </head>    
    <body></body>    
</html>  

这个是正确的代码:

<html>    
  <head>    
    <script language="javascript">    
      function Dog(){    
      }    
      var dog1=new Dog();    
      Dog.prototype.shout=function(){    
          window.alert("小狗");    
      } // 这里就是让所有的Dog对象共享同一个shout属性function(){}    
      dog1.shout();    
      var dog2=new Dog();    
      dog2.shout();//这里ok    
    </script>    
  </head>    
    <body></body>    
</html>  

如上面使用原型的方法来添加对象的方法,已经是第四种方法了。

 

前面已经讲解了三种了

  1. 在类定义的内部
  2. 外部添加如上面的:p1.abc=show1;
  3. 外部添加如上面的:p1.abc=function show1(){}

 

此时就讲到了在demo1.html中的麻烦事,如在类中定义,this.show=function(){};这种 定义方法,在有些时候,老板或项目经理会对你不满意,因为你每创建一个p1,p2,p3...每一个都会有这个show属性,就相当于每个对象实例都有 this.show=function(){};这段代码。

下面再来看一段代码:

<html>    
  <head>    
    <script language="javascript">    
      function Person(){    
          this.name="abc";    
          this.age=900;    
          this.abc=function(v1,v2){    
              window.alert(this.name+" "+this.age+" "+v1+v2);    
          }    
      }    
      var p1=new Person();    
      p1.abc=function () {window.alert("OK");}  
      var p2=new Person();    
      p1.abc();  
      p2.abc();  
      window.alert(p1.abc);  
      window.alert(p2.abc);  
        
      window.alert(p1.abc==p2.abc); //返回一个 false ,表示p1.abc 和 p2.abc 的堆地址不一样  
                                    //这也正映证了 window.alert(p1.abc); window.alert(p2.abc);输出结果不一样  
    </script>    
  </head>    
    <body></body>    
</html>
<html>    
  <head>    
    <script language="javascript">    
      function Dog(){    
      }    
      //希望所有的对象,共享某个函数    
      //使用prototype[绑定在类上的] 去绑定一个函数给shout    
      Dog.prototype.shout=function(){    
          window.alert("小狗");    
      }    
      var dog1=new Dog();    
      dog1.shout();    
      var dog2=new Dog();    
      dog2.shout();  //这里OK  

      window.alert(dog1.shout==dog2.shout); //返回 true ,表示  dog1.shout和dog2.shout的地址是一样的,即共享的  

      //扩展    
      var dog3=new Dog();    
      var dog4=new Dog();    
      window.alert("dog3==dog4"+(dog3==dog4));//false,dog3和dog4指向的堆区地址不一样    
      var dog5=dog4; // 让dog5指向dog4    
      window.alert("dog4==dog5"+(dog4==dog5));//true,dog4和dog5指向的堆区地址一样    
    </script>    
  </head>    
    <body></body>    
</html>

结论:前面的三种方法有一个问题:那就是每个对象,独占函数代码,这样如果对象很多,则会影响效率。

js设计者,给我们提供了另一个方法 原型法 prototype,使用prototype就可以实现共享代码空间,节省资源。

 

补讲:==号的作用

①当 ==的两边都是字符串的时候,则比较内容是否相等。

②如 ==的两边是数字,则比较数的大小是否相等。

③如 ==的两边是对象 或者是对象函数,则比较它们的地址是否相同。 

下一章写Object类

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值