编写高质量JavaScript代码的基本技巧

一、尽量少用全局变量

减少全局名字空间污染,最理想的情况是一个应用程序仅有一个全局变量。

二、单一var模式

var a = 1,
    b = 2,
    sum = a + b,
    c;

只使用一个var在函数顶部进行变量声明,其好处:

  • 提供一个单一的地址以查找到函数需要的所有局部变量;

  • 防止出现变量在定义之前就被使用的逻辑错误;

  • 帮助牢记要声明变量,以尽可能少地使用全局变量;

  • 更少的代码(无论是输入代码还是传输代码都更少了)。

三、for循环

for (var i = 0; i < dom.length; i++) {
    //DO STH
}

每一次循环都查询dom的长度是很消耗时间的,把dom.length缓存起来,这样,对长度的值只提取一次,但能应用到整个循环中。

用i++替代以下两种表达式:i = i + 1; i += 1;

四、for-in循环

for-in循环应该用来遍历非数组对象。使用for-in循环也被称为枚举(enumeration)。
从技术上来说,也可以使用for-in循环来遍历数组(因为在JavaScript中,数组也是对象),但是不推荐用户这样使用,因为当该数组对象已经被自定义函数扩大后,这样做有可能导致逻辑上的错误。因此,推荐使用正常的for循环来处理数组,使用for-in循环来处理对象。

当遍历对象属性来过滤遇到原型链的属性时,推荐使用hasOwnProperty()函数。

五、不要增加内置的原型

增加内置构造函数(如Object(),Array()和Function()等)的原型属性是一个增强功能性的强大的方法,但这可能会严重影响可维护性,因为这种做法将使代码变得更加不可预 测。其他开发者在使用您的代码时可能期望内置的JavaScript方法的使用是一致的,而不期望有一些您自己添加的方法。

此外,给原型添加的属性在没有使用hasOwnProperty()时可能会在循环中出现,这会导致一些混乱。

六、switch模式

var inspect_me = 0,
    result = '';
switch (inspect_me) {
    case 0:
        result = "zero";
        break;
    case 1:
        result = "one";
        break;
    default:
        result = "unknown";
}
  • 在每个case语句中使用代码缩进;

  • 在每个case语句结尾有一个明确的break语句;

  • 避免使用fall-throughs(也就是有意不使用break语句,以使得程序会按顺序一直向下执行),如果确实希望采用fall-throughs,那么请确信在代码中使用fall-throughs的确是最好的途径,因为在代码中这样做会让其他阅读您代码的人以为代码是有错误的;

  • 用default语句来作为switch的结束:当以上所有情形都不匹配时,给出一个默认的结果。

七、避免使用隐式类型转换

在使用比较语句的时候推荐使用===和!===操作符来对数值和类型进行比较。JS代码质量检查工具——JSLint,要求严格的等价比较,这样的做法会使得代码看起来更为一致,并减少在阅读代码时的脑力开销(==的使用是故意的还是无意遗漏的)。

八、避免使用eval()

“eval( )是一个魔鬼”

九、使用parseInt()的数值约定

parseInt(string, radix);

参数string:要被解析的值。如果参数不是一个字符串,则将其转换为字符串。字符串开头的空白符将会被忽略。
参数radix:一个2到36之间的整数值,用于指定转换中采用的基数。比如参数"10"表示使用我们通常使用的十进制数值系统。总是指定该参数可以消除阅读该代码时的困惑并且保证转换结果可预测。当忽略该参数时,不同的实现环境可能产生不同的结果。

在没有指定基数,或者基数为 0 的情况下,JavaScript 作如下处理:

  • 如果字符串 string 以"0x"或者"0X"开头, 则基数是16 (16进制);

  • 如果字符串 string 以"0"开头, 基数是8(八进制)或者10(十进制),那么具体是哪个基数由实现环境决定。ECMAScript 3认为是八进制;ECMAScript5认为是十进制。因此,永远都要明确给出radix参数的值。

  • 如果字符串 string 以其它任何值开头,则基数是10 (十进制)。

详细资料参考:MDN-parseInt

十、编码约定

确定并一致遵循约定比这个具体约定是什么更为重要。

  • 缩进
    需要对哪些内容执行缩进?规则是只需要对大括号中所有的代码执行缩进。主要包含函数体、循环体(do、while、for、for-in)、if语句、switch语句和对象字面量引用的属性。

  • 大括号

    • 一直使用大括号
      应该经常使用大括号,甚至在可选的情形下,都请使用大括号(if语句for语句只有一行语句的时候)

    • 将开放的大括号放置在前面语句的同一行
      开放的大括号放置的位置一般有两种选择:

        //大括号和语句放在同一行
        if (true) {
            alert("It's True!");
        }
      
        //大括号放在接下来的一行
        if (true) 
        {
            alert("It's TRUE!");
        }

      采用哪种方式只是个人习惯的不同,但是有些情况下随着大括号的位置不同,程序的执行结果也会有所不同,这是由分号插入机制(semicolon insertion mechanism)导致的。JavaScript对代码不会很挑剔,当没有正确使用分号结束本语句时,它会自动补上。该行为在函数返回一个对象字面量并且开放的大括号位于接下来的一行时会导致问题:

        function func() {
            return
            {
                name: "Jason"
            };
        }
        //由于分号插入机制,上面的写法等价于下面的写法
        function func() {
            return;
            {
                name: "Jason"
            };
        }

      函数func返回的结果是undefined,而不是期望的对象{name: "Jason"},所以推荐将开放的大括号放置在前面语句的同一行。

  • 在语句的末尾一直使用分号

  • 空格
    使用空格有助于改善代码的可读性和一致性。使用空格比较好的位置包含如下:

    • 操作符(+ - * = == < > <= >= === !== && || +=等)的前后

    • 在分开for循环的各个部分的分号之后:

        for (var i = 0; i < 10; i += 1) {}
    • 在限定数组项的逗号后面:

        var a = [1, 2, 3];
    • 对象属性的逗号之后和将属性名和属性值分开的冒号之后:

        var o = {a: 1, b: 2};
    • 分隔开函数中各个参数的逗号之后:

        myFunc(a, b, c)
    • 在函数声明的大括号之前:

        function myFunc() {}
    • 匿名函数关键字function之后( )之前:

        var myFunc = function () {};
    • 在函数中使用大括号开始符之前,例如if-else语句、循环语句和对象字面量等

    • 在大括号结束符和else或while之间

    • 一个常用的增加可读性的做法是使用垂直的空格——使用空行来分隔代码的不同单元

十一、命名约定

  • 构造函数的首字母大写

       var jason = new Person();
  • 分隔单词

    • 构造函数——大骆驼峰式命名法:MyConstructor( )

    • 函数和方法——小骆驼峰式命名法:myFunction( )、calculateArea( )

    • 变量——小骆驼峰式命名法或者所有的单词都使用小写,并用下划线分隔开各个单词 :first_name、sold_company_name。推荐使用后者,这样根据名字就能明显地区分出变量、函数和基本常量等。

  • 其他命名模式

    • 常量:将变量名全部大写来表明该变量在程序生命周期中不可改变

        //精确的常量,请不要修改
        var PI = 3.14,
            MAX_WIDTH = 800;
    • 为全局变量命名时,约定将所有的字符大写

        var GLOBAL_TIP = "Hello World";
    • 使用一个下划线前缀来标识私有方法或私有属性

        var person = {
            _nickName: "jason",
            getName: function () {
                return this._nickName + this._getFirst() + '' + this._getLast();
            },
            _getFirst: function () {
                //...
            },
            _getLast: function () {
                //...
            }
        }

      getName( )意味着这是API的一个公开的方法,而_getFirst( )和_getLast( )意味着这是一个私有函数,_nickName意味着这是一个私有属性。尽管它们都是普通的公开方法和属性,但是使用下划线前缀的表示方法可以提醒使用person对象的用户,告诉他们这些方法在其他地方不能确保一定能够正常工作,不能直接调用。

十二、编写注释

注释的重要性就不用言表了,当你看到一份通篇都是代码而没有一个注释的文件时,心中也是一万头草泥马奔腾而过吧。

不需要注释一些比较明显的代码:例如每一个变量或每一行都注释。但通常有必要对所有的函数、函数参数、返回值和其他有趣或不同寻常的算法和技术都用文档记录下来。

最重要的习惯,也是最难遵循的习惯就是不断更新注释,因为过期的注释可能会误导阅读者,这比没有注释还可怕。


参考:《JavaScript模式》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值