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