Classy JavaScript with dojo/_base/declare

dojo/_base/declare模块是Dojo Toolkit中创建类的基础。declare允许使用多重继承为开发者创建灵活的代码,而且避免编写相同代码的过程。Dojo,Dijit和Dojox模块都使用declare。在这个教程你将知道为什么要使用它。


Getting Started

确保你复习了上一节的内容


Basic Dojo Class Creation with Dojo(创建基本的Dojo类)

declare 函数在dojo/_base/declare模块中定义。 declare 接受三个参数: className, superClass, and properties.


ClassName

className代表类的名字,而且包含命名空间。被命名的类被放置在全局范围内,className也可以通过命名空间代表类的继承链。


Named Class(命名类)

1
2
3
4
// Create a new class named "mynamespace.MyClass" 
declare( "mynamespace.MyClass" null , {
                  // Custom properties and methods here
              });

一个名为mynamespace.MyClass的类已经可以在程序的全局中使用了。


如果类是用于Dojo parser的,则必须给类命名。其他所有类应该忽略className参数。


"Anonymous" Class(匿名类)

1
2
3
4
5
6
// Create a scoped, anonymous class
var  MyClass = declare( null , {
                
     // Custom properties and methods here
                
});

MyClass现在可以在当前范围内使用。


SuperClass(es)(超类(或者多个))

superClass参数可以是null,单个存在的类或多个存在的类数组。如果一个新类继承多个类,第一个类将作为继承属性,其余的视为混入。


Class with No Inheritance(不继承的类)

1
2
3
4
5
var  MyClass = declare( null , {
               
     // Custom properties and methods here
               
});

null代表没有从其他类继承。


Class Inheriting from Another Class(从其他类继承的类)

1
2
3
4
var  MySubClass = declare(MyClass, {
               // MySubClass now has all of MyClass's properties and methods
     // These properties and methods override parent's
  });

新的MySubClass类将继承MyClass类的属性和方法。通过为daclare的第三个参数添加新的键值和定义将重写超类的属性或方法,我们马上解释它。


Class with Multiple Inheritance(多重继承的类)

1
2
3
4
5
6
7
8
9
10
var  MyMultiSubClass = declare([
     MySubClass,
     MyOtherClass,
     MyMixinClass
],{
              
     // MyMultiSubClass now has all of the properties and methods from:
     // MySubClass, MyOtherClass, and MyMixinClass
              
});

一个类的数组代表多重继承。属性和方法是从左到右继承的,数组的第一个类作为基础属性,其余类混入这个类中。


 如果多个超类都指定了一个同名的属性或方法,将使用最后的超类的属性或方法。


Properties and Methods Object(对象的属性和方法)

最后一个daclare的参数是一个包含属性和方法的对象,它作为类的原型。这个参数提供的属性和方法将重写超类中同名的属性或方法。


Custom Properties and Methods(自定义属性和方法)

1
2
3
4
5
6
7
8
9
10
11
// Class with custom properties and methods
var  MyClass = declare(MyParentClass, {
     // Any property
     myProperty1: 12,
     // Another
     myOtherProperty:  "Hello" ,
     // A method
     myMethod:  function (){
               // Perform any functionality here
               returnresult;
     } });


Example: Basic Class Creation and Inheritance(示例:基本的类创建和继承)

下面的代码创建了一个从dijit/form/Button继承的widget:

1
2
3
4
5
6
7
8
9
10
11
12
define([
     "dojo/_base/declare" ,
     "dijit/form/Button"
],  function (declare, Button){
     return  declare( "mynamespace.Button" , Button, {
         label:  "My Button"
         onClick:  function (evt){
             console.log( "I was clicked!" );
             this .inherited(arguments); 
         }
     });
});

从上面的片段我们可以推断:

  • 类名是mynamespace.Button。

  • 类可以使用全局的mynamespace.Button或模块的返回值来引用。

  • 它继承dijit/form/Button (和button的依赖项)。

  • 这个类定义了属性和方法。

让我们来学习constructor方法更深入挖掘类的创建。


The constructor Method(constructor方法)

特殊方法之一是constructor。constructor在类实例化后被触发,它在新对象中执行,这意味着this关键词引用的是实例而不是类。constructror方法接受任意数目的实例特定的参数。

// Create a new class
var Twitter = declare(null, {
	// The default username
	username: "defaultUser",

	// The constructor
	constructor: function(args){
		declare.safeMixin(this,args);
	}
});
 

实例化它:

1
var  myInstance = newTwitter();

因为没有指定实例的设置,username默认为"defaultUser"。为了利用safeMinxin方法,我们提供username参数。

1
2
3
var  myInstance =  new  Twitter({
      username:  "sitepen"
});

现在实例使用sitepen作为username的设置。


在创建和继承类中declare.safeMixin同样很有用。下面引用一段API文档的陈述:


 这个函数用来混合属性,有点像lang._mixin做的事,但是它读取一个constructor属性和装饰函数,又像dojo/_base/declare的工作。这意味着它是与类和dojo/_base/declare制造的对象一起使用的。一个函数混入了declare.safeMixin也可使用 this.inherited()函数就像普通函数一样。这个函数用于实现constructor的extend()方法。


Inheritance(继承)

如上所述,declare第二个参数是继承的定义。类是从左到右混入的,后面的类的方法和属性会覆盖前面的。做一个演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Define class A
var  A = declare( null , {
     // A few properties...
     propertyA:  "Yes" ,
     propertyB: 2
});
    
// Define class B
var  B = declare(A, {
     // A few properties...
     propertyA:  "Maybe" ,
     propertyB: 1,
     propertyC:  true
});
    
// Define class C
var  C = declare([mynamespace.A, mynamespace.B], {
     // A few properties...
     propertyA:  "No" ,
     propertyB: 99,
     propertyD:  false
});

继承类的属性结果是:

1
2
3
4
5
6
7
// Create an instance
var  instance =  new  C();
    
// instance.propertyA = "No" // overridden by B, then by C
// instance.propertyB = 99 // overridden by B, then by C
// instance.propertyC = true // kept from B
// instance.propertyD = false // created by C

number,string和boolean变量是可以直接设置和重定义的。注意当使用数组和对象在dojo/_base/declare中,确保它们的范围是正确的。数组和对象在return中定义将被所有实例对象共享使用。在constructor中定义是每个实例的属性。参考文档dojo/_base/declare获得额外的信息。


this.inherited

虽然重定义方法确实有用,但有时候每个类的构造函数通过继承链应该被执行保护其原始的功能。这就需要用到this.inherited(arguments)语句,它调用父类中同名的方法。考虑下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Define class A
var  A = declare( null , {
     myMethod:  function (){
         console.log( "Hello!" );
     }
});
    
// Define class B
var  B = declare(A, {
     myMethod:  function (){
         // Call A's myMethod
         this .inherited(arguments);  // arguments provided to A's myMethod
         console.log( "World!" );
     }
});
    
// Create an instance of B
var  myB =  new  B();
myB.myMethod();
    
    
// Would output:
//      Hello!
//      World!

 this.inherited方法可以在任何时候在子类中被调用。有时候你想去调用inherited()在子函数中间甚至在最后。也就是说,你不应该在constructor里调用它。


Conclusion(结论)

declare是创建模块化、可重用类的关键。declare允许创建多重继承的复杂类以及任意数量的属性和方法。更好的是declare容易学习,它将避免开发者重复代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值