代码规范
源文件
[强制] JavaScript源文件必须以无BOM的UTF-8编码。
缩进
[强制] 必须采用4个空格缩进,不允许以Tab制表符或2个空格代替。
[强制] switch 中的 case 和 default 必须保持缩进。
1// 正例 2switch (variable) { 3 case '1': 4 // do... 5 break; 6 case '2': 7 // do... 8 break; 9 default: 10 // do... 11} 12 13// 反例 14switch (variable) { 15case '1': 16 // do... 17 break; 18case '2': 19 // do... 20 break; 21default: 22 // do... 23}
空格
[强制] 二元运算符两个操作数之间必须使用空格,但一元运算符与其操作数间不能有空格。
1let a = !arr.length; 2a++; 3a = b + c;
[强制] 在 { 前必须有1个空格。
1// 正例 2 3if (condition) { 4} 5 6set('attr', { 7 some: 'xxx', 8 any: 'yyy' 9}); 10 11function funcName() { 12} 13 14 15// 反例 16 17if (condition){ 18} 19 20set('attr',{ 21 some: 'xxx', 22 any: 'yyy' 23}); 24 25function funcName(){ 26}
[强制] if / else / for / while / function / switch / do / try / catch / finally 等关键字与括号之间都必须加一个空格。
1// 正例 2 3if (condition) { 4} 5 6while (condition) { 7} 8 9(function () { 10})(); 11 12 13// 反例 14 15if(condition) { 16} 17 18while(condition) { 19} 20 21(function() { 22})();
[强制] 在创建对象的语句中,: 后必须加一个空格,: 前不能有空格。
1// 正例 2const obj = { 3 a: 1, 4 b: 2, 5 c: 3 6}; 7 8// 反例 9const obj = { 10 a : 1, 11 b:2, 12 c :3 13};
[强制] 在函数声明、命名函数表达式和函数调用时,函数名称和 ( 间不能有空格。
1// 正例 2 3function funcName() { 4} 5 6const funcName = function funcName() { 7}; 8 9funcName(); 10 11 12// 反例 13 14function funcName () { 15} 16 17const funcName = function funcName () { 18}; 19 20funcName ();
[强制] , 和 ; 前不能有空格。
1// 正例 2callFunc(a, b); 3 4// 反例 5callFunc(a , b) ;
[强制] ( 和 [ 之后、 ) 和 ] 之前不能有空格。
1// 正例 2 3callFunc(param1, param2, param3); 4 5save(this.list[this.indexes[i]]); 6 7needIncream && (variable += increament); 8 9if (num > list.length) { 10} 11 12while (len--) { 13} 14 15 16// 反例 17 18callFunc( param1, param2, param3 ); 19 20save( this.list[ this.indexes[ i ] ] ); 21 22needIncreament && ( variable += increament ); 23 24if ( num > list.length ) { 25} 26 27while ( len-- ) { 28} 29 30 31// 正例 32const arr1 = []; 33const arr2 = [1, 2, 3]; 34const obj1 = {}; 35const obj2 = {name: 'obj'}; 36const obj3 = { 37 name: 'obj', 38 age: 20, 39 sex: 1 40}; 41 42// 反例 43const arr1 = [ ]; 44const arr2 = [ 1, 2, 3 ]; 45const obj1 = { }; 46const obj2 = { name: 'obj' }; 47const obj3 = {name: 'obj', age: 20, sex: 1};
[强制] 每行代码后不能有尾随空格。
换行
[强制] 必须在语句的结尾换行。
[强制] 单行字符数不能超过120个,超出则需要换行。
[强制] 如果需要换行,运算符必须放在新行的开头。
1// 正例 2if (user.isAuthenticated() 3 && user.isInRole('admin') 4 && user.hasAuthority('add-admin') 5 || user.hasAuthority('delete-admin') 6) { 7 // Code 8} 9 10const result = number1 + number2 + number3 11 + number4 + number5; 12 13 14// 反例 15if (user.isAuthenticated() && 16 user.isInRole('admin') && 17 user.hasAuthority('add-admin') || 18 user.hasAuthority('delete-admin')) { 19 // Code 20} 21 22const result = number1 + number2 + number3 + 23 number4 + number5;
[强制] 如果括号中的内容有多行,必须为 )、 ]、 } 另开一个新行,并使新行与 (、 [、 { 所在行的缩进相对应。
1// 正例 2if (product) { 3 product.load(); 4 if (user.isAuthenticated() 5 && user.isInRole('admin') 6 && user.hasAuthority('add-admin') 7 ) { 8 sendProduct(user, product); 9 } 10} 11const arr = [ 12 'candy', 'sugar' 13]; 14 15// 反例 16if (product) { 17 product.load(); 18 if (user.isAuthenticated() 19 && user.isInRole('admin') 20 && user.hasAuthority('add-admin')) { 21 sendProduct(user, product); 22 } 23} 24const arr = [ 25 'candy', 'sugar' 26 ];
[强制] , 或 ; 前不能有换行。
1// 正例 2const obj = { 3 a: 1, 4 b: 2, 5 c: 3 6}; 7 8foo( 9 aVeryVeryLongArgument, 10 anotherVeryLongArgument, 11 callback 12); 13 14 15// 反例 16const obj = { 17 a: 1 18 , b: 2 19 , c: 3 20}; 21 22foo( 23 aVeryVeryLongArgument 24 , anotherVeryLongArgument 25 , callback 26);
[推荐] 建议换行和缩进遵循如下风格:
1if (user.isAuthenticated() 2 && user.isInRole('admin') 3 && user.hasAuthority('add-admin') 4) { 5 // Code 6} 7 8foo( 9 aVeryVeryLongArgument, 10 anotherVeryLongArgument, 11 callback 12); 13 14baidu.format( 15 dateFormatTemplate, 16 year, month, date, hour, minute, second 17); 18 19$('#items') 20 .find('.selected') 21 .highlight() 22 .end(); 23 24const result = thisIsAVeryVeryLongCondition 25 ? resultA : resultB; 26 27const res = condition 28 ? thisIsAVeryVeryLongResult 29 : resultB;
[强制] 如果使用多行代码块,else 和 catch 必须另开一个新行。
1// 正例 2 3if (condition) { 4 // some statements; 5} 6else { 7 // some statements; 8} 9 10try { 11 // some statements; 12} 13catch (ex) { 14 // some statements; 15} 16 17 18// 反例 19 20if (condition) { 21 // some statements; 22} else { 23 // some statements; 24} 25 26try { 27 // some statements; 28} catch (ex) { 29 // some statements; 30}
语句
[强制] 语句必须以 ; 结尾。
[强制] 如果只有一行,{} 不能被省略。
1// 正例 2if (condition) { 3 callFunc(); 4} 5 6// 反例 7if (condition) callFunc(); 8if (condition) 9 callFunc();
[强制] 函数定义的末尾不能有分号 ;。
1// 正例 2function funcName() { 3} 4 5// 反例 6function funcName() { 7}; 8 9// 对于函数表达式,不能忽略分号 10const funcName = function () { 11};
[强制] 对象和数组的声明中不能有尾随逗号。
1// 正例 2 3const obj = { 4 attr1: 'xxx', 5 attr2: 'yyy' 6}; 7 8const arr = [ 9 'xxx', 10 'yyy' 11]; 12 13 14// 反例 15 16const obj = { 17 attr1: 'xxx', 18 attr2: 'yyy', 19}; 20 21const arr = [ 22 'xxx', 23 'yyy', 24];
命名规约
[强制] 变量名、属性名及函数名的命名必须遵循 lowerCamelCase(小骆驼拼写法)。
1const loadingModules = {}; 2function loadProduct() { 3}
[强制] class类的命名必须遵循 UpperCamelCase (Pascal),即大骆驼拼写法(帕斯卡拼写法)。
1function Element(options) { 2}
[推荐] 缩略词的所有字符应当一并大写或一并小写。
1function parseSVG() { 2} 3const svgParser;
语法特性
兼容性
语法特性可以通过一些工具方法进行弥补,但不能通过修改内置JavaScript对象的原型来实现。
1// 正例 2 3import * as zrUtil from 'zrender/src/core/util'; 4 5zrUtil.each(array, function (val, index) { 6 sum += val; 7}); 8 9const result = zrUtil.map(array, function (val) { 10 return parse(val); 11}); 12 13const pos = zrUtil.indexOf(array, val); 14 15const obj2 = zrUtil.extend({}, obj1); 16 17function Element() { 18 // ... 19} 20 21 22// 反例 23 24array.forEach(function (val, index) { 25 sum += val; 26}); 27 28let result = array.map(function (val) { 29 return parse(val); 30}); 31 32const pos = array.indexOf(val); 33 34const obj2 = Object.assign({}, obj1); 35 36class Element { 37 // ... 38} 39 40String.prototype.trim = function () { 41};
变量
[强制] 优先使用const声明变量,且一行不能同时声明多个变量。
1// 正例 2const name = 'MyName'; 3const hangModules = []; 4const missModules = []; 5const visited = {}; 6 7// 反例 8name = 'MyName'; 9const hangModules = [], 10 missModules = [], 11 visited = {};
条件判断
[强制] 对于相等运算符,== 只能用于检查是否为 null 或者 undefined,其余情况必须使用 ===。
1// 正例 2if (age === 30) { 3 // ... 4} 5if (type == null) { 6 // ... 7} 8 9// 反例 10if (age == 30) { 11 // ...... 12}
[推荐] 建议使用 xxx == null 来判断 null 或 undefined。
[推荐] 尽量让 null 和 undefined 的含义相同。也就是说,不要让用户或开发者去区分变量是 null 还是 undefined。
[推荐] 函数表达式或者函数声明不应该放在循环体中。
1// 正例 2function clicker() { 3 // ...... 4} 5 6for (let i = 0, len = elements.length; i < len; i++) { 7 const element = elements[i]; 8 addListener(element, 'click', clicker); 9} 10 11 12// 反例 13for (let i = 0, len = elements.length; i < len; i++) { 14 const element = elements[i]; 15 addListener(element, 'click', function () {}); 16}
类型转换
[推荐] 建议使用 + '' 将值转为字符串。
1// 正例 2num + ''; 3 4// 反例 5new String(num); 6num.toString(); 7String(num);
[推荐] 建议使用 + 将值转为数值。
1// 正例 2+str; 3 4// 反例 5Number(str);
[强制] 在使用 parseInt 时,必须传入第二个参数。
1// 正例 2parseInt(str, 10); 3 4// 反例 5parseInt(str);
字符串,对象,数组
[强制] 必须使用 ' 而不是 " 定义字符串。
[强制] 必须使用对象字面量 {} 来创建简单对象。
1// 正例 2const obj = {}; 3 4// 反例 5const obj = new Object();
[强制] 如果一个对象字面量的所有属性都不需要引号,引号必须省略。如果需要加引号,须使用 ' 而不是 "。
1// 正例 2const info = { 3 name: 'someone', 4 age: 28 5}; 6 7// 反例 8const info = { 9 'name': 'someone', 10 'age': 28 11}; 12const info2 = { 13 "age": 40 14};
[强制] 禁止修改内置对象的原型。
1// 禁止 2String.prototype.trim = function () { 3};
[推荐] 尽可能使用 . 而不是 [] 访问对象的属性。
[推荐] 使用 for ... in ... 时,应当注意使用 hasOwnProperty 以防 Object 的原型在某些运行时环境中被添加一些额外属性的情况。
1const newInfo = {}; 2for (const key in info) { 3 if (info.hasOwnProperty(key)) { 4 newInfo[key] = info[key]; 5 } 6}
[强制] 除非需要创建指定长度的数组,否则必须使用数组字面量 [] 创建数组。
1// 正例 2const arr = []; 3const arr2 = new Array(1e4); 4 5// 反例 6const arr = new Array();
[强制] 不要使用 for in 语句对数组进行遍历。
其他
[强制] 不要使用 eval 和 with。允许使用new Function。
