原文地址:https://dojotoolkit.org/documentation/tutorials/1.10/declare/index.html
本翻譯項目放在GitBook上,歡迎參與。
GitBook地址:https://www.gitbook.com/book/limeng1900/dojo1-11-tutorials-translation-in-chinese/details
轉載請註明出處:http://blog.csdn.net/taijiedi13/ – 碎夢道
dojo/_base/declare
模塊是Dojo Toolkit裏類創建的基礎。declare
允許多重繼承來讓開發者編寫靈活的代碼並避免重複同樣的代碼。Dojo、 Dijit 和 Dojox 模塊都使用declare
;在本教程中,你將瞭解爲什麼你也要用它。
入門
確保你瞭解模塊教程中提出的概念。
Dojo的基礎類創建
declare
函數定義在dojo/_base/declare
模塊裏。declare
接收三個參數:className
、superClass
和properties
。
ClassName
className
參數表示要創建的類的名字,包括命名空間。命名的類放在全局作用域內。className
也可以通過命名空間表示繼承鏈。
命名類
// Create a new class named "mynamespace.MyClass"
declare("mynamespace.MyClass", null, {
// Custom properties and methods here
});
一個名叫mynamespace.MyClass
的類現在存在於應用的全局作用域。
如果用在Dojo解析器,應該只創建命名類。其他類應該忽略className
參數。
“匿名”類
// Create a scoped, anonymous class
var MyClass = declare(null, {
// Custom properties and methods here
});
MyClass
現在它給出的作用域的可用。
超類
超類的參數可以是null
、一個已有類或者一個已有類的數組。如果一個新類繼承自多個類,那麼列表中的第一個類將作爲基本原型,其餘的作爲“混合”。
無繼承類
var MyClass = declare(null, {
// Custom properties and methods here
});
null
意味着這個類沒有類來繼承。
單繼承的類
var MySubClass = declare(MyClass, {
// MySubClass now has all of MyClass's properties and methods
// These properties and methods override parent's
});
新的MySubClass
將繼承MyClass
的屬性和方法。一個父類的方法或屬性可以進行重寫,只要在第三個參數裏添加它的新定義的鍵值,隨後再細說。
多繼承的類
var MyMultiSubClass = declare([
MySubClass,
MyOtherClass,
MyMixinClass
],{
// MyMultiSubClass now has all of the properties and methods from:
// MySubClass, MyOtherClass, and MyMixinClass
});
一個類數組表示多繼承。屬性和方法從左到右繼承。數組的第一個類作爲基礎原型,隨後的類混入該類。
如果一個屬性或方法在多個被繼承的類裏指定過,則使用最後一個被繼承的該屬性或方法。
屬性和方法對象
declare
最後一個參數包含了類原型的方法和屬性。如果被繼承的類有同樣的屬性或方法,這個參數將會對同名的屬性和方法進行重寫。
自定義屬性和方法
// 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
return result;
}
});
示例:基類的創建和繼承
下面的代碼創建一個繼承自dijit/form/Button
的widget:
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
方法來深入瞭解Dojo類的創建。
構造器方法
constructor
方法是一個特殊的類方法。constructor
方法在類實例化時觸發,在新對象的作用域內執行。這就是說this
關鍵字引用該實例,而不是原始類。constructor
方法也接收任意數量實例指定的參數。
// Create a new class
var Twitter = declare(null, {
// The default username
username: "defaultUser",
// The constructor
constructor: function(args){
declare.safeMixin(this,args);
}
});
如下創建實例:
var myInstance = new Twitter();
該實例中的username在指定設置之前都將是“defaultUser”。利用safeMixin
方法提供一個username參數:
var myInstance = new Twitter({
username: "sitepen"
});
現在該實例將username設爲sitepen
。
declare.safeMixin
在類的創建和繼承中也很有用。如API文檔中:
這個函數用來像lang._mixin 一樣混入屬性,但是它跳過一個構造器屬性並且像dojo/_base/declare那樣修飾函數。就是說它用來和dojo/_base/declare進行類和對象的生成。和declare.safeMixin混合的函數可以想普通方法一樣使用this.inherited()。這個函數用來實現declare()產生的構造器的方法的extend()。
declare.safeMixin
是創建類是的好幫手。
繼承
如上所述,declare
第二個參數定義繼承。父類的屬性和方法從左到右混入類,如果屬性已定義後來的具有優先權。如下:
// 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
});
繼承類最後的屬性是:
// 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)設定默認值,並且需要的時候可以在實例中更新它們。然而,如果你在原型的屬性上指定一個對象值(Object、Array),每個實例都將操作這個共享的值。如下:
var MyClass = declare(null, {
primitiveVal: 5,
objectVal: [1, 2, 3]
});
var obj1 = new MyClass();
var obj2 = new MyClass();
// both return the same value from the prototype
obj1.primitiveVal === 5; // true
obj2.primitiveVal === 5; // true
// obj2 gets its own property (prototype remains unchanged)
obj2.primitiveVal = 10;
// obj1 still gets its value from the prototype
obj1.primitiveVal === 5; // true
obj2.primitiveVal === 10; // true
// both point to the array on the prototype,
// neither instance has its own array at this point
obj1.objectVal === obj2.objectVal; // true
// obj2 manipulates the prototype's array
obj2.objectVal.push(4);
// obj2's manipulation is reflected in obj1 since the array
// is shared by all instances from the prototype
obj1.objectVal.length === 4; // true
obj1.objectVal[3] === 4; // true
// only assignment of the property itself (not manipulation of object
// properties) creates an instance-specific property
obj2.objectVal = [];
obj1.objectVal === obj2.objectVal; // false
爲了避免無意地在實例之間共享數組或對象,對象屬性應該聲明爲空並在構造器函數裏進行初始化。
declare(null, {
// not strictly necessary, but good practice
// for readability to declare all properties
memberList: null,
roomMap: null,
constructor: function () {
// initializing these properties with values in the constructor
// ensures that they ready for use by other methods
// (and are not null or undefined)
this.memberList = [];
this.roomMap = {};
}
});
更多信息參考 dojo/_base/declare
this.inherited
完全重寫方法當然很有用,有時候每個類的構造器執行繼承鏈時需要保留其原始功能。這裏this.inherited(arguments)
就很方便。this.inherited(arguments)
調用父類的同名方法。如下:
// 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()
。即便如此,你不能在構造器裏調用它。
小結
declare
函數是創建模塊化和重用Dojo Toolkit 類的關鍵。declare
允許多重繼承和任意數量的屬性和方法來生成複雜類。更簡單的是declare
易於學習並且可以讓開發者避免重複代碼。
dojo/_base/declare資源
declare
和類創建的更多細節請查看一下資源: