JS代码规范.md 9.07 KB

JavaScript代码规范

行的长度

每行长度不应该超过120个字符,如果一行多余120个字符,应该在一个运算符后换行,下一行增加2级缩进,即8个空格)

doSomething(argument1, argument2, argument3, argument4,
        argument5);

运算符间距

二元运算符前后必须使用一个空格保持表达式的整洁,操作符包括赋值运算符和逻辑运算符

var name = 'xuqi'; //GOOD
var name='xuqi'; //BAD

括号间距

当使用括号时,紧接左括号之后和紧接右括号之前不应该有空格。

doSomething(arg);//GODD
doSomething( arg );//BAD

字符串

  1. 使用单引号并保持一行,禁止在字符串中使用\另一起行;
  2. 断行后字符串与上一行对齐

    //GOOD
    var str = 'I am a programer.I love JS and' +
              'Node';
    //BAD
    var str = 'I am a programer.I love JS and \
            Node';

空行

  • 方法之间添加空行分隔
  • 单行或多行注释前添加空行
  • 逻辑块之间添加空行增加可读性

null使用场景

  • 用来初始化一个变量,该变量可能被赋值为一个对象
  • 用来和一个已经初始化的变量比较
  • 当函数的参数期望为对象时,被用作参数传入
  • 当函数的返回值期望是对象时,被用作返回值传出

undefined

禁止使用name === undefined判断一个变量是否定义。应该使用typeof(name) === 'undefined';

对象直接量

  • 起始左括号应该与表达式保持一行
  • 每个属性的键名前保持一个缩进,第一个属性应该在左括号后另一起行
  • 每个属性的键名不包含引号,其后跟一个冒号(前无空格,后有空格),然后是值
  • 如果属性值为函数,函数体应该在属性名之下另起一行,并且其前后均应保留一个空行
  • 一组相关属性的前后插入空行以提高代码的可读性
  • 结束的右括号独占一行

    var person = {
        name: 'xuqi',
        age: 25,
        //
        groupAttr1_1: xx1,
        groupAttr1_2: xx2,
        //
        walk: function() {
            //
        }
    };
  • 当对象字面量作为函数参数时,起始括号应该与函数名同行

    doSomething({
        //do something
    });

声明

变量

  • 所有变量在使用前应该先定义
  • 变量定义应该放在函数开头
  • 使用一个var表达式定义变量,每行定义一个
  • 除了首行,所有行都应该多一层缩进使变量声明对齐
  • 初始化的变量放在未初始化的变量之前
  • 所有的变量命名必须使用英文单词
  • 浮点变量必须指明实部(即便以0.开头)和小数点后一位

    var name = 'xuqi',
        age,
        sex,
        ...

另外,变量名需要给出注释,否则别人很难读懂接下来代码的意思。

变量术语约定

变量可以按照一定规则命名也表示某些特定功能,比如:

  • is前缀可以表示boolean值
  • num或者count表示计数
  • 错误加上Exception或者Error后缀
  • ...

函数

  • 函数在使用前应该先定义
  • 函数名和开始圆括号之间无空格(包括匿名函数的function关键字与圆括号之间)
  • 开始圆括号和结束圆括号之间无空格
  • 参数名之间应该在逗号之后保留一个空格
  • 开始花括号应该同function关键字保持同一行,结束圆括号和开始花括号之间应该保留一个空格
  • 函数体保持一级缩进

    function doSomething(arg1, arg2) {
        doThing1();
        doThing2();
    }
    //
    var method = function() {
        doSomething();
    };

另外,IIFE的标准格式也在这里指出:

(function(args) {
    //
}(args)); //(args)位于外层括号内

其他声明函数需要注意的方面:

  • 循环中切勿加入函数,很容易因为闭包的原因造成错误。

    //BAD
    for(i = 0; i < 3; i++) {
        setTimeout(function() {
            console.log(i);
      }, 0);
    }
  • “代码块”中切勿加入函数声明,混淆作用域

    //BAD
    if (conditions) {
        function() {
            //doSomethings
        }
    }

命名

变量:

  • 采用小驼峰命名格式
  • 变量命名为名词(区别函数)
  • 变量中不使用_

常量:

  • 所有字符大写,不同单词之间适用单个下划线隔开

函数:

  • 采用小驼峰命名格式
  • 函数命名为动词(区别变量)
  • 函数名中不使用_

构造函数:

  • 采用大驼峰命名格式
  • 命名应该是名词

私有成员:

  • 一个对象中不希望外部访问的以下划线开头(约定)

表达式

赋值

当给变量赋值时,如果右侧是含有比较语句等形式的表达式时,用圆括号包裹

var flag = (i < count);//GOOD
var flag = i < count;//BAD

等号运算符

使用===!==,禁止使用==!=

三目运算符

三目运算符应该仅仅使用在条件赋值语句中,禁止作为if的替代品

var val = codition ? val1 : val2;//GOOD
condition ? dothing1() : dothing2();//BAD

语句

每一行只包含一条语句,所有简单语句都应该以分号结束

return语句

当返回语句返回一个值的时候不应该使用圆括号包裹,除非在某些情况下这么做可以让返回值更容易理解

return abc;//GOOD
return (abc);//BAD
return (size > 0 ? size : default);//GOOD

if语句

if (condition) {
    doSomething();
} else if (condition1) {
    doSomething2();
} else {
    soOtherThing();
}

for语句

//GOOD
var i;
for (i = 0; i < len; i++) {
    doSomething();
}
for (i in collection) {
    if (collection.hasOwnProperty(i)) {
        doSomething();
    }
}
//BAD
for (var i = 0; i < len; i++) {
    doSomething();
}
for (i in collection) {
    doSomething();
}

while,do语句

while (condition) {
    doSomething();
}
do {
    doSomething();
} while (condition)

switch语句

  • 每一个case保持一个缩进,除第一个之外包括default在内的每一个case都应该在之前保留一个空行
  • 每一组语句都应该以break,return等结尾,或者用一行注释表示跳过(falling through)
  • 无default的情况也要注释特别说明

    switch (val) {
        case 1:
            //nothing
    
        case 2:
            doSomething();
            break;
    
        default:
            doDefault();
    }

try语句

    try {
        doSomething();
    } catch (err) {
        doSomething2();
    } finally {
        doSomething3();
    }

其他规范

  • 禁止使用String等原始包装类型创建对象
  • 禁止使用eval和with
  • 避免使用try...catch...
  • 使用for...in...的时候要添加hasOwnProperty判断
  • 不给setTimeout和setInterval传递字符串参数,那就等同于eval了

模块化规范

CommonJs/CMD规范:

  • 一个单独的文件就是一个模块,每个模块都有单独的作用域
  • 模块标识可以为文件路径或者spm的包名称。require默认读取js文件,因此读取路径时可以省略.js后缀
  • 模块与外部通信的桥梁为module.exports对象,通过exports.api可以对外抛出api接口。当然如果有需要,也可以通过module.exports = ...指定模块返回的内容而不仅仅是一个对象
  • 模块引用通过require('module')可以获取module暴露的所有的接口

模块代码规范说明:

  • 模块开头require加载所有依赖模块和JQ插件。如果是spm的依赖包,只要模块名即可,如果不是,需要写引用模块的相对路径+模块名

    var $ = require('jquery'),
        tools = require('yoho-tools'), //spm包
        flip = require('../plugin/flip'); //普通文件
    
    require('../plguin/login');
    ..
  • 定义需要抛出的接口

    exports.init = function() {
        //doInit
    };
    
    exports.show = function() {
        //doShow
    };
    ...
  • 模块中不应该出现全局环境使用的变量或函数,这样可以保证模块的独立性

  • 模块抛出接口应该给予注释说明功能和使用方法

其他事项

JS文件说明

/**
 * 文件功能描述
 * 使用方法
 * author
 * date
 */

函数的说明也采取类似格式:

/**
 * 函数功能描述
 * @param ...
 * @returns ...
 */

标签说明

JQuery插件规范

  • 文件命名为jquery.plugin-name.js
  • 所有新方法附加到jquery.fn对象,所有新功能附加到jquery对象
  • this用于引用jquery对象
  • 插件的开头带一个;,防止代码合并出现问题
  • 除特殊注明外,所有方法必须返回jquery对象以便于链式调用
  • 使用this.each迭代匹配的元素
  • 在插件代码中使用JQuery而不是$,减少命名冲突对我们的影响