(71)聲明一個類declare
作用:
封裝一個類,然后可以通過調用這個類,來調用其類方法。
優點:
①可以繼承其他類的類方法;
②假如我們需要使用一個類的類方法,而這個類依賴於5個插件。如果正常調用的話,我們需要在每個使用這個類的js文件里,調用這5個插件。當我們使用封裝時,我們只需要調用這個類即可。而調用這個類的方法很簡單。
③可以使得代碼模塊化,按需加載。例如,我有封裝好的A類B類C類,起初我用的是A類(假設A類依賴於20個插件),然后我可能棄用A類改用B類(B類使用與A類不同的15個插件)和C類(C類使用另外10個插件)。
在之前的情況下,我們需要刪除A類(包括其依賴的插件比如dojo/dom),然后依次刪除其類方法(還要小心沒有刪錯,或者少刪了什么東西)。當刪除完之后,依次加入B類和C類的插件、參數、方法等。灰常麻煩,而且容易搞錯。
使用封裝的類后,我們只需要提前寫好B類和C類,然后在js里導入B類和C類(像導入插件那樣導入),在回調函數的參數中,加上B類和C類的參數。然后聲明一個B類的實例和一個C類的實例,通過這個實例來調用B類和C類的方法即可。
(如果不太明白,建議先去看看我的博客:
http://blog.csdn.NET/qq20004604/article/details/51388185
搜索關鍵字:構造函數)
如果還不太明白,可以這么理解,我聲明了一個對象A,這個對象A有一個方法add,其效果是給2個參數,返回他們的和。
var fun = function () { this.add = function (num1, num2) { //構造函數的方法 return num1 + num2; } } var p = new fun(); //聲明一個實例 console.log(p.add(2, 3)); //調用這個實例,返回值,並輸出
返回值是5
聲明一個類,就類似fun這個變量,
使用這個類,就是new fun()生成一個實例
調用這個類方法,就是p.add(2,3)這樣調用它。
如果還不明白?!那先看下去,然后把代碼拿過來用用,再改改就知道了。
如何聲明一個類:
require(["dojo/_base/declare"], function (declare) { declare("aClass", null, { /* constructor:function(){ 構造函數是聲明一個實例時使用,我們這里並沒有使用它,所以注釋掉 },*/ add: function (num1, num2) { //類方法 return num1 + num2; } //注意!!類結尾的方法之后不能有逗號 }) var m = new aClass(); console.log(m.add(3, 3)); })
這是非常簡單的一個封裝類,我沒有為她創建一個構造函數,也只給他設置了一個方法add(這些都是在declare第三個參數中)。他的類名是aClass(第一個參數),沒有繼承任何類(declare第二個參數null)。
在聲明他之后,我創建了一個他的實例m,然后最后通過m調用add這個方法。
這里是在同文件聲明,我們聲明類的目的,是為了在另外一個文件中使用它,這樣才能起到封裝的作用(調用類,並使用其提供的API接口)。
那么如何在另一個文件中聲明並調用一個類呢?(封裝類)
如何封裝類:
同樣是上面那個方法。
①首先,我們找到dojo文件夾,就是有dojo、dijit這兩個文件夾的位置,在它旁邊創建一個myclass文件夾。
②然后在其中創建一個add.js這個文件,記住這個文件名(還有myclass文件夾的名字)
③打開那個js文件,把以下這段代碼放進去:
define(["dojo/_base/declare"], function (declare) { return declare("aClass", null, { /* constructor:function(){ 構造函數是聲明一個實例時使用,我們這里並沒有使用它,所以注釋掉 },*/ add: function (num1, num2) { //類方法 return num1 + num2; } }) })
④打開你的html文件,引用dojo.js,我給個例子吧:
<script>var dojoConfig={async:true}</script> <script src="dojo/dojo.js"></script>
其中第一段代碼的意思是表示異步執行,很重要,不能缺。不懂的話就別管他,記得加上就行,而且要放在加載dojo之前。(不然會出錯)
⑤調用這個封裝的類:
require(["myclass/add"], function (myclass) { var m = new myclass(); console.log(m.add(3, 3)); })
還記得上面自定義的路徑么,參數就是路徑(myclass文件夾,add.js文件),然后在回調函數里加上參數(指我們定義的這個類)。
通過第二行代碼,生成這個類的實例m;
第三行代碼,調用其方法add。
刷新頁面,會在console控制台輸出6。
解釋:
①在當前文件調用一個類,使用require;
在一個新的文件聲明類,需要使用define。
二者區別在於,require是請求(請求一個聲明好的),define是定義(定義一個新的)。
我們在當前文件調用類時,並不是我們自己聲明的(當前文件聲明不需要使用require或者define),因此我們需要請求(這個請求是dojo幫我們完成的);
那么我們需要自己定義一個類,用於給其他人請求時使用,那么就必須用define。dojo在看到define的時候,就知道我們這里是定義了一個類了。
②在自定義的add.js文件的第二行代碼中,有一個return。
這里的return,實時上是return的是一個函數(可以理解為上面所說的js的構造函數),這個構造函數里有一些類方法和變量(當然我們這里只有一個add方法)。
return的這個函數跑哪里去了呢?很簡單,就是我們調用它時,回調函數里的那個參數。(注意,參數不需要和類名相同,因為調用時這個參數一般就不重要了——應該吧)。
因為有了這個參數,所以我們才能通過new myclass()來獲得這個類的實例。因為他實質上就像這樣
var fun = function () {//fun右邊的函數,可以理解為那個被return的函數 this.add = function (num1, num2) {
return num1 + num2; } } var p = new fun(); //聲明一個實例
③我們可以在add.js里,像我們正常使用dojo那樣,引用很多個插件,然后依次在回調函數里給插件對應的參數。
然后聲明一些類方法,在類方法里寫我們需要的功能(即API接口)。
也可以聲明一些變量,並在類方法中調用它。
也可以使用構造函數,做一些聲明該類實例時就做的事情。
還可以繼承(當然這里就略了,下次說)
就像這樣:
define(["dojo/_base/declare"], function (declare) { return declare("aClass", null, { mynum: 10, //聲明一個變量(在這個類里是全局的) constructor: function (num) { //這個是構造函數,聲明類的實例時,傳的參數在這里 console.log(num); //我們讓聲明實例時,輸出他傳的參數 }, add: function (num1) { //類方法,調用類方法時,返回值是參數+10 return this.mynum + num1; //必須加this.mynum才能調用類內置的變量 }, getMynum: function () { //返回類內部的變量 return this.mynum; }, mynumAdd:function(){ this.mynum++; return this.mynum; } }) })
方法很簡單,就不詳細解釋了。
然后調用它。
require(["myclass/add"], function (myclass) { var m = new myclass(1); console.log(m.add(3)); console.log(m.getMynum()); console.log(m.mynumAdd()); var n = new myclass(1); console.log(n.getMynum()); })
輸出結果是:
1
13
10
11
1
10
我們會發現:
①不同的實例,並不會共享類內的變量。
②類內聲明的變量,類外是無法直接訪問的:
console.log(mynum);
報錯,提示undefined
另外:
①假如在html文件里引用了jQuery庫(或者其他庫),然后又在html里引用了這個類,那么是可以直接在add.js里調用jquery的方法的(並不需要在add.js里引用jquery庫);當然,如果html里沒引用jquery庫的話,是會報錯的。