JavaScript基本編碼模式

姬光發表於2012-06-18

無論編寫任何程式都會接觸到編碼風格,設計模式等概念,編碼風格一般側重於書寫規範,而設計模式則偏向於程式架構設計。本文中筆者整理的這些“模式”包含了編寫JavaScript程式碼時一些常用的方法或者小技巧,可以幫助初學JavaScript的同學迅速提升程式碼質量。當然,在此之前首先要保證規範的書寫習慣,在此之上可以再將本文介紹的知識點運用到程式碼編寫中,則可以大大提升程式碼質量。

下面是筆者整理的一些點,沒有什麼邏輯順序,想到哪兒寫到哪兒了,不足之處歡迎大家補充指正。

1. 變數定義

// 一般寫法
var a = 0;
var b = 1; 
var c = 'xxx';

// 推薦寫法
var a = 0,
    b = 1,
    c = 'xxx';

2. 儘量使用字面量

// 一般寫法
var obj = new Object();
        obj.a = 'aa';
        obj.b = 'bb';
        obj.c = 'cc';

var arr = new Array();

// 推薦寫法
var obj = {
        a: 'aa',
        b: 'bb'
    };

var arr = [];

function getXX(index){
    return ['aa', 'bb', 'xx', 55, 'xxb'](index);
}

function getMessage(code){
    return {
        404: 'xxx',
        500: 'xxx'
    }[code];
}

3. 正則字面量

var regex = new RegExp('someting');

// 當正規表示式可能變化時才使用建構函式
var cls = 'someclass',
    regex = new RegExp(cls + '\\s*', 'ig');   // only for dynamic regexs

// 其他情況均使用字面量
var regex = /someting/ig;

4. 設定預設值

// Default values
var arg = arg || 'default';  // fallback

document.getElementById('test').onclick = function(event){
    var event = event || window.event;
};

function getX(a){
    return a+1 || 'default';
}

5. 條件判斷

// Conditions
answer = obj && obj.xx && obj.xx.xxx;

// 連續判斷
if(obj && obj.xx && obj.xx.xxx){
    // do something
}

if(obj.xx){
    // do something
}

if(!obj){
    // do something
}

// 使用全等判斷
if(a === b){
    // do something
}

// 儘量不檢測瀏覽器,僅檢測要使用的特性是否支援
if(document.getElementById){
    // ability detect
}

6. 三元操作符

// Ternary
check ? value1 : value2;

// 三元操作符更簡潔
var foo = (condition) ? value1 : value2;

function xx(){
    if(condition){
        return value1;
    }else{
        return value2;
    }
}

function xx(){
    return (condition) ? value1 : value2;
}

// 格式化三元操作符
foo = predicate ? "one" :
      predicate ? "two" :
                  "default";   // format

7. 插入迭代值

// Insert iteration
var name = value[i];
    i++;

// 直接將迭代值插入
var name = value[i++];

8. DOM操作

// DOM Operation
el.style.display = 'none'; // offline
    // operation
el.style.display = 'block';

// 使用文件碎片操作更好
var fragment = document.createDocumentFragment();  // better

el.innerHTML = '';  // fast remove all children, but may leaks memory
el.innerHTML = 'xxx';  // ok, use it!

// 小心處理NodeList
var images = document.getElementsByTagName('img');  // be careful! dynamic list

9. 事件代理

// 使用事件代理,在更外層的元素上監聽事件
document.getElementById('list').onclick = function(evt){
    var evt = evt || window.event,
        target = evt.target || evt.srcElement;

    if(target.id === 'btn1'){
        // do something
    }
}

10. 名稱空間

// An Object as a Namespace
var MYAPP = {};
    MYAPP.dom.get = function(id){};
    MYAPP.style.css = function(el, style){};

MYAPP.namespace('event');

11. 鏈式操作

// Chaining operation: return this
function setValue(el, value){
    el.value = value;
    return this;
}

var obj = new MYAPP.dom.Element('span');
    obj.setText('hello')
    .setStyle('color', 'red')
    .setStyle('font', 'Verdana');

12. 私有作用域

// Function
(function(){
    var _private = 'cant see me';

})();

(function($){
     $('#xxb').click(function(){ });
})(jQuery);

13. 配置物件

// Configure Object
function foo(id, conf, null , null){
    // do somethin
}

foo('bar', {
    key1 : 1,
    key2 : 2
});

14. 型別轉換

// Type Conversion
+'010' === 10;
Number('010') === 10;
parseInt('010', 10) === 10;
10 + '' === '10';

+new Date() // timestamp
+new Date;

15. 擴充套件原型

// 僅在需要向前相容時才使用,其他情況不建議擴充套件原型物件
Array.prototype.forEach = function(){
    // only for forward compatible
};

16. 迴圈優化

// 快取
for(var i=0, j = document.getElementsByTagName('a').length; i0; i--){
    // maybe faster
}

// 據說是最快的
while(i--){
    // maybe fastest
}

17. 儘量使用新特新

Array.forEach();
getElementsByClassName();
querySlectorAll();

// 首先檢測是否支援新特性,能用就用
if(document.getElementsByClassName){
    // use
}else{
    // your implementations
}

18. 惰性載入

// 只判斷一次,再次呼叫該函式則無需判斷
function lazyDef(){
    if(condition1){
        lazyDef = function(){ };
    }else if(condition2){
        lazyDef = function(){ };
    }
    return lazyDef();
}

19. 私有函式與公共方法

var MYAPP = {};

MYAPP.dom = (function(){
    var _setStyle = function(el, prop, value){
        console.log('setStyle');
    };

    return {
        setStyle: _setStyle
    };
})();

// 當 MYAPP.dom.setStyle 不慎被覆寫時,_setStyle在內部仍然可用

20. 除錯

// 儘量使用,可以傳入多個引數,最後輸出拼接後的字串
console.log('xx','xx','...');
console.dir(someObj);
console.dirxml(someDom);
console.time('timer');
console.warn('xxx');

// 封裝可以保證不小心釋出出去也不會導致問題,但報錯時行號可能有問題
function msg(msg){
    if(console && console.log){
        console.log(msg);   // wrong line number
    }
}

基本上目前想到的只有這些,歡迎大家補充討論:)

相關文章