微软的Javascript代码规范

<本方译自http://www.asp.net/ajaxlibrary/act_contribute_codingStandards_Programming.ashx。原文主要针对ASP.net的Ajax 控件工具箱,但多数准则亦普遍适用于javascript编程>

本节的主题是帮助程序员防止一些常见的错误,或者强调一些可以明显提高性能、可维护性或者可支持性的惯例。

5.1  变量声明

所有变量都应该使用var来声明,以减少遍历作用域链(scope chain)的额外开销。除非绝对必要,不要使用全局变量,因为它们查找起来总是最慢的。变量应该被初始化为缺省值或者null。例:

var counter = 0; 

var empty = null; 

建议将所有变量声明都放在函数头部。将变量分组声明以减少脚本的大小。如:

var counter = 0, empty = null;

Javascript没有块作用域的概念;因此定义在函数内部的"if"或"for"块中的变量,可以在该函数内的任意地方访问。因此,对javascript来说是享受不到任何变量延迟定义的好处的。

<译注:

当必须使用全局变量时,可以使用Global Import  模式,将全局变量导入成为局部变量,这样在需要使用原全局变量的时候改为使用导入的局部变量,从而减少了作用域链查找的代价。

在变量分组声明上,Dojo的观点是,只能将逻辑上相关联的一组变量放在一起声明。如果没有逻辑上的关联,则变量必须每个单独成行声明。可读性高于一切。毕竟,这种做法并不会显著提升性能。>

避免使用"with"语句。它不只是降低了代码的可读性,而且对性能亦有损伤。

<译注:在VBA中使用with语句倒是加快性能的方法。此一时,彼一时也。不过此前根本就不知道javascript还支持with语法>

5.2 函数快捷方式

<译注: 不理解何为function shourtcuts。 疑为IE独门绝技?>

Avoid using function shortcuts such as $get within script that must coexist on a page with other scripts, or may do in the future. This is to avoid other scripts reassigning a global shortcut to an alternative function, which may cause your script to fail.
Instead use fully qualified function calls whenever a script may be reused in uncertain or shared circumstances, or for non-global functions use a closure as described in section 3.7.1.

5.3  函数别名

当需要在一个循环中调用某个函数多次时,可以使用函数别名以减少作用域链的查找,例:

function doSomething() {
    var get = getDataByIndex;
    for (var counter = 0; counter < 10000; counter++) {
        var current = get(counter);
        // ...code removed  
   }
} 

注意在使用别名时,函数一定要设计成允许这样使用。比如依赖于"this"的函数可能就不能被成功地通过别名来引用。

5.4  比较和相等

任何时候只要可能,都使用严格相等符号("===")来决定两个值是否相等。这样可以避免隐藏的类型转换,而且确保精度的责任也不由程序员来承担。例:

如果"x"和"y"都有数值型值:

错误: if (x==5 && y != 4)

正确: if (x === 5 && y !== 4)

5.5  Undefined和null

不要在使用undefined和null关键字上摇摆不定,确保任何字段或变量都初始化为确定值或者为null;

this._result = null;

如果不象上面这样声明,意味着_result将是undefined。

当测试一个类实例变量是否有值,或者一个可选参数是否提供给一个函数时,且该变量/参数确定为一个对象是,使用下面的语法:

    if (message) {
        // message was provided and not null  
    } 

5.6  循环和递归

循环和递归都会放大低性能代码的影响力。因此必须从一开始就坚持好的惯例,而且在必要时进行优化。一些好的编程习惯如:

将一些代价昂贵的调用从重复代码中移到外层来。如不变的try/catch块和if-else分支就应该移到外层去。

错误:

    for (var counter = 0; counter < 10000; counter++) {
            try {
                performAction();
            } catch (e) {
                alert('Failure: ' + e);
                break;
            }
        }  

正确:

    try {
        for (var counter = 0; counter < 10000; counter++) {
            performAction();
            }
    } catch (e) {
            alert('Failure: ' + e);
        } 

如果退出条件的计算很昂贵,也将它移出来。

错误:

    try {
        for (var counter = 0; counter < 10000; counter++) {
            performAction();
            }
    } catch (e) {
            alert('Failure: ' + e);
        }  

正确:

var target = document.getElementsByTagName('div').length;
for (var counter = 0; counter < target; counter++) {
    performAction();
} 

在上面的例子中,对函数getElementsByTagName的调用会导致每个迭代时都重新计算DOM树一次。这应该并不是假想中必须完成的行为。如果将这个调用移出循环的话,也要确保performAction调用不会修改循环的集合。

在同一个函数的多个循环中使用同一个循环变量,以避免多次声明同一变量。

错误:

    for (var counter = 0; counter < 10; counter++) {
        performAction();
        };
    for (var counter = 0; counter < 10; counter++) {
        performOtherAction();
        };  


正确:

var counter;
for (counter = 0; counter < 10; counter++) {
    performAction();
    };
for (counter = 0; counter < 10; counter++) {
    performOtherAction();
    };

<译注: 改正后的代码在第一个循环前即声明了变量var counter,并在后面两个循环中都使用同一变量。比错误的例子小了一次声明。注意这个改动能提升的性能十分有限,如果这样做会牺牲代码的可读性/可维护性,则显见得不偿失。>

5.7  DOM操作

5.7.1  批量修改

通过Javascript来操作DOM是十分昂贵的,而且为引起浏览器重新生成文档流。为减少DOM树更新和屏幕重绘次数,应该对DOM进行批量修改,一次更新。

避免拼接HTML到文档元素的innerHTML属性(例如使用 += 操作符),这会在DOM树更新之前就产生一次大的字符串拼接。

5.7.2  循环引用

在DOM元素和Javascript对象之间的循环引用会造成一些老旧的浏览器的内存泄漏。尽管这一问题现在已大为好转,但对internet应用来讲仍然必须仔细考虑。请参见"Understanding and Solving Internet Explorer Leak Patterns"

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值