1. 文件
1、统一使用VSCode编辑器;
2、文件使用无 BOM 的 UTF-8 编码;
3、文件命名规则;全部采用小写方式,以下划线分隔,例:my_project_name、account_model.js。
2. 统一规范
1、使用Tab缩进,每嵌套一级缩进一个Tab,“()”需保持缩进对齐;
2、一行代码只做一件事;
3、长行拆分。
A..字符串过长截断:字符串过长时需换行,一般分号“;”或逗号“,”之后,并使用+运算符进行连接
var html =''
+ '<artical>'
+ '<hi>Title here</h1>'
+ '<p>This isparagraph</p>'
+'<footer>complete</footer>'
+ '</artical>';
var html = [
'<artical>',
'<hi>Title here</h1>',
'<p>This isparagraph</p>',
'<footer>complete</footer>',
'</artical>';
];
html= html.join(''); //注意需要join
B.三元运算符过长
varresult = condition
? resultA
: thisIsAVeryVeryLongCondition;
不得出现如下结果
var result = condition ? resultA
: thisIsAVeryVeryLongCondition;
当因为较复杂的逻辑条件组合导致80个字符无法满足需求时,应当将每个条件独立一行,逻辑运算符放置在行首进行分隔,或将部分逻辑按逻辑组合进行分隔。最终将右括号)与左大括号{放在独立一行,保证与if内语句块能容易视觉辨识
// 注意逻辑运算符前的缩进
if (user.isAuthenticated()
&& user.isInRole('admin')
&&user.hasAuthority('add-admin')
|| user.hasAuthority('delete-admin')
){
// code
}
D.过长的JSON和数组
如果对象属性较多导致每个属性一行占用空间过大,可以按语义或逻辑进行分组的组织,如:
var mapping = [
'one', 'two', 'three', 'four', 'five',
'six', 'seven', 'eight', 'nine', 'ten',
'eleven', 'twelve', 'thirteen','fourteen', 'fifteen',
'sixteen', 'seventeen', 'eighteen','nineteen', 'twenty'
];
3. JavaScript编码规范
3.1 结构
A. 缩进
1、使用 4 个空格做为一个缩进层级,不允许使用 2 个空格 或 tab 字符。
B. 空格
1、二元运算符两侧必须有一个空格,一元运算符与操作对象之间不允许有空格;
var a =!arr.length;
a++;
a = b + c;
2、用作代码块起始的左花括号 { 前必须有一个空格;
// good
function funcName() {
}
// bad
function funcName(){
}
3、if / else / for / while / function / switch / do / try / catch / finally 关键字后,必须有一个空格;
// good
if(condition) {
}
// bad
if(condition){
}
4、在对象创建时,属性中的 : 之后必须有空格,: 之前不允许有空格wozheb;
示例
//good
varobj = {ian
a: 1,
b: 2,
c: 3
};
//bad
varobj = {
a:1,
b:2,
c :3
};
5、函数声明、具名函数表达式、函数调用中,函数名和 ( 之间不允许有空格;
// good
function funcName() {
}
var funcName = function funcName() {
};
funcName();
// bad
function funcName () {
}
var funcName = function funcName () {
};
funcName ();
6、, 和 ; 前不允许有空格;
// good
callFunc(a, b);
// bad
callFunc(a , b) ;
7、在函数调用、函数声明、括号表达式、属性访问、if / for / while / switch / catch 等语句中,() 和 [] 内紧贴括号部分不允许有空格;
// good
callFunc(param1, param2,param3);
// bad
callFunc( param1, param2, param3 );
8、单行声明的数组与对象,如果包含元素,{} 和 [] 内紧贴括号部分不允许包含空格;
// good
var arr1 = [];
var arr2 = [1, 2, 3];
var obj1 = {};
var obj2 = {name: 'obj'};
var obj3 = {
name: 'obj',
age: 20,
sex: 1
};
// bad
var arr1 = [ ];
var arr2 = [ 1, 2, 3 ];
var obj1 = { };
var obj2 = { name: 'obj' };
var obj3 = { name: 'obj', age: 20, sex:1 };
9、行尾不得有多余的空格。
C. 换行
1、在函数声明、函数表达式、函数调用、对象创建、数组创建、for语句等场景中,不允许在 , 或 ; 前换行;
2、不同行为或逻辑的语句集,使用空行隔开,更易阅读;
3、对于 if...else... 、 try...catch...finally 等语句,推荐使用在 } 号后添加一个换行。
D. 语句
1、不得省略语句结束的分号;
2、在 if / else / for / do / while 语句中,即使只有一行,也不得省略块 {...};
3、函数定义结束不允许添加分号;
// good
function funcName() {
}
// bad
function funcName() {
};
// 如果是函数表达式,分号是不允许省略的。
var funcName = function () {
};
4、 IIFE (立即执行函数表达式)必须在函数表达式外添加 (,非 IIFE 不得在函数表达式外添加 ( 。
// good
var task = (function () {
// Code
return result;
})();
var func = function () {
};
// bad
var task = function () {
// Code
return result;
}();
var func = (function () {
});
3.2 命名
① PascalCase 大驼峰式命名法:首字母大写。eg:StudentInfo、UserInfo、ProductInfo
② CamelCase 小驼峰式命名法:首字母小写。eg:studentInfo、userInfo、productInfo
1、变量、函数名、函数参数、类的方法/属性、命名空间使用 Camel命名法;
var loadingModules = {};
function stringFormat(source){
}
function hear(theBells) {
}
functionTextNode(value, engine) {
this.value = value;
this.engine = engine;
}
TextNode.prototype.clone= function () {
return this;
};
2、类名、枚举变量使用Pascal命名法;
示例
}
READING: 1,
READED: 2,
APPLIED: 3,
READY: 4
};
3、常量、枚举的属性使用全部字母大写(参考如2),单词间下划线分隔的命名方式;
示例
3.3 注释
1、单行注释须独占一行,//后跟一空格;
2、多行注释避免使用/*…*/,建议使用多个单行注释;
3、文件、namespace、类、函数或方法、类属性、事件、全局变量、常量须包含以/**...*/ 形式的块注释中;
4、常量必须使用 @const 标记,并包含说明和类型信息;
/**
*常量说明
*
*@const
*@type {string}
*/
var REQUEST_URL = 'myurl.do';
5、文件注释时需在顶部且使用@file标识文件说明;
示例
/**
*
* \Copyright : Copyright (c) 2017, 北京亚控科技发展有限公司.
*
*\version :1.0
* author: change:
* 2.0
* author: change:
*
* \author :W A P
* \contact :user@company.com
*
* \brief :
*
* \note :
*
* @file
*/
6、命名空间使用@namespace标识;
* 描述
*
* @namespace
*/
var util ={};
7、类或构造函数使用@class标识;
* 描述
*
* @class
*/
function Developer() {
// constructor body
}
8、类的继承使用@extend标记;
/**
*描述
*
*@class
*@extends Developer
*/
function Fronteer() {
Developer.call(this);
// constructor body
}
util.inherits(Fronteer, Developer);
9、类的属性或方法等成员信息使用@public / @protected / @private 标识可访问性;
10、函数/方法注释须包含函数说明、参数及其类型说明、返回值及其类型说明;
示例
*函数描述
*
*@param {string} p1 参数1的说明
*@param {string} p2 参数2的说明,比较长
*那就换行了.
*@param {number=} p3 参数3的说明(可选)
*@return {Object} 返回值描述
*/
function foo(p1, p2, p3) {
var p3 = p3 || 10;
return {
p1: p1,
p2: p2,
p3: p3
};
}
11、对 Object 中各项的描述,必须使用 @param 标识;
/**
* 函数描述
*
* @param {Object} option 参数描述
* @param {string} option.url option项描述
* @param {string=} option.method option项描述,可选参数
*/
functionfoo(option) {
// TODO
}
12、事件注释时需使用@event 标识,且事件参数的标识与方法的描述标识相同
/**
*值变更时触发
*
*@event
*@param {Object} e e描述
*@param {string} e.before before描述
*@param {string} e.after after描述
*/
onchange: function (e) {
}
3.4 语言特性
A. 变量
1、变量在使用前必须通过 var 定义,且每个 var 只能声明一个变量;
// good
var hangModules = [];
var missModules = [];
var visited = {};
// bad
var hangModules = [],
missModules = [],
visited = {};
2、变量必须即用即声明 ,不得在函数或其它形式的代码块起始位置统一声明所有变量;
B. 条件
1、在 Equality Expression 中使用类型严格的 === 。仅当判断 null 或 undefined 时,允许使用 == null(使用 === 可以避免等于判断中隐式的类型转换) ;
示例
if (age === 30) {
// ......
}
// bad
if (age == 30) {
// ......
}
2、尽可能使用简洁的表达式(如使用if(name)而不使用 if(name != ‘’);
// 字符串为空
// good
if (!name){
// ......
}
// bad
if (name=== '') {
// ......
}
// 字符串非空
// good
if (name){
// ......
}
// bad
if (name!== '') {
// ......
}
// 数组非空
// good
if(collection.length) {
// ......
}
// bad
if(collection.length > 0) {
// ......
}
// 布尔不成立
// good
if(!notTrue) {
// ......
}
// bad
if(notTrue === false) {
// ......
}
// null 或 undefined
// good
if(noValue == null) {
// ......
}
// bad
if(noValue === null || typeof noValue === 'undefined') {
// ......
}
3、按执行频率排列分支的顺序;
4、对于相同变量或表达式的多值条件,用 switch 代替 if;
5、如果函数或全局中的 else 块后没有任何语句,可以删除 else。
C. 循环
1、不要在循环体中包含函数表达式,事先将函数提取到循环体外(注:因运行过程中会生成循环次数个函数对象);
// good
function clicker() {
// ......
}
for (var i = 0, len = elements.length; i< len; i++) {
var element = elements[i];
addListener(element, 'click', clicker);
}
// bad
for (var i = 0, len = elements.length; i< len; i++) {
var element = elements[i];
addListener(element, 'click', function () {});
}
2、对循环内多次使用的不变值,在循环外用变量缓存;
示例
//good
varwidth = wrap.offsetWidth + 'px';
for(var i = 0, len = elements.length; i < len; i++) {
var element = elements[i];
element.style.width = width;
// ......
}
//bad
for(var i = 0, len = elements.length; i < len; i++) {
var element = elements[i];
element.style.width = wrap.offsetWidth +'px';
// ......
}
3、对有序集合进行遍历时,缓存 length;
4、对有序集合进行顺序无关的遍历时,使用逆序遍历。
D. 类型
1、类型检测优先使用 typeof 。对象类型检测使用 instanceof 。null 或 undefined 的检测使用 == null 。
// string
typeof variable === 'string'
// number
typeof variable === 'number'
// boolean
typeof variable === 'boolean'
// Function
typeof variable === 'function'
// Object
typeof variable === 'object'
// RegExp
variable instanceof RegExp
// Array
variable instanceof Array
// null
variable === null
// null or undefined
variable == null
// undefined
typeof variable === 'undefined'
2、转换成 string 时,使用 + '' ;
示例
//good
num+ '';
//bad
newString(num);
num.toString();
String(num);
3、转换成 number 时,通常使用 + ;
示例
//good
+str;
//bad
Number(str);
4、string 转换成 number ,要转换的字符串结尾包含非数字并期望忽略时,使用 parseInt;
var width = '200px';
parseInt(width, 10);
5、使用 parseInt 时,必须指定进制;
示例
//good
parseInt(str,10);
//bad
parseInt(str);
6、转换成 boolean 时,使用 !! ;
var num =3.14;
!!num;
7、number 去除小数点,使用 Math.floor / Math.round / Math.ceil ,不使用 parseInt。
// good
var num = 3.14;
Math.ceil(num);
// bad
var num = 3.14;
parseInt(num, 10);
E. 字符串
1、字符串开头和结束使用单引号 ';
2、使用 数组 或 + 拼接字符串
// 使用数组拼接字符串
var str = [
// 推荐换行开始并缩进开始第一个字符串, 对齐代码, 方便阅读.
'<ul>',
'<li>第一项</li>',
'<li>第二项</li>',
'</ul>'
].join('');
// 使用 + 拼接字符串
var str2 = '' // 建议第一个为空字符串, 第二个换行开始并缩进开始, 对齐代码, 方便阅读
+ '<ul>',
+ '<li>第一项</li>',
+ '<li>第二项</li>',
+ '</ul>';
F. 对象
1、使用对象字面量 {} 创建新 Object;
2、对象创建时,如果一个对象的所有 属性 均可以不添加引号,则所有属性不得添加引号;
示例
varinfo = {
name: 'someone',
age: 28
};
3、对象创建时,如果任何一个 属性 需要添加引号,则所有属性必须添加 ' ;
// good
var info = {
'name': 'someone',
'age': 28,
'more-info': '...'
};
// bad
var info = {
name: 'someone',
age: 28,
'more-info': '...'
};
4、不允许修改和扩展任何原生对象和宿主对象的原型;
// 以下行为绝对禁止
String.prototype.trim = function () {
};
5、for in 遍历对象时, 使用 hasOwnProperty 过滤掉原型中的属性。
var newInfo = {};
for (var key in info) {
if (info.hasOwnProperty(key)) {
newInfo[key] = info[key];
}
}
G.数组
1、使用数组字面量 [] 创建新数组,除非想要创建的是指定长度的数组;
示例
//good
vararr = [];
//bad
vararr = new Array();
2、遍历数组不使用 for in;
3、不因为性能的原因自己实现数组排序功能,尽量使用数组的 sort 方法;
4、清空数组使用 .length = 0。
H.函数
1、一个函数的长度控制在 50 行以内(特定算法等不可分割的逻辑允许例外);
2、一个函数的参数控制在 6 个以内;
3、通过 options 参数传递非数据输入型参数;
4、在适当的时候将闭包内大对象置为 null ;
5、空函数不使用 new Function() 的形式;
6、对于性能有高要求的场合,建议存在一个空函数的常量,供多处使用共享。
I. 面向对象
1、类的继承方案,实现时需要修正 constructor;
/**
*构建类之间的继承关系
*
*@param {Function} subClass 子类函数
*@param {Function} superClass 父类函数
*/
function inherits(subClass, superClass){
var F = new Function();
F.prototype =superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
}
2、声明类时,保证 constructor 的正确性;
3、属性在构造函数中声明,方法在原型中声明;
function TextNode(value, engine) {
this.value = value;
this.engine = engine;
}
TextNode.prototype.clone = function () {
return this;
};
4、自定义事件的事件名必须全小写;
5、自定义事件只能有一个 event 参数。如果事件需要传递较多信息,应仔细设计事件对象;
4. Html编码规范
1、使用 4 个空格做为一个缩进层级,不允许使用 2 个空格 或 tab 字符;
<ul>
<li>first</li>
<li>second</li>
</ul>
2、每行不得超过 120 个字符(注:过长不易阅读与维护);
3、id 建议单词全字母小写,单词间以 - 分隔。同项目必须保持风格一致;
4、在HTML5中, 你不一定要关闭所有元素 (例如 <p> 元素),但建议每个元素都要添加关闭标签;
5、属性名必须使用小写字母,属性值必须用双引号包围;
<!--good -->
<tablecellspacing="0">...</table>
<!--bad -->
<tablecellSpacing="0">...</table>
<!--good -->
<scriptsrc="esl.js"></script>
<!--bad -->
<scriptsrc='esl.js'></script>
<scriptsrc=esl.js></script>
6、使用 HTML5 的 doctype 来启用标准模式,建议使用大写的 DOCTYPE;
示例
<!DOCTYPEhtml>
7、页面必须使用精简形式,明确指定字符编码。指定字符编码的 meta 必须是 head 的第一个直接子元素。(HTML文件使用无 BOM 的UTF-8 编码);
<html>
<head>
<meta charset="UTF-8">
......
</head>
<body>
......
</body>
</html>
8、引入 CSS 时必须指明 rel="stylesheet";
示例
<linkrel="stylesheet" href="page.css">
9、页面必须包含 title 标签声明标题。title 必须作为 head 的直接子元素,并紧随 charset 声明之后。
示例
<head>
<meta charset="UTF-8">
<title>页面标题</title>
</head>
5. CSS编码规范
1、使用 4 个空格做为一个缩进层级,不允许使用 2 个空格 或 tab 字符;
.selector {
margin: 0;
padding: 0;
}
2、选择器 与 { 之间必须包含空格;
示例
.selector{
}
3、属性名 与之后的 : 之间不允许包含空格, : 与 属性值 之间必须包含空格。
示例
margin:0;
4、列表型属性值 书写在单行时,, 后必须跟一个空格;
font-family: Arial, sans-serif;
5、每行不得超过 120 个字符,除非单行不可分割。
6、当一个 rule 包含多个 selector 时,每个选择器声明必须独占一行;
/* good */
.post,
.page,
.comment {
line-height: 1.5;
}
/* bad */
.post, .page, .comment {
line-height: 1.5;
}
7、 >、+、~ 选择器的两边各保留一个空格;
/* good */
main > nav {
padding: 10px;
}
label + input {
margin-left: 5px;
}
input:checked ~ button {
background-color: #69C;
}
/* bad */
main>nav {
padding: 10px;
}
label+input {
margin-left: 5px;
}
input:checked~button {
background-color: #69C;
}
8、属性选择器中的值必须用双引号包围;
/*good */
article[character="juliet"]{
voice-family: "Vivien Leigh",victoria, female
}
/*bad */
article[character='juliet']{
voice-family: "Vivien Leigh",victoria, female
}
9、属性定义必须另起一行并且属性定义后必须以分号结尾。
示例
.selector{
margin: 0;
}
/* bad */
.selector{
margin: 0
}
10、选择器的嵌套层级应不大于 3 级,位置靠后的限定条件应尽可能精确。
/* good */
#username input {}
.comment .avatar {}
/* bad */
.page .header .login #username input {}
.comment div * {}
11、在可以使用缩写的情况下,尽量使用属性缩写;
/* good */
.post {
font: 12px/1.5 arial, sans-serif;
}
/* bad */
.post {
font-family: arial, sans-serif;
font-size: 12px;
line-height: 1.5;
}
12、同一rule set下的属性在书写时,应按功能进行分组,并以
Formatting Model(布局方式、位置) > Box Model(尺寸) > Typographic(文本相关) > Visual(视觉效果)的顺序书写,以提高代码的可读性;
.sidebar {
/* formatting model: positioning schemes / offsets / z-indexes / display/ ... */
position: absolute;
top: 50px;
left: 0;
overflow-x: hidden;
/* box model: sizes / margins / paddings / borders / ... */
width: 200px;
padding: 5px;
border: 1px solid #ddd;
/* typographic: font / aligns / text styles / ... */
font-size: 14px;
line-height: 20px;
/* visual: colors / shadows / gradients / ... */
background: #f5f5f5;
color: #333;
-webkit-transition: color 1s;
-moz-transition: color 1s;
transition: color 1s;
}
13、文本内容必须用双引号包围。
/* good */
html[lang|="zh"] q:before {
font-family: "Microsoft YaHei", sans-serif;
content: "“";
}
html[lang|="zh"] q:after {
font-family: "Microsoft YaHei", sans-serif;
content: "”";
}
/* bad */
html[lang|=zh] q:before {
font-family: 'Microsoft YaHei', sans-serif;
content: '“';
}
html[lang|=zh] q:after {
font-family: "Microsoft YaHei", sans-serif;
content: "”";
}
14、url() 函数中的路径不加引号和url() 函数中的绝对路径可省去协议名。
示例
body{
background: url(bg.png);
}
15、长度为 0 时须省略单位。 (也只有长度单位可省);
/* good */
body {
padding: 0 5px;
}
/* bad */
body {
padding: 0px 5px;
}
16、RGB颜色值统一使用带有alpha的颜色信息的 rgba(),使用时每个逗号后保留一个空格;
示例
/*good */
.success{
box-shadow: 0 0 2px rgba(0, 128, 0, .3);
border-color: rgba(0, 128, 0, .3);
}
/*bad */
.success{
box-shadow: 0 0 2px rgba(0,128,0,.3);
border-color: rgba(0, 128, 0, .3);
}