• dojo中的类


    使用arcgis api for js 4.*进行地图的web前端开发,就不得不与dojo打交道。dojo是一个框架,自成体系,比如它对类的支持,有自己的一套。众所周知,js不是面向对象语言,没有类这一说,都是用函数来模拟类。

    那么dojo里的类是怎么样的呢?

    1、定义(声明)类

    用declare。

    declare(基类,类定义)
    
    • 1

    第一个参数是基类,单个基类或多个基类组成的数组,如果没有基类,则以null或空数组“[ ]”代替。比如下面:

    var A = declare(null, {
      constructor: function(name, age, residence){
        this.name = name;
        this.age = age;
        this.residence = residence;
      }
    });
    
    var a = new A("孙悟空",48000,"花果山水帘洞");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    类定义,总体上看是一个json。构造函数,各种方法,都是json元素。

    constructor,顾名思义,是构造函数。注意name、age、residence并没有声明,直接使用,作为实例的属性。这样不管new多少个A实例,实例之间的属性都不会互相影响。

    但我之前不懂,将变量声明在declare之外,new出来的实例,变量居然是共用的。看上去,变量放在declare外部,就相当于全局静态变量
    在这里插入图片描述
    注:图中的代码,是dojo比较老旧的版本,所以declare有三个参数。

    2、继承

    //员工类
    define(["dojo/_base/declare", "my/Person"], function(declare, Person){
      return declare(Person, {
        constructor: function(name, age, residence, salary){
          // The "constructor" method is special: the parent class (Person)
          // constructor is called automatically before this one.
    
          this.salary = salary;
        },
    
        askForRaise: function(){
          return this.salary * 0.02;
        }
      });
    });
    
    //领导类
    define(["dojo/_base/declare", 'my/Employee'], function(declare, Employee){
      return declare(Employee, {
        askForRaise: function(){
          return this.salary * 0.25;
        }
      });
    });
    
    //使用员工类和领导类
    require(["my/Employee", "my/Boss"], function(Employee, Boss){
      var kathryn = new Boss("Kathryn", 26, "Minnesota", 9000),
          matt    = new Employee("Matt", 33, "California", 1000);
    
      console.log(kathryn.askForRaise(), matt.askForRaise()); // 2250, 20
    });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    3、类的链式初始化

    就是创建dojo的类实例时,初始化默认是从最老的祖宗开始,一代接一代的依次初始化。

    require(["dojo/_base/declare"], function(declare){
      var A = declare(null, {
        constructor: function(){ console.log("A"); }
      });
    
      var B = declare(A, {
        constructor: function(){ console.log("B"); }
      });
    
      var C = declare(B, {
        constructor: function(){ console.log("C"); }
      });
    
      new C();
    });
    
    // prints:
    // A
    // B
    // C
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    如果想打断这种链式初始化,如:

    require(["dojo/_base/declare"], function(declare){
      var A = declare(null, {
        constructor: function(){
          console.log("A");
        }
      });
    
      var B = declare(A, {
        "-chains-": {//声明链式初始化为手动模式,其实就是打断了链式传播。好滑稽的方法
          constructor: "manual"
        },
        constructor: function(){
          console.log("B");
        }
      });
    
      var C = declare(B, {
        constructor: function(){
          console.log("C - 1");
          this.inherited(arguments);//显式调用父类初始化,爷爷或更老的祖宗就不必了
          console.log("C - 2");
        }
      });
    
      var x = new C();
    });
    
    // prints:
    // C - 1
    // B
    // C - 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    4、扩展类

    如果要扩展一个类,可以用 类.extend(扩展部分定义)。注意扩展部分是扩展,不是完全覆盖。只有重复部分才会被覆盖,原先没有的,则新增到类里。所谓有则改之,无则增加。类修改后,所有的实例都受到影响。

    extend返回扩展后的类。

    示例如下:

    require(["dojo/_base/declare"], function(declare){
      var A = declare(null, {
        m1: function(){
          // ...
        }
      });
    
      A.extend({
        m1: function(){
          // this method will replace the original method
          // ...
        },
    
        m2: function(){
          // ...
        }
      });
    
      var x = new A();
      a.m1();
      a.m2();
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    5、派生类

    多说无益,直接看代码

    require(["dojo/_base/declare"], function(declare){
      var A = declare(null, {
         m1: function(){},
         s1: "bar"
      });
      var B = declare(null, {
          m2: function(){},
          s2: "foo"
      });
      var C = declare(null, {});
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    对于上述代码,下面2种方法的效果是一样的:
    1)方式一

    var D1 = A.createSubclass([B, C], {
        m1: function(){},
        d1: 42
    });
    var d1 = new D1();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2)方式二

    var D1 = declare([A, B, C], {
        m1: function(){},
        d1: 42
    });
    var d1 = new D1();
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    其中方式一就使用了createSubclass。由A派生,同时继承B和C。等同于同时继承A、B、C。
    createSubclass有两个参数,参数一为基类,参数二为注入新类的定义。所谓注入,即有则改之,无则增加,参考 4、扩展类。

    createSubclass与extend的区别,在于extend只是对现有类进行扩展,而createSubclass是继承并派生出一个新类。

    6、调用父类方法

    inherited()

    这个方法十分令人费解。它最多有三个参数。

    第一个参数是方法名,可选。不指定,调用的是父类的当前方法的同名方法(?)

    第二个参数是arguments,是个伪变量,不用声明。据说用于“内省(introspection)”,不知道是什么意思。反正名字不能改把它当作保留字看待。

    第三个参数是传递的参数,如果没有指定,第二个参数arguments就发挥作用。但如果为[“true”],则返回父类方法的定义,而不执行。

    如果没有父类方法,则返回undefined。

    require(["dojo/_base/lang", "dojo/_base/declare"], function(lang, declare){
      var A = declare(null, {
        m1: function(){
          // ...
        },
        m2: function(){
          // ...
        },
        m3: function(){
          // ...
        },
        m4: function(){
          // ...
        },
        m5: function(){
          // ...
        }
      });
    
      var B = declare(A, {
        m1: function(){
          // simple super call with the same arguments
          this.inherited(arguments);
          // super call with new arguments
          this.inherited(arguments, [1, 2, 3]);
        }
      });
    
      // extend B using extend()
      B.extend({
        m2: function(){
          // this method is going to be properly annotated =>
          // we can use the same form of this.inherited() as
          // normal methods:
          // simple super call with the same arguments
          this.inherited(arguments);
          // super call with new arguments
          this.inherited(arguments, ["a"]);
        }
      });
    
      // extend B using lang.extend()
      lang.extend(B, {
        m3: function(){
          // this method is not annotated =>
          // we should supply its name when calling
          // a superclass:
          // simple super call with the same arguments
          this.inherited("m3", arguments);
          // super call with new arguments
          this.inherited("m3", arguments, ["a"]);
        }
      });
    
      // let's create an instance
      var x = new B();
      x.m1();
      x.m2();
      x.m3();
      x.m4(); // A.m4() is called
      x.m5(); // A.m5() is called
    
      // add a method on the fly using declare.safeMixin()
      declare.safeMixin(x, {
        m4: function(){
          // this method is going to be properly annotated =>
          // we can use the same form of this.inherited() as
          // normal methods:
          // simple super call with the same arguments
          this.inherited(arguments);
          // super call with new arguments
          this.inherited(arguments, ["a"]);
        }
      });
    
      // add a method on the fly
      x.m5 = function(){
        // this method is not annotated =>
        // we should supply its name when calling
        // a superclass:
        // simple super call with the same arguments
        this.inherited("m5", arguments);
        // super call with new arguments
        this.inherited("m5", arguments, ["a"]);
      };
    
      x.m4(); // our instance-specific method is called
      x.m5(); // our instance-specific method is called
    });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90

    7、在arcgis api for js中的应用

    示例

    define([
      "dojo/_base/declare",
      "esri/geometry/support/webMercatorUtils",
      "./WebGlLayer",
    ], function (declare, webMercatorUtils, WebGlLayer) {
      return declare(null, {
        constructor: function (mapView) {
          this.core = new Core(mapView);
        },
        draw: function (data, options) {
          this.core.load(data, options);
        },
        clear: function () {
          this.core.clear();
        },
      });
    
      function Core(mapView) {
      	。。。
      }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    以上仅为dojo类定义及操作的部分内容。dojo只是一个框架,对类的定义和实现自成一家,有些地方十分有趣。因为前端要用到arcgis api for js,依赖dojo,了解即可,不作深究。dojo有关类的完整阐述,见参考文章。

    参考文章:
    https://dojotoolkit.org/reference-guide/1.9/dojo/_base/declare.html

  • 相关阅读:
    单细胞测序实践
    NLP中基于Bert的数据预处理
    基础算法(二)#蓝桥杯
    java基础之你所不知道的字符串
    35【源码】数据可视化:基于 Echarts + Python 动态实时大屏 - 门店销售业绩数据中心
    Linux多线程
    C++ 基础入门
    Java基础:Java程序设计环境
    Java8的SerializedLambda详解
    Spring实战之bean重复、指定bean的名字、消除bean的歧义性
  • 原文地址:https://blog.csdn.net/leftfist/article/details/128164252