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