前端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=0;i<myarr.length;i++){

    //此写法性能一般;

    }

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

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

12,统一使用缩进大小,以tab为基准;

13,var 的时候若有常量,全用大写;

如  var  KPI = 123;

14,js中避免过多的DOM操作,需创建文档片段;

数据较多的时候,会影响性能,如下:

for(var i=0;i<500;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=0,len=500;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(1);
}
function createNumB(){
    console.log(2);
}
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: 200px;
}
document.getElementById(‘myDiv’).className = ‘addActive’;

26,操作DOM前,先把DOM节点删除或隐藏,因为隐藏的节点不会触发重排

优化前:

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

for (var i=0; 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=0; 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 = 1000000;
console.time('Each需要花费的时间');
    for(var i=0;i<$KPI;i++){
        $arr.each(function(i,val){
            this;
        });
    }
    console.timeEnd('Each需要花费的时间');

2),数组array实现

var $arr = $('li'),
        $KPI = 1000000;
    //  array实现
    console.time('Array需要花费的时间');
    for(var i=0;i<$KPI;i++){
        var _len = $arr.length;
        for(var j=0;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=0;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 = 0,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 = 0,len=_span.length;i<len;i++){
                _span[i].onclick = (function(arg){
                    return function(){
                        console.log(arg);
                    }
                })(i);

        }

总价:以上3中方法都可以,看个人喜好!
温馨提示:zQuery地址:https://github.com/hzaini1989/zQuery

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值