12條寫(xiě)出高質(zhì)量JS代碼的方法
書(shū)寫(xiě)出高質(zhì)量的JS代碼不僅讓程序員看著舒服,更加能夠提高程序的運(yùn)行速度,以下就是腳本之家的小編整理方法:
一、如何書(shū)寫(xiě)可維護(hù)性的代碼
當(dāng)出現(xiàn)bug的時(shí)候如果你能立馬修復(fù)它是最好的,此時(shí)解決問(wèn)題的四路在你腦中還是很清晰的。否則,你轉(zhuǎn)移到其他任務(wù)或者bug是經(jīng)過(guò)一定的時(shí)間才出現(xiàn)的,你忘了那個(gè)特定的代碼,一段時(shí)間后再去查看這些代碼就 需要:
1.花時(shí)間學(xué)習(xí)和理解這個(gè)問(wèn)題 2.化時(shí)間是了解應(yīng)該解決的問(wèn)題代碼
還有個(gè)問(wèn)題,特別對(duì)于大的項(xiàng)目或是公司,修復(fù)bug的這位伙計(jì)不是寫(xiě)代碼的那個(gè)人(且發(fā)現(xiàn)bug和修復(fù)bug的不是同一個(gè)人)。因此,必須降低理解代 碼花費(fèi)的時(shí)間,無(wú)論是一段時(shí)間前你自己寫(xiě)的代碼還是團(tuán)隊(duì)中的其他成員寫(xiě)的代碼。這關(guān)系到底線(營(yíng)業(yè)收入)和開(kāi)發(fā)人員的幸福,因?yàn)槲覀兏鼞?yīng)該去開(kāi)發(fā)新的激動(dòng) 人心的事物而不是花幾小時(shí)幾天的時(shí)間去維護(hù)遺留代碼。所以創(chuàng)建可維護(hù)性代碼是至關(guān)重要的,一般可維護(hù)性的代碼有以下幾個(gè)原則:
可讀性
一致性
可預(yù)測(cè)性
看上去就像同一個(gè)人寫(xiě)的
已記錄
二、全局變量的問(wèn)題
全局變量的問(wèn)題在于,你的JavaScript應(yīng)用程序和web頁(yè)面上的所有代碼都共享了這些全局變量,他們住在同一個(gè)全局命名空間,所以當(dāng)程序的兩個(gè)不同部分定義同名但不同作用的全局變量的時(shí)候,命名沖突在所難免。web頁(yè)面包含不是該頁(yè)面開(kāi)發(fā)者所寫(xiě)的代碼也是比較常見(jiàn)的,例如:
第三方的JavaScript庫(kù)
廣告方的腳本代碼
第三方用戶跟蹤和分析腳本代碼
不同類(lèi)型的小組件,標(biāo)志和按鈕
例如說(shuō),該第三方腳本定義了一個(gè)全局變量,叫做A;接著,在你的函數(shù)中也定義一個(gè)名為A的全局變量。其結(jié)果就是后面的變量覆蓋前面的,第三方腳本就一下子失效啦!而且很難debug出來(lái)。
因此:盡可能少的使用全局變量是很重要的,例如命名空間模式或是函數(shù)立即自動(dòng)執(zhí)行,但是要想讓全局變量少最重要的還是始終使用var來(lái)聲明變量。
三、忘記var作用的副作用
隱式全局變量和明確定義的全局變量間有些小的差異,就是通過(guò)delete操作符讓變量未定義的能力。具體如下:
通過(guò)var創(chuàng)建的全局變量(任何函數(shù)之外的程序中創(chuàng)建)是不能被刪除的。
沒(méi)有通過(guò)var創(chuàng)建的隱式全局變量(無(wú)視是否在函數(shù)中創(chuàng)建)是能被刪除的。
所以隱式全局變量并不是真正的全局變量,但它們是全局對(duì)象的屬性。屬性是可以通過(guò)delete操作符刪除的,而變量是不能的,具體代碼我就不寫(xiě)了。
四、訪問(wèn)全局對(duì)象
在瀏覽器中,全局對(duì)象可以通過(guò)window屬性在代碼的任何位置訪問(wèn)(除非你做了些比較出格的事情,像是聲明了一個(gè)名為window的局部變量)。但是在其他環(huán)境下,這個(gè)方便的屬性可能被叫做其他什么東西(甚至在程序中不可用)。如果你需要在沒(méi)有硬編碼的window標(biāo)識(shí)符下訪問(wèn)全局對(duì)象,你可以在任何層級(jí)的函數(shù)作用域中做如下操作:
var global = (function () { return this; }());
五、for循環(huán)
在for循環(huán)中,你可以循環(huán)取得數(shù)組或是數(shù)組類(lèi)似對(duì)象的值,譬如arguments和HTMLCollection對(duì)象。通常的循環(huán)形式如下:
// 次佳的循環(huán) for (var i = 0; i < myarray.length; i++) { // 使用myarray[i]做點(diǎn)什么 }
這種形式的循環(huán)的不足在于每次循環(huán)的時(shí)候數(shù)組的長(zhǎng)度都要去獲取下。這回降低你的代碼,尤其當(dāng)myarray不是數(shù)組,而是一個(gè)HTMLCollection對(duì)象的時(shí)候。
六、不擴(kuò)展內(nèi)置原型
擴(kuò)增構(gòu)造函數(shù)的prototype屬性是個(gè)很強(qiáng)大的增加功能的方法,但有時(shí)候它太強(qiáng)大了。增加內(nèi)置的構(gòu)造函數(shù)原型(如Object(), Array(), 或Function())挺誘人的,但是這嚴(yán)重降低了可維護(hù)性,因?yàn)樗屇愕拇a變得難以預(yù)測(cè)。使用你代碼的其他開(kāi)發(fā)人員很可能更期望使用內(nèi)置的 JavaScript方法來(lái)持續(xù)不斷地工作,而不是你另加的方法。另外,屬性添加到原型中,可能會(huì)導(dǎo)致不使用hasOwnProperty屬性時(shí)在循環(huán)中顯示出來(lái),這會(huì)造成混亂。
七、避免隱式類(lèi)型轉(zhuǎn)換
JavaScript的變量在比較的時(shí)候會(huì)隱式類(lèi)型轉(zhuǎn)換。這就是為什么一些諸如:false == 0 或 “” == 0 返回的結(jié)果是true。為避免引起混亂的隱含類(lèi)型轉(zhuǎn)換,在你比較值和表達(dá)式類(lèi)型的時(shí)候始終使用===和!==操作符。
var zero = 0; if (zero === false) { // 不執(zhí)行,因?yàn)閦ero為0, 而不是false } // 反面示例 if (zero == false) { // 執(zhí)行了... }
八、避免eval()
如果你現(xiàn)在的代碼中使用了eval(),記住該咒語(yǔ)“eval()是魔鬼”。此方法接受任意的字符串,并當(dāng)作JavaScript代碼來(lái)處理。當(dāng)有 問(wèn)題的代碼是事先知道的(不是運(yùn)行時(shí)確定的),沒(méi)有理由使用eval()。如果代碼是在運(yùn)行時(shí)動(dòng)態(tài)生成,有一個(gè)更好的方式不使用eval而達(dá)到同樣的目 標(biāo)。例如,用方括號(hào)表示法來(lái)訪問(wèn)動(dòng)態(tài)屬性會(huì)更好更簡(jiǎn)單:
// 反面示例 var property = "name"; alert(eval("obj." + property)); // 更好的 var property = "name"; alert(obj[property]);
使用eval()也帶來(lái)了安全隱患,因?yàn)楸粓?zhí)行的代碼(例如從網(wǎng)絡(luò)來(lái))可能已被篡改。這是個(gè)很常見(jiàn)的反面教材,當(dāng)處理Ajax請(qǐng)求得到的JSON 相應(yīng)的時(shí)候。在這些情況下,最好使用JavaScript內(nèi)置方法來(lái)解析JSON相應(yīng),以確保安全和有效。若瀏覽器不支持JSON.parse(),你可 以使用來(lái)自JSON.org的庫(kù)。
同樣重要的是要記住,給setInterval(), setTimeout()和Function()構(gòu)造函數(shù)傳遞字符串,大部分情況下,與使用eval()是類(lèi)似的,因此要避免。在幕后,JavaScript仍需要評(píng)估和執(zhí)行你給程序傳遞的字符串:
// 反面示例 setTimeout("myFunc()", 1000); setTimeout("myFunc(1, 2, 3)", 1000); // 更好的 setTimeout(myFunc, 1000); setTimeout(function () { myFunc(1, 2, 3); }, 1000);
使用新的Function()構(gòu)造就類(lèi)似于eval(),應(yīng)小心接近。這可能是一個(gè)強(qiáng)大的構(gòu)造,但往往被誤用。如果你絕對(duì)必須使用eval(),你 可以考慮使用new Function()代替。有一個(gè)小的潛在好處,因?yàn)樵谛翭unction()中作代碼評(píng)估是在局部函數(shù)作用域中運(yùn)行,所以代碼中任何被評(píng)估的通過(guò)var 定義的變量都不會(huì)自動(dòng)變成全局變量。另一種方法來(lái)阻止自動(dòng)全局變量是封裝eval()調(diào)用到一個(gè)即時(shí)函數(shù)中。
考慮下面這個(gè)例子,這里僅un作為全局變量污染了命名空間。
console.log(typeof un); // "undefined" console.log(typeof deux); // "undefined" console.log(typeof trois); // "undefined" var jsstring = "var un = 1; console.log(un);"; eval(jsstring); // logs "1" jsstring = "var deux = 2; console.log(deux);"; new Function(jsstring)(); // logs "2" jsstring = "var trois = 3; console.log(trois);"; (function () { eval(jsstring); }()); // logs "3" console.log(typeof un); // number console.log(typeof deux); // "undefined" console.log(typeof trois); // "undefined"
另一間eval()和Function構(gòu)造不同的是eval()可以干擾作用域鏈,而Function()更安分守己些。不管你在哪里執(zhí)行 Function(),它只看到全局作用域。所以其能很好的避免本地變量污染。在下面這個(gè)例子中,eval()可以訪問(wèn)和修改它外部作用域中的變量,這是 Function做不來(lái)的(注意到使用Function和new Function是相同的)。
(function () { var local = 1; eval("local = 3; console.log(local)"); // logs "3" console.log(local); // logs "3" }()); (function () { var local = 1; Function("console.log(typeof local);")(); // logs undefined
九、編碼規(guī)范
建立和遵循編碼規(guī)范是很重要的,這讓你的代碼保持一致性,可預(yù)測(cè),更易于閱讀和理解。一個(gè)新的開(kāi)發(fā)者加入這個(gè)團(tuán)隊(duì)可以通讀規(guī)范,理解其它團(tuán)隊(duì)成員書(shū)寫(xiě)的代碼,更快上手干活。
十、縮進(jìn)
代碼沒(méi)有縮進(jìn)基本上就不能讀了。唯一糟糕的事情就是不一致的縮進(jìn),因?yàn)樗瓷先ハ袷亲裱艘?guī)范,但是可能一路上伴隨著混亂和驚奇。重要的是規(guī)范地使用縮進(jìn)。
十一、注釋
你必須注釋你的代碼,即使不會(huì)有其他人向你一樣接觸它。通常,當(dāng)你深入研究一個(gè)問(wèn)題,你會(huì)很清楚的知道這個(gè)代碼是干嘛用的,但是,當(dāng)你一周之后再回來(lái)看的時(shí)候,想必也要耗掉不少腦細(xì)胞去搞明白到底怎么工作的。
很顯然,注釋不能走極端:每個(gè)單獨(dú)變量或是單獨(dú)一行。但是,你通常應(yīng)該記錄所有的函數(shù),它們的參數(shù)和返回值,或是任何不尋常的技術(shù)和方法。要想到注 釋可以給你代碼未來(lái)的閱讀者以諸多提示;閱讀者需要的是(不要讀太多的東西)僅注釋和函數(shù)屬性名來(lái)理解你的代碼。例如,當(dāng)你有五六行程序執(zhí)行特定的任務(wù), 如果你提供了一行代碼目的以及為什么在這里的描述的話,閱讀者就可以直接跳過(guò)這段細(xì)節(jié)。沒(méi)有硬性規(guī)定注釋代碼比,代碼的某些部分(如正則表達(dá)式)可能注釋 要比代碼多。
十二、花括號(hào){}
花括號(hào)(亦稱大括號(hào),下同)應(yīng)總被使用,即使在它們?yōu)榭蛇x的時(shí)候。技術(shù)上將,在in或是for中如果語(yǔ)句僅一條,花括號(hào)是不需要的,但是你還是應(yīng)該總是使用它們,這會(huì)讓代碼更有持續(xù)性和易于更新。
相關(guān)文章
轉(zhuǎn)義字符(\)對(duì)JavaScript中JSON.parse的影響概述
JSON是一個(gè)提供了stringify和parse方法的內(nèi)置對(duì)象,前者用于將js對(duì)象轉(zhuǎn)化為符合json標(biāo)準(zhǔn)的字符串,后者將符合json標(biāo)準(zhǔn)的字符串轉(zhuǎn)化為js對(duì)象,本文為大家介紹下轉(zhuǎn)義字符對(duì)JSON.parse方法的影響2013-07-07window.navigate 與 window.location.href 的使用區(qū)別介紹
首先說(shuō)明的是 window.navigate 與 window.location.href 都是實(shí)現(xiàn)頁(yè)面鏈接跳轉(zhuǎn)的,下面將介紹它們的區(qū)別。感興趣的朋友可以參考下2013-09-09淺談JavaScript的內(nèi)置對(duì)象和瀏覽器對(duì)象
下面小編就為大家?guī)?lái)一篇淺談JavaScript的內(nèi)置對(duì)象和瀏覽器對(duì)象。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-06-06JavaScript學(xué)習(xí)筆記之基礎(chǔ)語(yǔ)法
本文不是零基礎(chǔ)教學(xué),請(qǐng)沒(méi)javascript基礎(chǔ)的小伙伴們先出門(mén)左拐,本人之前學(xué)習(xí)java的,所以本文主要對(duì)比下java學(xué)習(xí)javascript。2015-01-01JavaScript中splice與slice的區(qū)別
本文給大家分享的是JavaScript中的splice和slice的用法和區(qū)別,slice()方法和splice()方法都是原生js中對(duì)數(shù)組操作的方法,下面我們來(lái)詳細(xì)探討下2017-05-05JavaScript中Math對(duì)象使用說(shuō)明
2008-01-01關(guān)于jQuery $.isNumeric vs. $.isNaN vs. isNaN
本篇文章,小編將為大家介紹jQuery $.isNumeric vs. $.isNaN vs. isNaN,有需要的朋友可以參考一下2013-04-04