zoukankan      html  css  js  c++  java
  • JavaScript中的面向对象编程(一)

    Javaspript封装

    1、面向对象语言的要求

         (1)封装把相关的信息(无论数据或方法)存储在对象中的能力

         (2)聚集把一个对象存储在另一个对象内的能力

         (3) 继承由另一个类(或多个类)得来类的属性和方法的能力

         (4)多态编写能以多种方法运行的函数或方法的能力

    ECMAScript支持这些要求,因此可被看作面向对象的.

    2、对象的实例化

          var obj = new Object()

          var ostringobj = new String()

    ECMAScript中也可以把()去掉

         var obj = new object;

         var ostringobj = new String;

    3、对象废除

         ECMAScript中有无用存储单元收集程序,意味着不必专门销毁对象来释放内存.

       也可强制废除对象:eg:

     var obj = new Object();

     obj = null

       

    5、对象类型

         5.1 本地对象

                  Object Array Function String Boolean Number Date RegExp Error EvalError RangeError ReferenceError SyntaxError TypeError URIError

        5.2   自定义对象

    6、作用域,全部都是公共的

          ECMAScript来说,讨论作用域几乎毫无意义。ECMAScript只存在一种作用域(公有作用域)

        许多开发都制定了一个规约:私有的属性建议前后加下划线,如:obj._color_ = “red”;

    7、静态作用域并非静态的

         严格来说,ECMAScript并没有静态作用域,不过,它可以给构造函数提供属性和方法. 构造函数是函数,函数是对象,对象可以有属性和方法。

        如:function sayHi(){

                   alert(“hi”);  };

              sayHi.alternate = function(){ alert(“hellow”);}

    调用:

       sayHi();  sayHi.alternate();

     

     

     

    8、关键字this

           ECMAScript中,要掌握的最重要的概念之一是关键字this的用法.

          它用在对象的方法中,关键字this总是指向调用该方法的对象:

         eg:

         var oCar = new Object();

         oCar.color=“red”;

         oCar.showColor=function(){

             alert(this.color);    //等价于 oCar.color

         }

    说明:利有this,可在任意多个地方重用同一个函数.

    谁调用它这个this就指向谁

    如:function ShowColor()

           {

                alert(this.Color);

           }

           var oCar1 = new Object();

           oCar1.Color = “red”;

           oCar1.ShowColor = ShowColor; //这时thisocar1

       

           var oCar2 = new Object();

           oCar2.Color = “blue”;

          oCar2.ShowColor=ShowColor; //这时thisocar2

           oCar1.ShowColor();   // output “red”

           oCar2.ShowColor();   //outpub “blue”

    注意:引用对象的属性时必须使用this.

              eg: function ShowColor()

                     {

                           alert(Color); //error

                     }

     

     

     

     

     

     

     

     

     

     

     

     

     

    自定义类和对象

        1、工厂模式

             ECMAScript中对象的属性可在对象创建后动态定义.

             如:

     var oCar = new Object();

      oCar.Color = "red";

      oCar.doors = 4;

      oCar.mpg = 23;

      oCar.ShowColor = function(){

          alert(this.Color);

      }

            调用时 oCar.ShowColor();  //output “red”

    问题:需要创建多个Car实例怎么办?

    工厂模式:

    function CreateCar(){   //每次调用都创建新的实例

     var oCar = new Object();

      oCar.Color = "red";

      oCar.doors = 4;

      oCar.ShowColor = function(){

     alert(this.Color);

      }

      return oCar;

       }

    调用:

       var car1 = CreateCar();

       var car2 = CreateCar();  

    car2.color=’blue’;

       alert(car1.Color);    //output “red”

       car2.ShowColor(); //output “blue”

    改造并加入参数:

    function CreateCar(color,doors,mpg){

           var oCar = new Object();

      oCar.Color = color;

      oCar.doors = doors;

      oCar.mpg = mpg;

      oCar.ShowColor = function(){

          alert(this.Color); }

      return oCar; }

       var car1 = CreateCar("red",4,23);

       var car2 = CreateCar("blue",4,20);

       alert(car1.Color);   //output “red”

       car2.ShowColor();        //output “blue”

     

    JavaScript中的封装

    问题:上面的例子中,每次调用函数createCar(),都要创建新函数showColor(),意味着每个对象都有自己的showColor()版本,事实上,每个对象都共享了同一个函数 showColor每次创建都要分配内存空间

    解决方法:

         function showColor()

      {

          alert(this.color);

      }

      function createCar(sColor,iDoors,iMpg)

      {

         var oTempCar = new Object();

             oTempCar.color = sColor;

             oTempCar.doors = iDoors;

             oTempCar.mpg= iMpg;

             oTempCar.showColor = showColor;

             return oTempCar;

      }

      var oCar1 = createCar("red",4,23);

      var oCar2 = createCar("blue",3,25);

      oCar1.showColor();   //output “red”

      oCar2.showColor();   //output “blue”

    问题2

    问题:从功能上讲,这样解决了重复创建函数对象的问题,但该函数看起来不像对象的方法.

    解决办法:

        所有这些问题引发了开发者定义的构造函数的出现

    构造函数方式

        形式如下:

        function Car(sColor,iDoors)    {

            this.color = sColor;

            this.doors = iDoors;

            this.showColor=function(){

                   alert(this.color); } }

    //       oCar.ShowColor = function(){

      //   alert(this.Color); }

     

    //调用

       var oCar1 = new Car(“red”,4);

       var oCar2 = new Car(“blue”,4);

       oCar1.showColor();

       oCar2.showColor();

                                                                     

    问题:存在着和工厂模式相同的问题,创建对象的方法,都分配内存空间

    解决方法:也可以用外部函数重写构造函数,同样的,语义上无任何意义.这就是原型方式的优势所在.

    function Car(){};//相当于定义了一个空的类

    Car.prototype.color = “red”;//object的一个属性prototype

    Car.prototype.doors = 4;

    Car.prototype.showColor = function(){

        alert(this.color);

    }

    //调用

    var oCar1= new Car();

    var oCar2 = new Car();

    oCar1.showColor(); //output “red”

    oCar2.color=“blue”;

    oCar2.showColor(); //output “blue”,需要实例化的时候才分配内存空间

    此种方式,调用new Car(),原型的所有属性都被立即赋予要创建的对象,意味着所有Car实例存放的都是指向showColor()函数的指针.所有属性看起来都属于同一个对象,因此解决了前面两种方式的两个问题

    可以用instanceof运算符测试对象的类型

    eg: alert(oCar1 instanceof Car) //output “true”;

    问题:

    1、 构造函数没有参数.必须创建后才能改变属性的默认值,有些讨厌

    2、真正的问题在于,当属性指向对象时,对象会被多个实例共享。不灵活

    如:

    function Car(){};

    Car.prototype.color = “red”;

    Car.prototype.doors = 4;

     

    Car.prototype.showColor = function(){

        alert(this.color);

    }

    Car.prototype.drivers = new Array(“a”,”b”);

    //call

    var oCar1 = new Car();

    var oCar2 = new Car();

    oCar1.drivers.push(“c”);

    alert(oCar1.drivers); //output “a”,”b”,”c”;

    alert(oCar2.drivers); //outpub “a”,”b”,”c”;

     

     

     

     

    解决方法: 联合使用构造函数和原型方式

    联合使用构造函数和原型方式,就可像用其他程序设计语言一样创建对象.这种概念非常简单,即用构造函数定义对象的所有非函数属性,用原型方式定义对象的函数属性(方法).结果所有函数都只创建一次,而每个对象都具有自己的对象属性实例.

    eg:

    function Car(sColor,iDoors){//实例化的时候不实例化ShowColor这个函数

            this.color = sColor;

            this.doors = iDoors;

            this.drivers = new Array();

         }

    Car.prototype.ShowColor = function(){

         alert(this.color);

    }

    //Call

    var oCar1 = new Car(“red”,4,23);

    var oCar2 = new Car(“blue”,3,25);

    oCar1.drivers.push(“a”);

    oCar2.drivers.push(“b”);

    alert(oCar1.drivers);   //output “a”;

    alert(oCar2.drivers);   //output “b”;

    问题:此种方式已接近完善

    但类的定义分散在两部分,感觉还不是很完美

    解决办法:

    动态原型方法

    Function Car(sColor,iDoors,iMpg){

        this.color = sColor;

        this.doors = iDoors;

        this.mpg = iMpg;

        this.drivers=new Array();

        if (typeof Car._initialized==“undefined”){//initialized随便起的,刚创建的时候肯定不存在

               Car.prototype.showColor = function(){

                    alert(this.color);

               };

              Car._initialized = true;

    //下次再定义这个类的实例,initalized就有值了,就不会重新定义这个方法了

        }

    }

    //call

    var oCar = new Car("yellow",10,20);

    oCar.showColor(); //output “yellow”

     

     

    采用哪种方式?

    如前所述,目前使用最广泛的是混合的构造函数/原型方法.此外,动态原型方法也很流行,功能上和前者等价.可以采用上述方法中的一种.

    实例:

    1、利用javaScript的面向对象技术封装一个字符串连结的类.

    传统的方式:

    var str=“hellow”

    str +=“world”

    缺点:字符串的不变性,导致这种做法很没有效率

    改进一

    var Arr = new Array();

    Arr[0]=“hellow”;

    Arr[1]=“world”;

    var str = Arr.join(““);

    虽然解决了效率问题,但不太优雅.

    改进二

    function StringBuffer()

    {

        this._strings_=new Array(); //私用属性

    }

    StringBuffer.prototype.append = function(str)

    {

          this._strings_.push(str);

    }

    StringBuffer.prototype.toString=function(){

         return this._strings_.join(“”);

    // join() 方法用于把数组中的所有元素放入一个字符串。

    }

    //call 使用

    var strobj = new StringBuffer();

    strobj.append("hellow");

    strobj.append("world");

    alert(strobj.toString());

    修改对象已有的属性,创建新方法

    Eg1:

    Number.prototype.toHexString=function()

    {

       return this.toString(16);

    }

    //call

    var iNum=15;

    alert(iNum.toHexString()); //output “f”

    Eg2 array扩展3个方法

    Array.prototype.enqueue=function(vItem)

    {

     this.push(vItem);//想对象添加值

    }

    Array.prototype.dequeue = function()

    {

       return this.shift();

    shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值

    }

    Array.prototype.indexOf=function(vItem){

        for(var i=0;i<this.length;i++)

        {

             if (vItem == this[i])

                 return i;

        }

        return -1;

    }

    //call

    var arr = new Array();

    arr.enqueue("aaa");

    arr.enqueue("bbb");

    arr.enqueue("ccc");

    arr.dequeue();

    alert(arr.indexOf("aaa"));

    Eg3.扩展Object

    Object.prototype.alert = function()

    {

        alert(this.valueOf());

    }

    //call

    var str=“hellow”;

    var iNum = 25;

    str.alert();

    iNum.alert();

    重定义已有方法

         Function.prototype.toString = function(){

                 return “”; }

         function sayHi(){

              alert(“hi”); }

    //call

    alert(sayHi.toString()); //output “”

     

  • 相关阅读:
    Timer定时任务
    spring boot配置多数据源
    消费者模块调用提供者集群报错
    修改windHost文件
    spring常用注解+Aop
    添加ClustrMaps
    无题
    2020年3月21日 ICPC训练联盟周赛,Benelux Algorithm Programming Contest 2019
    2020年3月14日 ICPC训练联盟周赛,Preliminaries for Benelux Algorithm Programming Contest 2019
    2020.4.12 个人rating赛 解题+补题报告
  • 原文地址:https://www.cnblogs.com/aqbyygyyga/p/2224942.html
Copyright © 2011-2022 走看看