• 《JS权威指南学习总结--9.3 JS中JAVA式的类继承》


    内容要点:

    一.JS中的类

        1.JAVA或其他类似强类型 面向对象语言的 类成员的模样

           实例字段:它们是基于实例的属性或变量,用以保存独立对象的状态。

           实例方法: 它们是类的所有实例所共享的方法,由每个独立的实例调用

           类字段:这些属性或变量是属于类的,而不是属于类的某个实例的。

           类方法:这些方法是属于类的,而不是属于类的某个实例的

         2.JS中的类牵扯三种不同的对象,三种对象的属性的行为和下面三种类成员非常相似:

            构造函数对象:

                 之前提到,构造函数(对象)为JS的类定义了名字。任何添加到这个构造函数对象中的属性都是类字符和类方法(如果属性值是函数的话就是类方法)。

            原型对象:

                 原型对象的属性被类的所有实例所继承,如果原型对象的属性值是函数的话,这个函数就作为 类的实例的方法 来调用

            实例对象:

                类的每个实例都是一个独立的对象,直接给这个实例定义的属性是不会为所有实例对象所共享的。定义在实例上的非函数属性,实际上是实例的字段。

         3.JS中定义类的步骤可以缩减为一个分三步算法。

               第一步,先定义一个构造函数,并设置初始化新对象的实例属性。

               第二步,给构造函数的prototype对象定义实例的方法。

               第三步,给构造函数定义类字段和类属性。

            我们可以将这三个步骤封装进一个简单的defineClass()函数中(这里用到了例6-2中的extend()函数和例8-3中的改进版)

              //一个用以定义简单类的函数

               function defineClass(constructor,  //用以设置实例的属性的函数

                                             methods, //实例的方法,复制至原型中

                                             static)   //类属性,复制至构造函数中

                                            {

                                            if (methods) extend( constructor,prototype,methods );

                                            if (statics) extend( constructor,statics );

                                             return constructor;

                                             }

                   //这是Range类的另一个实现

                        var SimpleRange = defineClass(function(f,t){ this.f=f;this.t=t; },

                                                                     {

                                                                         includes:function(x){ return this.f <=x && x<=this.t;}

                                                                         toString:function(){ return this.f + "..." +this.t; }

                                                                      },

                                                                      {

                                                                          upto:function(t){ return new SimpleRange(o,t); }});

    二.例9-3 Complex.js : 表示复数的类

          /*Complex.js : 这个文件定义了Complex类,用来描述复数。回忆一下,复数是实数和虚数的和,并且虚数i是-1的平方根*/                         

          /*这个构造函数为它所创建的每个实例定义了实例字段r和i,这两个字段分别保存复数的实部和虚部,它们是对象的状态*/

           function Complex(real,imaginary){

             if(isNaN(real) || isNaN(imaginary)) throw new TypeError();   //确保两个实参都是数字,如果不都是数字则抛出错误

             this.r = real; //复数的实部

             this.i = imaginary; //复数的虚部

           }

           /*类的实例方法 定义为原型对象的函数值属性,这里定义的方法可以被所有实例继承,并为它们提供共享的行为。需要注意的是,JS类额实例方法必须使用关键字this来存取实例的字段。*/

           //当前复数对象加上另一个对象,并返回一个新的计算和值后的复数对象

           Complex.prototype.add = function(that){ return new Complex(this.r + that.r , this.i + that.i); };

            //当前复数乘以另一个复数,并返回一个新的计算乘积之后的复数对象

            Complex.prototype.mul = function(that){ return new Complex(this.r * that.r - this.i*that.i , this.r*that.i + this.i*that.r); };

            //计算复数的模,复数的模定义为原点(0 , 0)到复平面的距离

            Complex.prototype.mag = function(){ return new Complex(this.r * this.r + this.i * this.i); };

            //复数的求负运算

            Complex.prototype.neg = function(){ return new Complex(-this.r , -this.i); };

           //将复数对象转换为一个字符串

             Complex.prototype.toString = function(){ return "{" +this.r + "," +this.i + "}"; };

           //检测当前复数对象是否和另外一个复数值相等

             Complex.prototype.equals = function(that){ return that !=null &&          //必须有定义且不能是null

                                                                             that.constructor === Complex &&     //并且必须是Complex的实例,

                                                                             this.r === that.r && this.i === that.i; //并且必须包含相同的值

                                                                           };

             /*类字段(比如常量)和类方法 直接定义为构造函数的属性。需要注意的是,类的方法通常不使用关键字this,它们只对其参数进行操作*/

             //这里预定义了一些对复数运算有帮助的类字段,它们的命名全都是大写,用以表明它们是常量(在ES5中,还能设置这些类字段的属性为只读)

             Complex.ZERO = new Complex(0,0);

             Complex.ONE = new Complex(1,0);

             Complex.I = new Complex(0,1);

             //这个类方法将由实例对象的toString方法返回的字符串格式解析为一个Complex对象,或者抛出一个类型错误异常

             Complex.parse = function(s){

                   try{     //假设解析成功

                      var m = Complex._format.exec(s); //利用正则表达式进行匹配

                       return new Complex(parseFloat(m[1]),parseFloat(m[2]));

                   }catch(x){      //如果解析失败则抛出异常

                         throw new TypeError("Can't parse ' " + s + " ' as a complex number.");

                              }

                   };

               //定义类的"私有字段",这个字段在Complex.parse()中用到了下划线前缀表明它是类内部使用的,而不属于类的公有API的部分

                Complex._format = /^{(^,]+),([^}]+)}$/;

         代码分析:

         从例9-3中所定义的Complex类可以看出,我们用到了构造函数、实例字段、实例方法、类字段和类方法,看一下这段实例代码:

           var c = new Complex(2,3); //使用构造函数创建新的对象

           var d = new Complex(c.i , c.r); //用到了c的实例属性

           c.add(d).toString(); //=>"{5,5}":使用了实例的方法

          //这个稍微复杂的表达式用到了类方法和类字段

             Complex.parse(c.toString()).         //将c转换为字符串

                                  add(c.neg()).          //加上它的负数

                                  equals(Complex.ZERO)  //结果应当永远是“零”

  • 相关阅读:
    三列自适应等高且中列宽度自适
    两列高度自适应(转)
    Transform 1
    跟我一起透彻理解template模板模式
    走进C++程序世界-----operator new delete 重载
    linux下maven的安装
    JavaScript权威指南第01章 JavaScript 概述
    切勿辜负青春一场
    C++ 模板应用 实现一个Queue 队列
    从头认识java-14.4 Java提供的数组的有用功能(2)
  • 原文地址:https://www.cnblogs.com/hanxuming/p/5846372.html
Copyright © 2020-2023  润新知