JavaScript和Java雖然在語法上有些相近,但其實是差別很大的兩種編程語言!
Dorado是全新的事物,也必然會帶來很多全新的使用方法和最佳實踐。當然,最佳實踐這種東西原本是需要一些時間和應用來積累和驗證的,在目前階段我只能根據(jù)個人的經(jīng)驗來大體總結(jié)出一些開發(fā)建議。 本文列舉了一些我近期在各項目中看到的不夠好的JavaScript代碼,既有關(guān)于JavaScript本身的,也有關(guān)于Dorado的。
JavaScript不是Java!JavaScript是弱類型語言!所有類型的數(shù)值都可以用于邏輯判斷和邏輯運算。 所以要搞清楚String、Number、Boolean、Object這些類型在用于邏輯判斷時都會出現(xiàn)什么樣的結(jié)果。 例如不要編寫如下這么啰嗦的代碼來判斷一個字符串是否有效:
if (str != null && str != "") {
... ...
}
你完全可以這樣寫:
if (str) {
... ...
}
也可以進行邏輯運算:
if (!str) {
... ...
}
其他類型的變量同樣如此。
Dorado對象的get和set方法提供了很多實用的小技巧,善用這些技巧可以事半功倍。并且以下的這些技巧可以自由的搭配使用,以便于讓get和set在各種復雜的場景中發(fā)揮出最大的功效。 使用批量set 當需要對一個對象的多個屬性進行連續(xù)的賦值時,應盡可能使下面的語法:
foo.set({
readOnly: true,
value: "dorado"
})
而下面這種等效的寫法是不被推薦的,既羅嗦又低效。
foo.set("readOnly", true);
foo.set("value", "dorado");
使用迭代式的get和set get和set方法都支持迭代式的屬性訪問,即通過"."來分割一組屬性名,交由此方法一層層向下挖掘并返回最終結(jié)果或設置目標屬性。 當進行迭代式的讀取時,系統(tǒng)會自動判斷前一個屬性返回的對象是dorado.AttributeSupport的實例還是普通JSON對象,并藉此決定如何進一步執(zhí)行讀取操作:
oop.get("address.postCode"); // 迭代式的屬性讀取
// 如果address的屬性值是一個dorado.AttributeSupport的實例,那么此行命令的效果相當于oop.get("address").get("postCode")。
// 如果address的屬性值是一個JSON對象,那么此行命令的效果相當于oop.get("address").postCode
oop.set("address.postCode", 54733226); // 迭代式的屬性賦值
// 相當于oop.get("address").set("postCode",54733226) 或oop.get("address").postCode = 54733226
運用某些對象為get方法提供的特殊擴展 Dorado中的某些對象為get方法提供了特殊的擴展,通過這些擴展我們甚至可以訪問一些對象的Attribute之外的功能,這寫擴展進一步Dorado的開發(fā)體驗。 View
DataType
DataSet
// 首先獲得id為editorType的控件,然后返回其value屬性。
var value = view.get("#editorType.value");
// 首先獲得View中擁有advanceButton標簽的所有對象,然后批量設置它們的disabled屬性。
view.set("^advanceButton.disabled", true);
// 首先獲得id為dataSetDepts的DataSet,然后返回其中"#.employees"代表的數(shù)據(jù)。
var employees = view.get("#dataSetDepts.data:#.employees");
利用set為對象綁定事件 set方法不但可以用于為對象的屬性賦值,同時也可以用于為對象中的事件添加事件監(jiān)聽器。
// 使用上文中提及的第一種方法為label屬性賦值,同時為onClick事件綁定一個監(jiān)聽器。
oop.set({
label : "Sample Text",
onClick : function(self, arg) {
... ...
}
});
通過設置tag屬性以便于批量的查找和操作一組控件或?qū)ο螅@是Dorado中非常有特色的一種功能。該功能可以在很多場景下極大的簡化代碼。 在利用tag查找對象時Dorado會將所有匹配的對象封裝成一個ObjectGroup并返回。通過ObjectGroup,我們可以對其中的所有對象進行批量的屬性設置或方法調(diào)用。 在使用tag功能時,建議利用View對象對get和set方法所作的"^"前綴擴展,這可以讓代碼進一步的得到簡化。
// 首先獲得View中擁有advanceButton標簽的所有對象,然后批量設置它們的disabled屬性。
view.set("^advanceButton.disabled", true);
我在很多系統(tǒng)都見到過在頁面初始化階段執(zhí)行一到多次的dataSet.flush(),其實這些操作理論上都是可以避免的。 出現(xiàn)此類操作的主要原因是開發(fā)人員在頁面初始化階段通過JavaScript確定DataSet的parameter屬性的值,然后再利用dataSet.flush()從服務端提取相應的數(shù)據(jù)。而這里所說的parameter在很多情況下是可以在服務端的頁面準備階段直接獲得的。例如通過在DataSet的parameter屬性中填寫EL表達式的方式。
假設你需要根據(jù)外部條件來設置界面上的10個TextEditor的readOnly屬性,并且這種操作是一次性的,不會在用戶的操作過程中再次改變。那么利用控件的tag屬性在View的onReady事件中設置并不是最好的選項。這會讓代碼的可讀性變得稍差,更重要的是這會讓這10個控件在初始階段經(jīng)歷兩次刷新,對性能造成不顯著的損害。 對于這種情況,我們應該考慮直接在服務端設定好這些readOnly屬性。例如直接在這10個?控件的readOnly屬性中編寫 ${req.operation=="edit"} 這樣的EL表達式??墒且坏┪磥泶颂幍呐袛噙壿嬅媾R調(diào)整,你又必須再一次把這10個TextEditor全部找出來并一一調(diào)整其中的EL表達式。 為了避免這種尷尬,最好的辦法是在View中聲明一個Argument,將上面的EL表達式定義在這里并且讓10個TextEditor的readOnly屬性引用該Argument。例如:我們聲明一個名為為readOnly的Argument的,其值為 ${req.operation=="edit"},然后在TextEditor的readOnly屬性中通過 ${argument.readOnly}來引用它。
Dorado中的很多對象都支持each迭代,each迭代可以另代碼看起來更加簡潔明了。目前支持each迭代的對象包括:
var s = '';
['A', 'B', 'C'].each(function(item) {
s += item;
});
// s == "ABC"
JavaScript是解釋執(zhí)行的語言,這一點不同與于Java,所以其對代碼注釋的處理也有所不同。在Java中,被注釋掉的代碼不會在運行時產(chǎn)生影響。而在JavaScript中,被注釋掉的代碼仍然會被輸出到客戶端。這意味這著這些注釋仍然會產(chǎn)生網(wǎng)絡開銷。 在實際應用的場景中,我甚至見到過很多Client端事件中除了大段的代碼注釋外沒有任何一行有效代碼的情況。這意味著Dorado仍會為這些注釋生成一個無用的事件監(jiān)聽器。 所以,對于那些已經(jīng)不再需要的代碼,請果斷刪除而不是使用注釋。你可能會覺得的這些代碼未來或還會用的到,但實際的情況是,99%的情況下你再也不會用到他們了,而且一個小時你就會把這些注釋忘到一干二凈。
編程就像寫作。要把一件事情講清楚,你既可以寫一篇流水帳也可以寫一篇文章,要怎樣做取決于你對待這件事情的態(tài)度。 這原本不應該是本文應該討論的話題,然而我在日常的工作中卻見到了太多類似下面這樣的糟糕代碼:
var sum = this.id("dataSet").get("#.price") * this.id("dataSet").get("#.num");
this.id("dataSet").get("#").set("sum", sum);
... ... ...
if (this.id("checkboxDetail").get("checked") == true) {
this.id("textEditorHomePage").set("visible", true);
this.id("textEditorEmail").set("visible", true);
this.id("textEditorDesc").set("visible", true);
}
else {
this.id("textEditorHomePage").set("visible", false);
this.id("textEditorEmail").set("visible", false);
this.id("textEditorDesc").set("visible", false);
}
如果以寫作水平的角度來評價這段代碼,大概還處在小學二年級水平。而實際的情況往往比這例子中的更加令人作嘔(幸虧瀏覽器不會吐)!代碼里充斥著無用的注釋片段、沒有基本的縮進格式、定義之后又被廢棄的變量...... 我相信寫出類似水準代碼的同事是知道好的代碼應該是什么樣子的,之所以仍然會寫出這些丑陋的代碼,關(guān)鍵還在于態(tài)度。
更多建議: