天天看點

前端js代碼規範引導:為友善自已以及其它同僚,請大家遵守前端js規範,挺高工作效率!---持續更新中…..

友情連結

引導:為友善自已以及其它同僚,請大家遵守前端js規範,挺高工作效率!---持續更新中…..

注:後端隻需遵守js規範,後面的js優化部分了解即可;

1,統一采用閉包的立即執行的方式,不要污染全局變量;

(funcction(){        
//  to do ...    

})(window)
           

2,不要污染全局變量,盡量采用局部變量的;

;(function(){    
    不規範的書寫方式:        
    var name = 'andy';        
    var age = 'lcuy';        
    ....        

    function createNums(params) {           
        var sex = 'boy';           

        var city = 'BeiJing';            
        ...        

    }    


規範的書寫方式:        
統一的類型可以new 一個公共函數        
    function createPeople(){            
        var name = 'andy',                
        age = 'lcuy',                
        sex = 'boy',                
        city = 'BeiJing';        

    }    

    })(window);
           
```






## 3,為了區分全局變量和局部變量,書寫方式如下:    


全局變量采用 $ 符   



           

如 var $name = ‘andy’;

局部變量采用 _ 符   




           

如 var _age = ‘30’;

## 4,不要想當然的建立過多的函數,統一放到一個位置,或在原型裡添加:    若是構造函數,首字母要大寫    




var Union_config = function(){        
    create:function(){            
        var Union_config = function(){             

            init:function(){   
            //  初始化函數                    
            ....                

            },                
            sumbit:function(){  
            //  送出表單資訊                    
            ...                

            },                
            ...                
            ...            

        };            

    return Union_config;        

    }    
};  


var myUnion = Union_config.create();  


//  調用函數    以下可以按需調用函數方法;


myUnion.sumbit();      ...
           

5,注釋!!!---為了友善其它同僚,自己寫代碼的時候一定要寫注釋; 若是定義的全局注釋或者函數等注釋采用标準等文檔注釋;

如:

/**@zJquery    通用js庫     
*  @author     huangzhao     
*  *  ....    
*  */

           

6,鍊式調用以及其它用法

如:  $('.div1').html('');  $('.div2').html('');  


可以寫成: $('.div1,.div2').html('');  


如:  $('.div1').css('color','red');  


$('.div1').addClass('active');  


可以寫成: $('.div1').css('color','red').addClass('active');
           

// 可以采用鍊式

7,函數命名統一采用駝峰命名法

如:

function createNums(){        
    //....    

    }
           

8,規範定義JSON對象,補全雙引号 對于JSON資料,我們推薦采用标準地書寫格式,友善檢視;

如:{name:'andy',age:'18'}  改成  {"name":"andy","age":"17"}
           

9,關于ESLite代碼檢查檢視以下連結

http://eslint.cn/docs/rules/

10,用“===“取代“==“

前者是嚴格判斷,後者會進行隐式的類型轉換;

11,關于for循環性能體驗

一般寫法:

var myarr = [" " " " " ];

    for(var i=;i<myarr.length;i++){

    //此寫法性能一般;

    }

    for(var i=,len=myarr.length;i<len;i++){
    //此寫法性能良好
    }

    for(var i=,val;val = myarr[i++]){
        console.log(i,val);
    //此寫法性能好---推薦使用
    }
           

12,統一使用縮進大小,以tab為基準;

13,var 的時候若有常量,全用大寫;

14,js中避免過多的DOM操作,需建立文檔片段;

資料較多的時候,會影響性能,如下:

for(var i=;i<;i++)


{ 
    var _span = document.createElement('span'); 

    var _text = document.createTextNode(i); 

    _span.appendChild(_text); 

    document.body.appendChild(_span); 

}
           

通過建立文檔片段來優化性能:如下:

var $frgment = document.createDocumentFragment();


for(var i=,len=;i<len;i++){


    var _span = document.createElement('span'),

        _text = document.createTextNode(i);

    _span.appendChild(_text);

    $frgment.appendChild(_span);//  先添加到文檔片段中 

}


document.body.appendChild($frgment);//  最後再綁定給要賦予的元素
           

15,如何處理onload事件要執行的多個函數?

function createNumA(){
    console.log();
}
function createNumB(){
    console.log();
}
window.onload = createNumA;//這個不會執行,被下面的覆寫了;
window.onload = createNumB;//當然,這個可以執行,覆寫了上面的onload事件
           
//  解決方法1:可以用隐式函數----此方法比較常見,便于了解
window.onload = function(){
    //都會被執行 
    createNumA();
    createNumB();
};
           
//  解決方法2:
function addEventOnload(func){
    var oldOnload = window.onload;
    if(typeof window.onload != 'function'){
        window.onload = func;
    }else{
        window.onload = function(){
            oldOnload();
            func();
        };
    }
}
//  調用方法
addEventOnload(createNumA);
addEventOnload(createNumB);
           

提示:以上兩個方法都推薦使用,看個人喜好;

16,js代碼要做到高内聚/低耦合!

高内聚:就是指某個系統子產品有一段相關行很強的代碼組成,隻負責一項任務開發,俗稱“單一責任原則”;

低耦合:一段完整的js代碼,子產品與子產品之間盡可能獨立存在,原因是可能每個子產品處理的js代碼功能不同。子產品與子產品之間的接口盡量也少而簡單。如果某個子產品比較大,盡量拆分來做,便于修改以及調用;

例如:

//  階乘函數
    function factorial(num){
        if(num <= 1 ){
            return 1;
        }else{
            return num * factorial(num-1);
        }
    };
    factorial(3);
    console.log(factorial(3));//    6=1*2*3

    //  上面的函數,這樣定義沒有問題,但問題是這個函數的執行與函數名factorail緊緊耦合在了一起。
    //  為了消除這種緊密耦合的現象,用arguments.callee來解決
    function factorial(num){
        if(num <= 1){
            return 1;
        }else{
            return num * arguments.callee(num-1);
        }
    }


    /*  注意:在函數内部,有兩個特殊的對象,arguments和this
        雖然,arguments的主要用途是儲存函數參數,但這個對象有個名叫callee的屬性,
        該屬性是一個指針,指向擁有arguments對象的函數
    */
           

17, 定義多個函數的時候,如果參數相同,可以用apply()和call()改變環境對象,得到引用

每個函數都包括非繼承而來的方法,apply()和call();
     apply()和call()方法相同,差別在于接受的參數不同而已;


    function sum(num1,num2){
        return num1 + num2;
    }
    function callSum(num1,num2){
        return sum.apply(this,arguments);
    }
    function callSum1(num1,num2){
        return sum.apply(this,[num1,num2]);
    }
    function callSum2(num1,num2){
        return sum.call(this,num1,num2);
    }
    console.log(callSum(10,10));    //10
    console.log(callSum1(10,10));   //10
    console.log(callSum2(10,10));   //10
    //  但是,傳遞參數并不是apply()和call()的真正用武之地,他們真正的強大的地方是能夠擴充函數賴以運作的作用域
    window.color = 'red';
    var $o = {"color":"blue"};
    function sayColor(){
        console.log(this.color);
    }
    sayColor();//red
    sayColor.call(this);//red
    sayColor.call(window);//red
    sayColor.call($o);//blue
           

除此,推薦大家使用ECMAScript5中定義的一個方法:bind()方法

var objSayColor = sayColor.bind($o);
    objSayColor();//blue 
           

18,不要使用eval()函數

原因:1),性能差;2),不能打斷點調試;3),容易受到攻擊;4),可讀性差;5),優化機率低;

19,減少花費在作用域鍊上的時間,增加腳本的整體性能

優化之前:

function createUi(){
        var _span = document.getElementsByTagName('span');
        console.log(_span.length);
        for(var i = 0,len = _span.length;i<len;i++){
            _span[i].title = document.title + 'txt' + i;
            console.log(i);
        }
    }
    createUi();
           

createUi中包含了二個對于全局變量document對象的引用,特别是循環中的document引用,查到次數是O(n),每次都要進行作用域鍊查找。通過建立一個指向document的局部變量,就可以通過限制一次全局查找來改進這個函數的性能。

優化之後:

function createUi(){
        var _doc = document,
            _span = _doc.getElementsByTagName('span');
        for(var i = 0,len=_span.length;i<len;i++){
            _span[i].title = _doc.title + 'txt' + i;
        }
    }
           

20,避免with()語句

缺點:1),運作緩慢;2),會建立自己的作用域,因為會增加代碼塊中執行的作用域的長度;3),難以優化;

21, 提倡對象字面量

//  避免
    var $a = new Array();
    $a[0] = 1;
    $a[1] = 'andy';
    $a[2] = 'false';

    var $obj = new Object();
    $obj.name = 'andy';
    $obj.age = 20;

//  提倡
    var $a = [1,'andy','false'];
    var $b = {
        name:'andy',
        andy:20
    } 
           

22,建議多使用innerHtml

頁面上建立DOM節點的方法有兩種:

使用諸如createElement()和appendChild()之類的DOM方法,以及使用innerHTML。

對于小的DOM更改,兩者效率差不多,但對于大的DOM更改,innerHTML要比标準的DOM方法建立同樣的DOM結構快得多。

當使用innerHTML設定為某個值時,背景會建立一個HTML解釋器,然後使用内部的DOM調用來建立DOM結構,而非基于JS的DOM調用。由于内部方法是編譯好的而非解釋執行,故執行的更快。

23,通過模闆元素clone,替代createElemnet

如果文檔中存在現成的樣闆節點,應該是用cloneNode()方法,因為使用createElement()方法之後,

你需要設定多次元素的屬性,使用cloneNode()則可以減少屬性的設定次數——同樣如果需要建立很多元素,==應該先準備一個樣闆節點==

優化之前:

var $frag = document.createDocumentFragment();
    for (var i = 0; i < 10; i++) {
        var _el = document.createElement('p');
        _el.innerHTML = i;
        $frag.appendChild(_el);
    }
    document.body.appendChild($frag);
           

優化之後:

var $frag = document.createDocumentFragment();
    var $pEl = document.getElementsByTagName('p')[0];
    for (var i = 0; i < 10; i++) {
        var _el = $pEl.cloneNode(false);
        _el.innerHTML = i;
        $frag.appendChild(_el);
    }
    document.body.appendChild($frag);
           

24,|| 和 && 布爾運算符的應用

function eventHandler(e) {
        if (!e) e = window.event;
    }

    //可以替換為:
    function eventHandler(e) {
        e = e || window.event;
    }


    if (myobj) {
        doSomething(myobj);
    }
    //可以替換為:
    myobj && doSomething(myobj);
           

25,一次性修改樣式屬性;

目的:防止頁面過多重排

優化前:

ele.style.backgroundColor = "#e6e6e6";  
ele.style.color = "#000";  
ele.style.fontSize = "12rem";
           

優化後:

.addActive {
    background: #eee;
    color: #093;
    height: px;
}
           

26,操作DOM前,先把DOM節點删除或隐藏,因為隐藏的節點不會觸發重排

優化前:

var $items = document.getElementsByClassName('mydiv');

for (var i=; i < $items.length; i++){  
    var _item = document.createElement("li");  
    _item.appendChild(document.createTextNode("Option " + i);  
    $items[i].appendChild(_item);  
}
           

優化後:

$items.style.display = "none";  
for (var i=; i < items.length; i++){  
    var _item = document.createElement("li");  
    _item.appendChild(document.createTextNode("Option " + i);  
    $items[i].appendChild(_item);  
}  
$items.style.display = "";
           

DOM的核心問題是:DOM修改導緻的頁面重繪、重新排版!重新排版是使用者阻塞的操作,同時,如果頻繁重排,CPU使用率也會猛漲!

27,用數組方式來周遊Dom對象集合;

html:

<ul id="testList" >
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li> 
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
        </ul>
           

js:

1),each:

var $arr = $('li'),
        $KPI = ;
console.time('Each需要花費的時間');
    for(var i=;i<$KPI;i++){
        $arr.each(function(i,val){
            this;
        });
    }
    console.timeEnd('Each需要花費的時間');
           

2),數組array實作

var $arr = $('li'),
        $KPI = ;
    //  array實作
    console.time('Array需要花費的時間');
    for(var i=;i<$KPI;i++){
        var _len = $arr.length;
        for(var j=;j<_len;j++){
            $arr[i];
        }
    }
    console.timeEnd('Array需要花費的時間');
           

總結:經過測試,在性能方面,對于each方法這種優雅實作是有代價的。花費的時間長;然而通過數組來實作, Dom對象集合就是一個類數組,具有length和value屬性。花費時間短;

28,不要在函數體内做過多的嵌套判斷;

優化前:

function createNums(){
    var _r = {};
    _r.data = {};
    _r.data.age = 20;
    if(_r){
        if(_r.data){
            if(_r.data.age){
                console.log('true');
            }else{
                console.log('false');
            }
        }
    }
}
createNums();
           

優化後:

function createNums1(){
    var _r = {};
    _r.data = {};
    _r.data.age = 20;
    if(!_r){
        return;
    }
    if(!_r.data){
        return;
    }
    if(_r.data.age){
        console.log('true');
    }else{
        console.log('false');
    }
}
createNums1();
           

29,适當用while代替for循環,可以提高性能;如數組元素與排序無關的情況

var $date = new Date();
var $arrs = [1,1,2,3,4,5,6,7,8,9,10,11,11,22,33,44,555,55555555555555,555,55,55,32,32,8,8,8,8,1324123414],
    $sum = 0,
    $len = $arrs.length;
           

優化前:

for(var i=;i<$len;i++){
        $sum += $arrs[i]; 
    }
    console.log($sum);
    console.log(new Date() - $date);
           

優化後:

while($len --){
    $sum += $arrs[$len];
}
console.log($sum);
console.log(new Date() - $date);
           

提示:資料小的情況下可能差别不大,如果資料量比較大,第二種寫法效果就比較明顯了;大家可根據情況應用,一般情況下要知道,能用for循環的就不要用for..in循環(因為for.in循環會自動在背景建立一個枚舉器,比較損壞性能),此外,能用while循環的盡量不要用for循環;最後也推薦大家用下do..while循環(前三種是前測試循環,最後一個是後測試循環);

30,關于閉包的問題解決方法:

html:

<span>1</span>
<span>2</span>
<span>3</span>
           

js:

var _doc = document,
            _span = _doc.getElementsByTagName('span');
        for(var i = ,len=_span.length;i<len;i++){
                _span[i].onclick = function(){
                    console.log(i);
                }
        }
        //提示;我們會發現列印出來的都是 3;這就是所謂的閉包
           

1),閉包的問題用閉包的方法去解決

解決思路:

增加若幹個對應的閉包空間(這裡是匿名函數),專門用來存儲原來需要引用的下标;

var _doc = document,
        _span = _doc.getElementsByTagName('span');
    for(var i = 0,len=_span.length;i<len;i++){
        (function(arg){ //
            _span[i].onclick = function(){  //onclick函數執行個體的function scope的closole 對象屬性有一個引用arg,隻要外部空間的arg不變,這裡的引用值也不會改變 
                console.log(arg);
            }
        })(i);
    }
           

2),将下标作為對象屬性(name:’i’,value:’i’的值)添加到每個數組項中;

var _doc = document,
        _span = _doc.getElementsByTagName('span');
    for(var i = 0,len=_span.length;i<len;i++){
            _span[i].i =i;  //為目前數組項目即目前span對象添加一個名為i的屬性,值為循環體的i變量的值;
            _span[i].onclick = function(){//此時目前span的對象的i屬性并不是循環體i變量的引用,而是一個獨立span對象的屬性,屬性值在聲明的時候就确定了;
                console.log(this.i);
            }

    }
           

3),閉包方法的延伸

//  此方法和方法1類似但又有不同;
//  相同點:都是增加若幹個對應的閉包空間來存儲下标;
//  不同點:方法1是在新增的匿名閉包空間完成事件的綁定;方法3是将事件綁定在新增的匿名函數傳回的函數上;
        var _doc = document,
            _span = _doc.getElementsByTagName('span');
        for(var i = ,len=_span.length;i<len;i++){
                _span[i].onclick = (function(arg){
                    return function(){
                        console.log(arg);
                    }
                })(i);

        }
           

總價:以上3中方法都可以,看個人喜好!

溫馨提示:zQuery位址:https://github.com/hzaini1989/zQuery

繼續閱讀