摘要:也就是說(shuō)避免屬性查找或其他的操作。簡(jiǎn)化循環(huán)體循環(huán)體是執(zhí)行最多的,所以要確保其被最大限度地優(yōu)化。代碼組織組織代碼要考慮到可維護(hù)性并不一定是傳送給瀏覽器的最好方式。
最佳實(shí)踐 可維護(hù)性 什么是可維護(hù)性的代碼
如果說(shuō)代碼是可維護(hù)的,它需要遵循以下特點(diǎn)
可理解性——其他人可以接手代碼并理解它的意圖和一般途徑,而無(wú)需原開(kāi)發(fā)人員的完整解釋。
直觀性——代碼中的東西一看就能明白,不管其操作過(guò)程多么復(fù)雜。
可適應(yīng)性——代碼以一種數(shù)據(jù)上的變化不要求完全重寫(xiě)的方法撰寫(xiě)。
可擴(kuò)展性——在代碼架構(gòu)上已考慮到在未來(lái)允許對(duì)核心功能進(jìn)行擴(kuò)展
可調(diào)試性——當(dāng)有地方出錯(cuò)時(shí),代碼可以給予你足夠的信息來(lái)盡可能直接地確定問(wèn)題所在。
代碼約定 可讀性可讀性大部分內(nèi)容和代碼的縮進(jìn)相關(guān),當(dāng)所有人使用一樣的縮進(jìn)方式時(shí),整個(gè)項(xiàng)目的代碼都會(huì)更加易于閱讀
可讀性的另一方面是注釋,下面內(nèi)容需要進(jìn)行注釋
函數(shù)和方法——每個(gè)函數(shù)或方法都應(yīng)該包含一個(gè)注釋,描述其目的和用于完成任務(wù)所可能使用的算法。陳述事先的假設(shè)也非常重要,如參數(shù)代表什么,函數(shù)是否有返回值(因?yàn)檫@不能從函數(shù)定義中推斷出來(lái))。
大段代碼——用于完成單個(gè)任務(wù)的多行代碼應(yīng)該在前面放一個(gè)描述任務(wù)的注釋。
復(fù)雜的算法——如果使用了一種獨(dú)特的方式解決某個(gè)問(wèn)題,則要在注釋中解釋你是如何做的。這不僅僅可以幫助其他瀏覽你代碼的人,也能在下次你自己查閱代碼的時(shí)候幫助理解。
Hack——因?yàn)榇嬖跒g覽器差異,JavaScript 代碼一般會(huì)包含一些 hack。不要假設(shè)其他人在看代碼的時(shí)候能夠理解 hack 所要應(yīng)付的瀏覽器問(wèn)題。如果因?yàn)槟撤N瀏覽器無(wú)法使用普通的方法,所以你需要用一些不同的方法,那么請(qǐng)將這些信息放在注釋中。這樣可以減少出現(xiàn)這種情況的可能性:有人偶然看到你的 hack,然后“修正”了它,最后重新引入了你本來(lái)修正了的錯(cuò)誤。
變量和函數(shù)命名
命名規(guī)則
變量名應(yīng)為名詞如 car 或 person 。
函數(shù)名應(yīng)該以動(dòng)詞開(kāi)始,如 getName() 。返回布爾類型值的函數(shù)一般以 is 開(kāi)頭,如isEnable() 。
變量和函數(shù)都應(yīng)使用合乎邏輯的名字,不要擔(dān)心長(zhǎng)度。長(zhǎng)度問(wèn)題可以通過(guò)后處理和壓縮來(lái)緩解
變量類型透明
三種表示變量數(shù)據(jù)類型的方式
初始化
//通過(guò)初始化指定變量類型 var found = false; //布爾型 var count = -1; //數(shù)字 var name = ""; //字符串 var person = null; //對(duì)象
使用匈牙利標(biāo)記法
//用于指定數(shù)據(jù)類型的匈牙利標(biāo)記法 var bFound; //布爾型 var iCount; //整數(shù) var sName; //字符串 var oPerson; //對(duì)象
使用類型注釋
//用于指定類型的類型注釋 var found /*:Boolean*/ = false; var count /*:int*/ = 10; var name /*:String*/ = "Nicholas"; var person /*:Object*/ = null松散耦合
幾條規(guī)則
勿將 event 對(duì)象傳給其他方法;只傳來(lái)自 event 對(duì)象中所需的數(shù)據(jù);
任何可以在應(yīng)用層面的動(dòng)作都應(yīng)該可以在不執(zhí)行任何事件處理程序的情況下進(jìn)行;
任何事件處理程序都應(yīng)該處理事件,然后將處理轉(zhuǎn)交給應(yīng)用邏輯
編程實(shí)踐 尊重對(duì)象所有權(quán)不要為實(shí)例或原型添加屬性;
不要為實(shí)例或原型添加方法;
不要重定義已存在的方法。
創(chuàng)建包含所需功能的新對(duì)象,并用它與相關(guān)對(duì)象進(jìn)行交互;
創(chuàng)建自定義類型,繼承需要進(jìn)行修改的類型。然后可以為自定義類型添加額外功能。
避免全局量//兩個(gè)全局量——避免??! var name = "Nicholas"; function sayName(){ alert(name); } //一個(gè)全局量——推薦 var MyApplication = { name: "Nicholas", sayName: function(){ alert(this.name); } }避免與null進(jìn)行比較
function sortArray(values){ if (values != null){ //避免! values.sort(comparator); } } function sortArray(values){ if (values instanceof Array){ // 推薦 values.sort(comparator); } }
如果看到了與null比較的代碼,嘗試使用以下技術(shù)替換
如果值應(yīng)為一個(gè)引用類型,使用 instanceof 操作符檢查其構(gòu)造函數(shù);
如果值應(yīng)為一個(gè)基本類型,使用 typeof 檢查其類型;
如果是希望對(duì)象包含某個(gè)特定的方法名,則使用 typeof 操作符確保指定名字的方法存在于對(duì)象上。
使用常量var Constants = { INVALID_VALUE_MSG: "Invalid value!", INVALID_VALUE_URL: "/errors/invalid.php" }; function validate(value){ if (!value){ alert(Constants.INVALID_VALUE_MSG); location.href = Constants.INVALID_VALUE_URL; } }性能 注意作用域 避免全局查找
function updateUI(){ var imgs = document.getElementsByTagName("img"); for (var i=0, len=imgs.length; i < len; i++){ imgs[i].title = document.title + " image " + i; } var msg = document.getElementById("msg"); msg.innerHTML = "Update complete."; } //改進(jìn) function updateUI(){ var doc = document; var imgs = doc.getElementsByTagName("img"); for (var i=0, len=imgs.length; i < len; i++){ imgs[i].title = doc.title + " image " + i; } var msg = doc.getElementById("msg"); msg.innerHTML = "Update complete."; }避免with語(yǔ)句
function updateBody(){ with(document.body){ alert(tagName); innerHTML = "Hello world!"; } } //改進(jìn) function updateBody(){ var body = document.body alert(body.tagName); body.innerHTML = "Hello world!"; }選擇正確方法 避免不必要的屬性查找 優(yōu)化循環(huán)
減值迭代——大多數(shù)循環(huán)使用一個(gè)從 0 開(kāi)始、增加到某個(gè)特定值的迭代器。在很多情況下,從最大值開(kāi)始,在循環(huán)中不斷減值的迭代器更加高效。
簡(jiǎn)化終止條件——由于每次循環(huán)過(guò)程都會(huì)計(jì)算終止條件,所以必須保證它盡可能快。也就是說(shuō)避免屬性查找或其他 O(n)的操作。
簡(jiǎn)化循環(huán)體——循環(huán)體是執(zhí)行最多的,所以要確保其被最大限度地優(yōu)化。確保沒(méi)有某些可以被很容易移出循環(huán)的密集計(jì)算。
使用后測(cè)試循環(huán)——最常用 for 循環(huán)和 while 循環(huán)都是前測(cè)試循環(huán)。而如 do-while 這種后測(cè)試循環(huán),可以避免最初終止條件的計(jì)算,因此運(yùn)行更快
展開(kāi)循環(huán)//credit: Speed Up Your Site (New Riders, 2003) var iterations = Math.floor(values.length / 8); var leftover = values.length % 8; var i = 0; if (leftover > 0){ do { process(values[i++]); } while (--leftover > 0); } do { process(values[i++]); process(values[i++]); process(values[i++]); process(values[i++]); process(values[i++]); process(values[i++]); process(values[i++]); process(values[i++]); } while (--iterations > 0);避免雙重解釋
//某些代碼求值——避免!! eval("alert("Hello world!")"); //創(chuàng)建新函數(shù)——避免!! var sayHi = new Function("alert("Hello world!")"); //設(shè)置超時(shí)——避免!! setTimeout("alert("Hello world!")", 500); //已修正 alert("Hello world!"); //創(chuàng)建新函數(shù)——已修正 var sayHi = function(){ alert("Hello world!"); }; //設(shè)置一個(gè)超時(shí)——已修正 setTimeout(function(){ alert("Hello world!"); }, 500);其他
原生方法較快——只要有可能,使用原生方法而不是自己用 JavaScript 重寫(xiě)一個(gè)。原生方法是用諸如 C/C++之類的編譯型語(yǔ)言寫(xiě)出來(lái)的,所以要比 JavaScript 的快很多很多。JavaScript 中最容易被忘記的就是可以在 Math 對(duì)象中找到的復(fù)雜的數(shù)學(xué)運(yùn)算;這些方法要比任何用 JavaScript 寫(xiě)的同樣方法如正弦、余弦快的多。
Switch 語(yǔ)句較快 —— 如果有一系列復(fù)雜的 if-else 語(yǔ)句,可以轉(zhuǎn)換成單個(gè) switch 語(yǔ)句則可以得到更快的代碼。還可以通過(guò)將 case 語(yǔ)句按照最可能的到最不可能的順序進(jìn)行組織,來(lái)進(jìn)一步優(yōu)化 switch 語(yǔ)句。
位運(yùn)算符較快 —— 當(dāng)進(jìn)行數(shù)學(xué)運(yùn)算的時(shí)候,位運(yùn)算操作要比任何布爾運(yùn)算或者算數(shù)運(yùn)算快。選擇性地用位運(yùn)算替換算數(shù)運(yùn)算可以極大提升復(fù)雜計(jì)算的性能。諸如取模,邏輯與和邏輯或都可以考慮用位運(yùn)算來(lái)替換
最小化語(yǔ)句數(shù) 多個(gè)變量聲明//4 個(gè)語(yǔ)句 —— 很浪費(fèi) var count = 5; var color = "blue"; var values = [1,2,3]; var now = new Date() //改進(jìn) //一個(gè)語(yǔ)句 var count = 5, color = "blue", values = [1,2,3], now = new Date()插入迭代值
var name = values[i]; i++; //改進(jìn) var name = values[i++];使用數(shù)組和對(duì)象字面量
//用 4 個(gè)語(yǔ)句創(chuàng)建和初始化數(shù)組——浪費(fèi) var values = new Array(); values[0] = 123; values[1] = 456; values[2] = 789; //用 4 個(gè)語(yǔ)句創(chuàng)建和初始化對(duì)象——浪費(fèi) var person = new Object(); person.name = "Nicholas"; person.age = 29; person.sayName = function(){ alert(this.name); }; //改進(jìn) //只用一條語(yǔ)句創(chuàng)建和初始化數(shù)組 var values = [123, 456, 789]; //只用一條語(yǔ)句創(chuàng)建和初始化對(duì)象 var person = { name : "Nicholas", age : 29, sayName : function(){ alert(this.name); } };優(yōu)化DOM交互 最小化現(xiàn)場(chǎng)更新
var list = document.getElementById("myList"), fragment = document.createDocumentFragment(), item, i; for (i=0; i < 10; i++) { item = document.createElement("li"); fragment.appendChild(item); item.appendChild(document.createTextNode("Item " + i)); } list.appendChild(fragment);使用innerHTML
var list = document.getElementById("myList"), html = "", i; for (i=0; i < 10; i++) { html += "
var images = document.getElementsByTagName("img"), image, i, len; for (i=0, len=images.length; i < len; i++){ image = images[i]; //處理 }部署 構(gòu)建過(guò)程
寫(xiě)的代碼不應(yīng)該原封不動(dòng)地放入瀏覽器中
知識(shí)產(chǎn)權(quán)問(wèn)題 —— 如果把帶有完整注釋的代碼放到線上,那別人就更容易知道你的意圖,對(duì)它再利用,并且可能找到安全漏洞。
文件大小 —— 書(shū)寫(xiě)代碼要保證容易閱讀,才能更好地維護(hù),但是這對(duì)于性能是不利的。瀏覽器并不能從額外的空白字符或者是冗長(zhǎng)的函數(shù)名和變量名中獲得什么好處。
代碼組織 —— 組織代碼要考慮到可維護(hù)性并不一定是傳送給瀏覽器的最好方式。
驗(yàn)證
JSLint可以查找JavaScript代碼中語(yǔ)法錯(cuò)誤以及常見(jiàn)的編碼錯(cuò)誤,可以發(fā)掘潛在問(wèn)題
eval() 的使用;
未聲明變量的使用;
遺漏的分號(hào);
不恰當(dāng)?shù)膿Q行;
錯(cuò)誤的逗號(hào)使用;
語(yǔ)句周圍遺漏的括號(hào);
switch 分支語(yǔ)句中遺漏的 break ;
重復(fù)聲明的變量;
with 的使用;
錯(cuò)誤使用的等號(hào)(替代了雙等號(hào)或三等號(hào));
無(wú)法到達(dá)的代碼。
壓縮 文件壓縮刪除額外的空白(包括換行);
刪除所有注釋;
縮短變量名。
HTTP壓縮
對(duì)于 Apache Web服務(wù)器,有兩個(gè)模塊可以進(jìn)行 HTTP壓縮: mod_gzip (Apache1.3.x)和 mod_deflate(Apache 2.0.x)。對(duì)于 mod_gzip ,可以給 httpd.conf 文件或者是 .htacces s文件添加以下代碼啟用對(duì)JavaScript的自動(dòng)壓縮:
告訴 mod_zip 要包含任何以.js 結(jié)尾的文件 mod_gzip_item_include file .js$
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/98226.html
摘要:當(dāng)代碼在一個(gè)環(huán)境中執(zhí)行時(shí),會(huì)創(chuàng)建變量對(duì)象的一個(gè)作用域鏈。作用域鏈的用途,是保證對(duì)執(zhí)行環(huán)境有權(quán)訪問(wèn)的所有變量和函數(shù)的有序訪問(wèn)。這樣,一直延續(xù)到全局執(zhí)行環(huán)境全局執(zhí)行環(huán)境的變量對(duì)象始終都是作用域鏈中的最后一個(gè)對(duì)象。 變量、作用域和內(nèi)存問(wèn)題 基本類型和引用類型的值 基本類型值指的是簡(jiǎn)單的數(shù)據(jù)段,而引用類型值值那些可能由多個(gè)值構(gòu)成的對(duì)象。 定義基本類型值的引用和引用類型值的方法是類似的,創(chuàng)建...
摘要:大多數(shù)情況下,可以是同局部變量完成相同的事情而不引入新的作用域。選擇正確的方法避免不必要的屬性查找一旦多次用到屬性對(duì)象,應(yīng)該將其存儲(chǔ)在局部變量中。盡可能多的使用局部變量將屬性查找替換為值查找。 1、可維護(hù)性 1.1 可維護(hù)代碼特征 1. 可理解性 2. 直觀性 3. 可適應(yīng)性 4. 可擴(kuò)展性 5. 可調(diào)試性 1.2 代碼約定 1、可讀性(代碼縮進(jìn)和代碼注釋) 2、變量和函數(shù)命名 變量...
摘要:對(duì)象的核心對(duì)象是,它表示瀏覽器的一個(gè)實(shí)例。而和則表示該容器中頁(yè)面視圖區(qū)的大小。在中,與返回相同的值,即視口大小而非瀏覽器窗口大小。第三個(gè)參數(shù)是一個(gè)逗號(hào)分隔的設(shè)置字符串,表示在新窗口中都顯示哪些特性。這應(yīng)該是用戶打開(kāi)窗口后的第一個(gè)頁(yè)面 BOM window對(duì)象 BOM的核心對(duì)象是window,它表示瀏覽器的一個(gè)實(shí)例。在瀏覽器中,window對(duì)象有雙重角色,它既是通過(guò)JavaScript訪...
摘要:匿名函數(shù)可以用來(lái)模仿塊級(jí)作用域來(lái)避免這個(gè)問(wèn)題這里是塊級(jí)作用域代碼定義并立即調(diào)用了一個(gè)匿名函數(shù),將函數(shù)聲明包含在一對(duì)圓括號(hào)中,表示它實(shí)際上是一個(gè)函數(shù)表達(dá)式,而緊隨其后的另一對(duì)圓括號(hào)會(huì)立即調(diào)用這個(gè)函數(shù)。 函數(shù)表達(dá)式 遞歸 遞歸函數(shù)是在一個(gè)函數(shù)通過(guò)名字調(diào)用自身的情況下構(gòu)成的 function factrial(num){ if(num
摘要:簡(jiǎn)介簡(jiǎn)史誕生于年,當(dāng)時(shí)主要負(fù)責(zé)表單的輸入驗(yàn)證。實(shí)現(xiàn)一個(gè)完整的由三部分組成核心文檔對(duì)象模型瀏覽器對(duì)象模型就是對(duì)實(shí)現(xiàn)該標(biāo)準(zhǔn)規(guī)定的各個(gè)方面內(nèi)容的語(yǔ)言的描述。把整個(gè)頁(yè)面映射為一個(gè)多層節(jié)點(diǎn)結(jié)構(gòu)。由萬(wàn)維網(wǎng)聯(lián)盟規(guī)劃。主要目標(biāo)是映射文檔的結(jié)構(gòu)。 JavaScript簡(jiǎn)介 JavaScript簡(jiǎn)史 JavaScript誕生于1995年,當(dāng)時(shí)主要負(fù)責(zé)表單的輸入驗(yàn)證。 如果沒(méi)有表單驗(yàn)證的功能,填入信息之...
閱讀 1572·2023-04-26 00:25
閱讀 950·2021-09-27 13:36
閱讀 956·2019-08-30 14:14
閱讀 2208·2019-08-29 17:10
閱讀 1035·2019-08-29 15:09
閱讀 1974·2019-08-28 18:21
閱讀 996·2019-08-26 13:27
閱讀 999·2019-08-26 10:58