[筆記]最佳實踐

最佳實踐將分爲三大方面講述:1.可維護性、2.性能、3.部署javascript

參考《JavaScript高級程序設計》總結出如下內容:php

1.可維護性

1.1什麼是可維護的代碼?

可維護的代碼遵循如下特色:java

  1. 可理解性:其餘人能夠接手代碼並理解它的意圖和通常途徑,而無需開發人員的完整解釋。
  2. 直觀性:代碼中的東西一看就能明白,無論其操做過程多麼複雜。
  3. 可適應性:代碼以一種數據上的變化不要求徹底重寫的方法撰寫。
  4. 可拓展性:在代碼架構上已考慮到在將來容許對核心功能進行擴展。
  5. 可調試性:當有地方出錯時,代碼能夠給予你足夠的信息來儘量直接的肯定問題所在。

1.2 代碼約定

1.可讀性:可維護的前提是必須可讀,因此可讀性是很重要的,主要兩方面改善可讀性:縮進,註釋。算法

通常而言如下地方須要進行註釋:編程

一、函數和方法數組

二、大段代碼bash

三、複雜的算法架構

四、Hack函數

2.變量和函數命名性能

適當給變量和函數起名字對於增長代碼可理解性和可維護性是很是重要的。

命名規則以下:

  • 變量名應爲名詞如car或person
  • 函數名應該以動次開始,如getName()。返回布爾類型值的函數通常以is開頭,如isEnable()。
  • 變量和函數都應使用合乎邏輯的名字,不要擔憂長度。長度問題能夠經過後處理和壓縮來緩解。

3.變量類型透明

JavaScript中變量類型是鬆散類型的,因此很容易就忘記變量所應包含的數據類型。合適的命名方式能夠必定程度上緩解這個問題,但放到全部的狀況下看,還不夠。有三種表示變量數據類型的方式。

第一種方式是初始化。當定義了一個變量後,他應該被初始化爲一個值,來暗示他未來應該如何應用,例如:

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;複製代碼

缺點是不能用多行註釋一次註釋大塊的代碼。


1.3 鬆散耦合

只要應用的某個部分過度依賴於另外一部分,代碼就是耦合過緊,男與維護。典型的問題如:對象直接引用另外一個對象,而且當修改其中一個的同時須要修改另一個。緊密耦合的軟件難於維護而且須要常常重寫。

1.解耦HTML/JavaScript

儘可能避免的緊密耦合狀況:

一、直接寫在HTML中的JavaScript

二、使用事件處理程序屬性值的緊密耦合的HTML/javascript

三、在JavaScript中建立大量HTML。

理想的狀況是,HTL和JavaScript應該徹底分離,而且經過外部文件和使用DOM附加行爲來包含JavaScript。


2.解耦CSS/JavaScript

現代Web開發免不了要用JavaScript改變某些樣式,可是未來若是須要更改樣式表,CSS和JavaScript文件可能都須要更改。這會對開發人員形成心理陰影...因此在這兩個層次之間必須有清晰的劃分。

但也是有解決方法的:經過更改樣式類而非特定樣式。


3.解耦應用邏輯/事件處理程序


1.4 編程實踐

1.尊重對象全部權

意思是你不能修改不屬於你的對象。更具體的說:

  • 不要爲實例或原型添加屬性;
  • 不要爲實例或原型添加方法;
  • 不要重定義已存在的方法。

只要對象不是本身建立的,就永遠不去修改,明顯Array、document這些對象都不是你的,它們在你的代碼執行前就存在了。可是依然能夠經過如下方式爲對象建立新的功能:

  • 建立包含所需功能的新對象,並用它與相關對象進行交互;
  • 建立自定義類型,繼承須要進行修改的類型,而後能夠爲自定義類型添加額外功能。


2.避免全局變量

3.避免與null進行比較

4.使用常量

儘管JavaScript沒有常量的正是概念,但它仍是頗有用的。這種將數據從應用邏輯分離出來的思想,能夠在不冒引入錯誤的風險的同時,就改變數據。請看如下例子:

function validata(value){
    if(!value){
        alert('Invalid value!');
        location.href = '/errors/invalid.php';
    ]
}複製代碼

這個函數中有兩段數據:要顯示給用戶的信息以及URL。顯示在用戶界面上的字符串應該以容許進行語言國際化的方式抽取出來。URL也應該被抽取出來,由於它們有隨着應用成長而改變的傾向。 基本上,有着可能因爲這樣那樣緣由會變化的這些數據,那麼都會須要找到函數並在其中修改代碼。而每次修改應用邏輯的代碼,均可能會引入錯誤。能夠經過將數據抽取出來變成單獨定義的常量的方式,將應用邏輯與數據修改隔離開來。例如:

var Constants = {
    INVALID_VALUE_MSG: 'Invalid value!',
    INVALID_VALUE_URL: '/errors/invalid.php'
};

function validata(value){
    if (!value){
        alert(Constants.INVALID_VALUE_MSG);
        location.href = Constants.INVALID_VALUE_URL;
    }
};複製代碼

在這段重寫過的代碼中,消息和URL都被定義於Constants對象中,而後函數引用這些值。這些設置容許數據在無需使用它的函數的狀況下進行變動。Constants對象甚至能夠在徹底獨立的文件中定義,同時該文件能夠由包含正確值的其餘過程根據國際化設置來生成。

關鍵在於將數據和使用它的邏輯進行分離。要注意的值的類型以下所示。

重複值:任何在多出用到的值都應該抽取爲一個常量,這就限制了當一個值變了而另外一個沒變的時候會形成的錯誤。這也包含了CSS類名。

用戶界面字符串:任何用戶顯示給用戶的字符串,都應被抽取出來以方便國際化。

URLs:在Web應用中,資源位置很容易變動,因此推薦一個公共地方存放全部的URL。

任意可能會更改的值:每當你在用到字面量值的時候,你都要問一下本身這個值在將來是否是會變化。若是答案是‘是’,那麼這個值就應該被提取出來做爲一個常量。

對於企業級的JavaScript開發而言,使用常量是很是重要的技巧,由於他能讓代碼更容易維護,而且在數據更改的同時保護代碼。


2.性能

2.1 注意做用域

只要能減小化肥在做用域鏈上的事件,就能增長腳本的總體性能。

1.避免全局查找

2.避免with語句


2.2 選擇正確方法

1.避免沒必要要的屬性查找。

屬性查找越多,執行時間就越長。

通常來說,只要能減小算法的複雜度,就要儘量減小。儘量多地使用局部變量將屬性查找替換爲值查找。

2.優化循環

循環的基本優化步驟以下所示:

  1. 減值迭代:大多數循環使用一個從0開始、增長到某個特定值的迭代器。在不少狀況ixa、從最大值開始,在循環中不斷減值的迭代器更加高效。
  2. 簡化終止條件:因爲每次循環過程都會計算終止條件,因此必須保證它儘量快。也就是說避免屬性查找或其餘O(n)的操做。
  3. 簡化循環體:循環體是執行最多的,因此要確保其被最大限度的有話啊。確保沒有某些能夠被很容易移出循環的密集計算。
  4. 使用後測試循環:do-while

3.展開循環

當循環的次數是肯定的,消除循環並使用屢次函數調用每每更快。

針對大數據集使用展開循環能夠節省不少時間,但對於小數據集,額外的開銷則可能得不償失。它是要花更多的代碼來完成一樣的任務,若是處理的不是大數據集,通常來講並不值得。

4.避免雙重解釋

5.性能的其餘注意事項

  • 原生方法較快:只要有可能,使用原生方法而不是本身用JavaScript重寫一個。
  • switch語句較快:若是有一系列複雜的if-else語句,能夠轉換成單個switch語句則能夠獲得更快的代碼。 還能夠經過將case語句按照最可能的到最不可能的順序進行組織,來進一步優化switch語句。
  • 位運算符較快


2.3 最小化語句數

JavaScript代碼中的語句數量也影響所執行的操做的速度。完成多個操做的單個語句要比完成單個操做的多個語句快。因此就要找出能夠組合在一塊兒的語句,以減小腳本總體的執行時間。

1.多個變量聲明

多個變量的聲明儘可能用一個語句。例如

//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();
複製代碼

2.插入迭代值

當使用迭代值的時候,儘量合併語句。請看代碼:

var name = values[i];
i++;複製代碼

優化後

var name = values[i++];複製代碼

3.使用數組和對象字面量(不用構造函數)

使用構造函數老是要用到更多的語句來插入元素或者定義屬性,而字面量能夠將這些操做在一個語句中完成。例如:

//用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);
    }
};複製代碼

只要有可能,儘可能使用數組和對象的字面量表達方式來消除不要的語句。


2.4 優化DOM交互

在JavaScript的各方面中,DOM毫無疑問是最慢的一部分。

因此優化DOM交互是極其重要的,下面是關於DOM優化的總結:

1.最小化現場更新:儘可能一次性把DOM元素添加成功,添加的操做(現場更新)越少越好。

2.使用innerHTML:innerHTML方法會在後臺建立一個HTML解析器,而後使用內部的DOM調用來建立DOM,而非基於JavaScript的DOM調用。因爲內部方法是編譯好的而非解釋執行的,因此執行快得多。

3.使用事件代理

4.注意HTMLCollection:最小化訪問HTMLCollection的次數能夠極大地改進腳本的性能。例如:

var images = document.getElementsByTagName('img'),
    i,len;
for(i=0,len=images.length;i<len;i++){
    //處理
}複製代碼

這裏的關鍵在於長度length存入了len變量,而不是每次都去訪問HTMLCollection的length屬性,當在循環中使用HTMLCollection的時候,下一步應該是獲取要使用的項目的引用,以下所示,一邊避免在循環體內屢次調用HTMLCollection

var images = document.getElementsByTagName('img'),
    image,
    i,len;
for(i=0,len=images,length;i<len;i++){
    image = images[i];
    //處理
}複製代碼

這段代碼添加了image變量,保存了當前的圖像,這以後在循環內疚沒有理由在訪問images的HTMLCollection了。

發生如下狀況時會返回HTMLCollection對象:

  1. 進行了對getElementsByTagName()的調用;
  2. 獲取了元素的childNodes屬性;
  3. 獲取了元素的attributes屬性;
  4. 訪問了特殊的集合,如document.forms/document.images等。



以上。

相關文章
相關標籤/搜索