針對 Java 開發人員的 Dojo 概念
聲明類並設定上下文 Dave Draper , WebSphere Application Server Administrative Console 開發人員, WSO2 Inc 在過去六年,Dave Draper 一直擔任 WebSphere Application Server Administrative Console 的開發。他是經過 Sun 認證的 Web Component 開發人員,在基於 Web 的工具開發方面具有豐富的經驗。
簡介: Dojo 在基於 Web 的應用程式中越來越受到歡迎。很多開發人員是 Java 編程方面的能手,但是在 JavaScript 方面卻缺乏經驗。從強型別、物件導向的編譯語言轉向動態、弱類型指令碼語言,開發人員需要經曆概念躍遷帶來的困難。這種混亂使開發人員很難正確地聲明 Dojo 類。本文將協助梳理這種混亂,解釋為何必須設定上下文,以及如何?它。 標記本文。
發布日期: 2008 年 11 月 03 日
層級: 中級
其他語言版本: 英文
訪問情況 860 次瀏覽
建議: 0 (添加評論 ) 平均分 (共 2 個評分 )
簡介
如果您是一名只有很少或根本沒有 JavaScript 經驗的開發人員,在接觸 Dojo 時可能需要掌握一些必要的概念。Dojo 的一個主要問題是(在撰寫本文之際),它仍然處於其嬰兒期(版本 1.0 在 2008 年 2 月份才發布),並且可用的文檔仍然非常有限。本文將協助您理解 Dojo 和 Java 代碼之間的聯絡,使您在開發應用程式時可以快速入手並掌握這個工具箱。
本文並沒有介紹如何獲得 Dojo 工具箱或一些必要的使用指令,因為已經有大量的資源提供了此類資訊。本文主要針對從 servlet 開發轉向 Dojo 的 Web 開發人員。 Ajax 資源中心
請訪問 Ajax 資源中心 ,這是有關 Ajax 編程模型資訊的一站式中心,包括很多文檔、教程、論壇、blog、wiki 和新聞。任何 Ajax 的新資訊都能在這裡找到。
JavaScript hash
需要面對的主要挑戰之一就是理解在調用 Dojo 函數時使用的文法,特別是 “hash” 或 JavaScript 對象。hash 被表示為使用逗號間隔的一組屬性,並且使用大括弧括起。清單 1 顯示了一個簡單的例子,它聲明了一個包含 6 個屬性的 hash:一個字串、一個整數、一個布爾值、一個未定義的屬性、另一個 hash 和一個函數。
清單 1. 樣本 JavaScript hash
var myHash = { str_attr : "foo", int_attr : 7, bool_attr : true, undefined_attr : null, hash_attr : {}, func_attr : function() {}}; |
注意,JavaScript 是弱類型的,因此儘管每個屬性被初始化為一個與其名稱相關的值,但仍然需要把str_attr 屬性設定為一個整數或布爾值(或其他任何類型)。使用 dot 操作符可以訪問或設定 hash 中的每個屬性(參見清單 2)。
清單 2. 訪問和設定 hash 屬性
// Accessing a hash attribute...console.log(myHash.str_attr);// Setting a hash attribute...myHash.str_attr = "bar"; |
myHash 的前四個屬性的含義不言自明。事實上,hash 可以擁有 hash 屬性,這並不奇怪。(可以將這看作類似於原語和對象的 Java 類)。這是需要理解的最後一個重要屬性。
函數和對象
儘管 Java 代碼中有一個 java.reflection.Method 類,但它實際上只充當方法的封裝器。在 JavaScript 中,該函數可以是任何可設定、引用和作為參數傳遞給其他函數的對象。通常,像在 Java 方法調用中聲明匿名 inner 類一樣,也需要在函數調用中聲明新函數。
Java 方法和 JavaScript 函數之間的另一個重要區別是 JavaScript 函數可以運行在不同的上下文中。在 Java 編程中,使用 this 關鍵字引用所使用類的當前執行個體。當在 JavaScript 函數中使用時,this 引用該函數啟動並執行上下文。如果沒有指定,函數將在定義它的閉包中運行。
在最簡單的情況下,閉包可以被看作是使用大括弧({} )包含的任意 JavaScript 代碼。JavaScript 檔案內部聲明的函數可以使用 this 訪問在檔案主體中聲明的任何變數,但是在 hash 內聲明的函數只能使用 this 引用在 hash 內部聲明的變數,除非提供其他上下文。
由於經常需要使用封閉的函數作為 Dojo 函數的參數,因此理解如何設定上下文將省去大量的調試工作。
用於指定內容相關的主要 Dojo 函數是 dojo.hitch 。您可能從不使用 dojo.hitch ,但必須瞭解它是 Dojo 的關鍵區段,很多函數都在內部調用它。
清單 3 展示了上下文串連的工作原理(其輸出顯示在圖 1 中): 在全域上下文(globalContextVariable )中定義一個變數,在一個 hash 上下文(enclosedVariable )中聲明另一個變數。 函數 accessGlobalContext() 可以成功訪問 globalContextVariable 並顯示其值。 但是,enclosedFunction() 只可以訪問其本地變數 enclosedVariable (注意globalContextVariable 的值顯示為 “未定義”)。 使用 dojo.hitch 將 enclosedFunction() 串連到全域上下文,這樣就可以顯示globalContextVariable (注意,enclosedVariable 現在為 “未定義”,因為它不是在運行 enclosedFunction() 的上下文中聲明的)。
清單 3. 閉包和上下文
var globalContextVariable = "foo";function accessGlobalContext() { // This will successfully output "foo"... console.log(this.globalContextVariable);};var myHash = { enclosedVariable : "bar", enclosedFunction : function() { // Display global context variable... console.log(this.globalContextVariable); // Display enclosed context variable... console.log(this.enclosedVariable); }};console.log("Calling accessGlobalContext()...");accessGlobalContext();console.log("Calling myHash.enclosedFunction()...");myHash.enclosedFunction();console.log("Switch the context using dojo.hitch...");var switchContext = dojo.hitch(this, myHash.enclosedFunction);switchContext(); |
圖 1. 上下文串連的工作原理
聲明類 聲明類的技巧 儘管 myClass 是一個有效名稱,但是最好使用完全限定類名的形式聲明名稱,例如com.ibm.dojo.myClass 。這並不表示應當把類部署到相對路徑 “./com/ibm/dojo/” 下的檔案系統;它只是減少了與其他類名衝突的幾率。 在最後一個屬性之後絕不會出現 , (逗號),因為一些瀏覽器將忽略它(FireFox),但是其他瀏覽器(Internet Explorer)會將它彈出。這條規則也適用於 hash 對象的聲明。
為什麼串連如此重要。您將在聲明 Dojo 類或建立自己的組件時體驗到它的重要性。Dojo 的一大功能就是能夠通過使用 dojo.connect 函數和內建的 pub/sub 模型將對象 “串連” 起來。
類的聲明需要三個對象: 一個惟一的類名 用於擴充函數的父類(以及類比多個繼承的 “混合” 類) 定義所有屬性和函數的 hash
清單 4 展示了最簡單的類聲明方式,清單 5 展示了該類的執行個體化。
清單 4. 基本的類聲明
dojo.declare( "myClass", null, {}); |
清單 5. 基本的類執行個體化
var myClassInstance = new myClass(); |
如果希望聲明一個 “真正的”(即有用的)Dojo 類,那麼一定要理解建構函式。在 Java 代碼中,您可以通過使用各種不同的簽名聲明多個重載的建構函式,從而支援執行個體化。在一個 Dojo 類中,可以聲明一個 preamble 、一個 constructor 和一個 postscript ,但是在大多數情況下,您只需要聲明一個建構函式。 除非混合使用了其他類來類比多個繼承,否則不需要用到 preamble ,因為它允許您在constructor 參數傳遞給擴充類和混合類之前對其進行處理。 postscript 產生了 Dojo 小組件生命週期方法,但對標準 Dojo 類沒有什麼用處。
不一定要全部都聲明,但是要將所有值傳遞到類的執行個體中,就必須將 constructor 函式宣告為 minimum。如果 constructor 參數將被該類的其他方法訪問,必須將它們賦值給已聲明的屬性。清單 6 展示了一個類,它只將其中一個 constructor 參數賦值給一個類屬性,並嘗試在另一個方法中引用它們。
清單 6. 賦值建構函式參數
dojo.declare( "myClass", null, { arg1 : "", constructor : function(arg1, arg2) { this.arg1 = arg1; }, myMethod : function() { console.log(this.arg1 + "," + this.arg2); } });var myClassInstance = new myClass("foo", "bar");myClassInstance.myMethod(); |
圖 2. 賦值建構函式參數的結果
複雜的屬性規則
類屬性可以在聲明時進行初始化,但是如果使用複雜物件類型(例如 hash 或數組)初始化屬性,該屬性將類似於 Java 類中的公用靜態變數。這意味著任何執行個體無論在何時更新它,修改將反映到所有其他執行個體中。為了避免這個問題,應當在建構函式中初始化複雜屬性;然而,對於字串、布爾值等簡單屬性則不需要這樣做。
清單 7. 全域類屬性
dojo.declare( "myClass", null, { globalComplexArg : { val : "foo" }, localComplexArg : null, constructor : function() { this.localComplexArg = { val:"bar" }; } });// Create instances of myClass A and B...var A = new myClass();var B = new myClass();// Output A's attributes...console.log("A's global val: " + A.globalComplexArg.val); console.log("A's local val: " + A.localComplexArg.val); // Update both of A's attributes...A.globalComplexArg.val = "updatedFoo";A.localComplexArg.val = "updatedBar";// Update B's attributes...console.log("A's global val: " + B.globalComplexArg.val);console.log("A's local val: " + B.localComplexArg.val); |
圖 3. 類屬性