天天看點

Javascript 初學者應知的 24 條最佳實踐

JavaScript 使用兩種相等性操作符:<code>===</code>,<code>!==</code>和<code>==</code>,<code>!=</code>。通常認為做比較的最佳實踐是使用前一組操作符。

"若兩個操作數的類型和值相同,那麼<code>===</code>比較的結果為真,<code>!==</code>比較的結果為假。" --- JavaScript語言精粹(JavaScript: The Good Parts)

然而,如果使用<code>==</code>和<code>!=</code>,當比較不同類型的操作數時,你就會碰到問題啦。在這種情況下,這組操作符會嘗試對操作數的值做無用的強制轉換。

對于那些不熟悉JavaScript的人來說,函數"evel"讓我們能夠通路JavaScript編譯器。我們可以通過給"eval"傳遞一個字元串參數來得到該字元串執行的結果。

這不僅會極大地降低你的腳本的性能,也會造成一個巨大的安全隐患,因為這賦予傳遞進來的純文字太多的能力。要盡可能地避免eval函數的使用。

技術上來說,你确實可能僥幸地省略多數花括号和分号。大多數浏覽器都能夠正确地解釋如下代碼片段:

然而,再考慮一下這段代碼:

可能會有人認為上一段代碼等價于:

很不幸,他錯了。事實上,它的本意是:

你應該也注意到了,代碼中縮進模仿了花括号的功能。毋庸置疑,這是非常恐怖的做法,無論如何都應該避免。唯一可以省略花括号的時候是在一行式的語句中,但即使這種情況,也是很有争議的。

始終要想着以後

如果以後的某個時候,你需要在這種if語句中增加更多的指令,那該怎麼辦呢?沒法子,你就隻能重寫這塊代碼了。處理這個問題的底線是對于省略寫法保持謹慎。

&gt;

"JSLint擷取一份JavaScript源碼,然後掃描代碼。如果發現問題,就會傳回一條資訊描述這個問題以及這個問題在源碼中的大緻位置。問題雖然經常是文法錯誤,卻不一定是。JSLint也會檢視一些風格習慣以及結構問題。它并不證明你的代碼是否正确,隻是提供另外的一雙眼睛來幫助發現問題。"---JSLint文檔

在結束腳本代碼的編寫之前,對其執行一次JSLint,能夠保證你不會犯一些愚蠢的錯誤。

這條技巧在本系列前面的文章中也推薦過。因為它在此處也非常合适(As it's highly appropriate though),所有我将那段資訊直接粘貼在這裡。

記住---這條最佳實踐的主要目标是盡可能快速地為使用者加載頁面。當加載一個腳本時,浏覽器直到整個腳本檔案全部加載完畢才能繼續。是以,使用者必須等上更長的時間才能注意到任何的進度。

如果JS檔案的目的僅僅是增加功能---例如,在點選某個按鈕後---那麼就将那些檔案放在底部,body結束标簽之前吧。這絕對是一個最佳實踐。

更好的做法

當執行一個冗長的"for"語句之時,僅僅讓解釋引擎做必須幹的活吧。例如:

糟糕的做法

注意上面代碼片段中的每次疊代都需要檢查數組的長度,并且每次都要周遊DOM樹找到"container"元素---效率多低啊!

感謝有位朋友留下評論展示如何進一步優化上面的代碼塊。

當需要周遊一個數組或者對象之時,不要總是使用你能信手粘來的"for"語句。創造性地找個能夠完成工作的最快速的方案。

"我不會以測試基準來煩你;你隻須相信我(或者自己去測試一下)---這是目前為止最快的方式!" 使用原生方法(比如join()),不用管抽象層面背後發生了什麼,通常會比任何非原生方法快得多。 --- James Padolsey, james.padolsey.com"
"通過将全局的東西封裝進單個命名空間,能夠大大降低與其他應用、部件、代碼庫互動混亂的機率。"--- Douglas Crockford

注意我們是怎樣将全局性的“足迹”減少為一個命名可笑的"DudeNameSpace"對象的。

一開始看起來似乎沒有必要,但請相信我,你将會想盡可能好地注釋你的代碼。當你幾個月後再次回到項目,會發生什麼呢?發現你根本沒法輕松地記起當初對每一行代碼的想法。或者,如果你的某個同僚需要修改你的代碼,那又會怎麼樣呢?始終,一直記着注釋你代碼的重要部分吧。

始終考慮到如何處理JavaScript禁用的情況。也許你會想“大多數我網頁的閱讀器都是啟用JavaScript的,是以我不擔心這個問題。”然而,這會是一個巨大的錯誤。

考慮一下如下代碼:

這段代碼不僅低效,而且其行為與"eval"函數相同。永遠不要傳給字元串給SetInterval和SetTimeOut。相反,應傳遞一個函數名。

乍一看,"With"語句似乎是個聰明的想法。基本概念是它們能夠為通路深度嵌套對象提供一種簡寫方式。例如...

取代如下寫法

很不幸,經過一些測試,會發現這種簡寫在設定新成員時表現非常糟糕。作為替代,你應該使用var。

JavaScript中有多種建立對象的方式。也許更傳統的方式是使用"new"構造器,像這樣:

然而,這種方式因其行為并不是我們所想的那樣而被認為是“糟糕的實踐。相反,我推薦你使用更健壯的對象字面方法。

更好的寫法

注意如果你隻是想簡單地建立個空對象,{}就派上用場了。

"對象字面量使我們能夠編寫支援很多特性的代碼,并對代碼的實作者來說代碼仍然相對直覺。不需要直接調用構造器或維護傳遞給函數的參數的正确順序,等等。" --- dyn-web.com

這同樣适用于建立一個新數組。

過得去的寫法

"JavaScript中一個常見的錯誤是需要數組時使用對象或需要對象時使用數組。規則很簡單:當屬性名是小的連續整數時,你應該使用數組。否則,使用對象"---Douglas Crockford

相當的不言自明。我不知道這裡是否有任何真正的速度提升,但是它使你的代碼更加簡潔了。

技術上來說,大多數浏覽器都允許你的省略一些分号。

話雖如此,但這是一種非常糟糕的做法,可能導緻更大的問題,問題查找起來也更困難。

周遊對象内的成員時,你也會得到方法函數。為了解決這個問題,應始終将你的代碼包裝在一個if語句中來過濾資訊。

引自JavaScript: 語言精粹, Douglas Crockford著

需要一種快速簡單的方法來檢測一個操作花費多長時間麼?使用Firebug的"timer"特性記錄結果。

我是一個Web開發部落格的超級粉絲(比如這個部落格!),但吃午餐或者睡前,部落格确實不是書籍的替代品。始終在你的床前桌上放一本wen開發書籍吧。如下是一些我最喜歡的JavaScript書籍。

<a target="_blank" href="http://www.amazon.cn/s/?_encoding=UTF8&amp;camp=536&amp;creative=3132&amp;field-keywords=%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%9A%84JavaScript&amp;linkCode=ur2&amp;tag=cfjh-23&amp;url=search-alias%3Daps">面向對象的JavaScript</a>

<a target="_blank" href="http://www.amazon.cn/gp/product/B0097CON2S/ref=as_li_ss_tl?ie=UTF8&amp;camp=536&amp;creative=3132&amp;creativeASIN=B0097CON2S&amp;linkCode=as2&amp;tag=cfjh-23">JavaScript:語言精粹</a>

<a target="_blank" href="http://www.amazon.cn/gp/product/B00BAXT8C2/ref=as_li_ss_tl?ie=UTF8&amp;camp=536&amp;creative=3132&amp;creativeASIN=B00BAXT8C2&amp;linkCode=as2&amp;tag=cfjh-23">瘋狂Ajax講義</a>

<a target="_blank" href="http://www.amazon.cn/gp/product/B00AH83HRS/ref=as_li_ss_tl?ie=UTF8&amp;camp=536&amp;creative=3132&amp;creativeASIN=B00AH83HRS&amp;linkCode=as2&amp;tag=cfjh-23">JavaScript學習指南</a>

多閱讀幾遍。我仍舊在讀!

相比調用函數,當頁面加載或調用父函數時,讓函數自動執行會簡單些。簡單地将你的函數包裝在圓括号内,并添加額外的一對圓括号,其本質上就調用了這個函數。

JavaScript代碼庫,如jQuery和Mootools,能夠為你節省大量的編碼時間---特别是使用AJAX操作。話雖如此,始終謹記代碼庫的執行速度始終是比不上原始JavaScript代碼的(假設了代碼的正确性)。

jQuery的"each"方法用來做周遊非常贊,但使用原生"for"語句始終會快一些。

簡單地導入該腳本,你就能獲得一個新的JSON全局對象,用于解析你的.json檔案。

幾年前,在script标簽内常見有"language"屬性。

然而,這個屬性很早就被棄用了,是以就不要再使用了。

繼續閱讀