提高JavaScript程式的魯棒性

來源:互聯網
上載者:User

轉自老田的部落格 《提高Javascript程式的魯棒性》Posted in 2009/07/10  02:17h. yongbin

我是學控制理論出身,一個控制系統的魯棒性,確實是在做系統設計時需要著重注意的。什麼是控制系統的魯棒性?

所謂“魯棒性”,是指控制系統在一定(結構,大小)的參數攝動下,維持某些效能的特性(摘自百度百科……汗)。

在軟體設計和開發中,同樣也要時刻考慮提高魯棒性。那麼如何提高JavaScript程式的魯棒性呢?我認為,RIA的魯棒性,一般來講,主要跟js的代碼規範性和DOM操作有關係。下面我總結幾點開發中需要注意的地方,讓頁面跑不死、不報錯。這些事情可能在實際開發中都是小事,但是對於提高軟體整體的魯棒性,是非常critical的!

1. 嚴禁使用全域變數

唉,這個我可是親身體會並深受其害啊!話說,當時我修改一個頁面,開發一段指令碼,需要寫cookie。我發現頁面上以前有人引用了一個js檔案,裡面有setCookie函數,好啊,拿來用!結果這個cookie死活都寫不對。檢查了半天,才發現這個頁面引用的另外一個js檔案也有一個setCookie函數,函數的參數和剛才那個不一樣,而我調用的估計是這個函數!應該是之前的兩個同事在同一個頁面上自己搞自己的,結果竟然函數重名,而這兩個函數都是全域的!設想一下,加入兩個人都在全域範圍內搞一個var i = 0; 那豈不是更加瘋掉。

這個故事得到的教訓,首先當然是同一個team的開發人員應該多相容並包,團結協作。其次呢,頁面的js較多的時候,一定要有一個好的層次,避免全域變數。避免全域變數的一個方式是namespace。例如建立一個這樣的程式結構:

   1:  var my_project = {
   2:    dom : {
   3:      get : function() {},
   4:      make : function() {} // etc.
   5:    },
   6:    cookie : {
   7:      get : function() {},
   8:      set : function() {},
   9:      remove : function() {}
  10:    },
  11:   
  12:    util : {
  13:      // some project utilities
  14:    }
  15:  }

2. 多使用短路運算式

全域變數的部分說的有點多了,大概是因為老田我經曆過那類痛苦吧。短路運算式就是&&和||,在這裡用來提高魯棒性。舉兩個例子,第一,要得到某div節點的第一個節點的nodeName:

   1:  var div = document.getElementById("div_id");
   2:  var node_name;
   3:  if (div && div.firstChild) { // 在用firstChild前,先判斷div是否存在
   4:    node_name = div.firstChild.nodeName;
   5:  }

其次,用||來快速解決一些瀏覽器安全色性問題:

   1:  // 得到元素內文本的跨瀏覽器解決方案
   2:  var text = span.innerText || span.textContent || "";

再例,用||來設定預設值:

   1:  // 設定預設值
   2:  var my_attr = span.getAttribute("my_attr") || default_value;

3. 操作元素前,首先判斷其存在

在第二條裡面已經舉過例子。再舉一例:

   1:  var input = document.getElementsByName("input")[0];
   2:  if (input) {
   3:    target = input.value;
   4:  }

4. 良好的代碼縮排和格式

Doug Crockford,《JavaScirpt: The Good Parts》的作者,在給Google做演講的時候,詳細分析了代碼格式的重要性。比如:

   1:  return
   2:  {
   3:    name : span.nodeName,
   4:    value : span.innerHTML
   5:  }

寫這種代碼的人肯定是C出身。js裡面,後果就是return nothing。js有語句的自動補全機制,return這一樣,會自動在末尾加上分號,導致返回。如果不注意的話,程式出了問題,很難找到原因。所以一定要養成一個代碼格式的好習慣,把左大括弧和return啊,if啊,function()啊,寫在一起。也就是:

   1:  return {
   2:    // something
   3:  }

5. 使用跨瀏覽器的代碼

在對DOM進行讀取和操作時,處處想著瀏覽器安全色性這件事,免得最後返工,自己給自己找麻煩。比如,只用document.getElementById;用nodeName,而不用tagName;不用getElementsByClassName等先進的選取器;不用applyElement, removeNode, swapNode等IE only的方法。

在瀏覽器安全色性方面,強烈推薦ppk的網站quirksmode.org。ppk此人對各個瀏覽器都進行了測試,工作十分紮實,是我們的榜樣啊!

6. 變數儘早定義

JavaScript的變數範圍是所在的整個function,在寫代碼的時候,如果變數在想用的時候再定義,很容易變得難於管理。在開發邏輯比較複雜的程式時,非常容易混亂,甚至變數重名。

7. 小心NodeList

NodeList,也就是節點列表,是一個陷阱,他不是靜態,而是危險的動態結構,它會立即反映文檔的變化。一個經典的死迴圈案例:

   1:  var lis = ul.getElementsByTagName("li");
   2:  for (var i = 0; i < lis.length; i++) {
   3:    ul.appendChild(lis[i].cloneNode(true));
   4:  }

上面的代碼裡,這些li的length不是固定的,而是隨著DOM的變化而變化。這個錯誤我是經曆過一次啊,不過不是死迴圈。還拿這個ul和li舉例子吧,我想刪掉某個ul下面的所有li,代碼類似於下面的樣子,大家看看有什麼問題呢?

   1:  var lis = ul.getElemenetsByTagName("li");
   2:  for (var i = 0; i < lis.length; i++) {
   3:    ul.removeChild(lis[i]);
   4:  }

8. 使用===和!==

某些人可能會問,我用==用的挺好的啊,為什麼要用===?那我要反問,既然===更加嚴謹,沒有類型轉換,而==充滿陷阱,為什麼不用===?沒有自信嗎?哦,那隻能說明你的程式不穩定,魯棒性不好了。

==會進行自動類型轉換,Crockford稱它為evil twins。其他的不說了,舉幾個例子:

   1:  alert(0 == '');  // true
   2:  alert(false == '0'); //true
   3:  alert('\r\n' == 0); // true

9. 不要用with

在設計JavaScript這門語言的時候,with本來是為一些操作提供捷徑的,但是設計的不夠好,可以說js裡面沒有with會更好。舉一個使用with的例子:

   1:  with(element.style) {
   2:    position = "absolute";
   3:    left = "100px";
   4:    top = "100px";
   5:  }

首先with破壞了這門語言的變數範圍結構。在js裡面,postion, left和top本來應該變成全域變數的。可能有些人說,這樣正好,我可以通過with來控制變數範圍!想法不錯,JavaScript 1.7也引入了let語句來做這件事。但是,with會產生無法預想的後果,舉例:

   1:  var a = '';
   2:  var obj = {b: 'b'};
   3:  with(obj) {
   4:   a = b;
   5:  }
   6:  alert(a); // result: 'b'

這裡的a又變成外部變數了!除了這種詭異的事情之外,with語句的執行速度相對來說是非常緩慢的。所以結論就是,想要提高程式的魯棒性,就不要用with。

10. 不要用eval

eval可以把一段字串當作js代碼來執行。eval經常被一些新手拿來用,例如:

eval("value = obj." + key + ";");

其實他完全可以:

value = obj["key"];

eval執行的時候會啟用js解譯器來執行這一小片代碼,速度會慢很多。除此之外,程式的可調試性、可維護性大大降低。類eval的語句還有:

   1:  window.setTimeout("var i = 0", 1000);
   2:  var sum = new Function("x", "y", "return x+y");
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.