不管有多少人共同参与同一项目,确保每一行代码都像同一个人编写的。
全部采用小写方式,多个单词组成时,以中划线分隔。
例:uxmid-core
、uxmid-web
参照项目命名规则,有复数结构时,采用复数命名法。
例:config
、components
、styles
、assets
、models
参照项目命名规则。
例:settings.vue
、account-model.js
、retina-sprites.less
- 使用4个空格代替 tab 缩进
- 嵌套标签应当另起一行并缩进一次(
head
和body
标签不需要缩进) - 在大的模块之间用空行隔开,使模块更清晰
- 在模块之间采用
<!--XXX BEGIN--> <!--XXX END-->
包裹起来 - 在属性上,确保全部使用双引号,而不是单引号
- 属性名全小写,用中划线做分隔符
- 确保在自闭合标签的尾部添加斜线(例:
<img />
或<input />
) - 脚本文件应在
</body>
的前一行引入
<!DOCTYPE html>
<html lang="zh-hans">
<head>
<meta charset="utf-8" />
<meta name="renderer" content="webkit" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Untitled</title>
<meta name="description" content="" />
<meta name="keywords" content="" />
<!-- CSS 文件 -->
<link rel="stylesheet" href="styles/layout.css" />
</head>
<body>
<div class="container">
<!-- 公共头部 BEGIN -->
<header>
<h1>网页标题...</h1>
</header>
<!-- 公共头部 END -->
</div>
<!-- JavaScript 文件 -->
<script src="scripts/vue.js"></script>
</body>
</html>
为每个 HTML 页面的第一行添加标准模式的声明,这样能够确保在每个浏览器中拥有一致的展现。
<!DOCTYPE html>
根据 HTML5 规范:
强烈建议为 html 根元素指定 lang 属性,从而为文档设置正确的语言。这将有助于语音合成工具确定其所应该采用的发音,有助于翻译工具确定其翻译时所应遵守的规则等等。
这里列出了语言代码表。
<!DOCTYPE html>
<html lang="zh-hans">
</html>
通过声明一个明确的字符编码,让浏览器轻松、快速的确定适合网页内容的渲染方式,通常指定为utf-8
。
<meta charset="utf-8" />
IE 通过特定的 <meta>
标签来确定渲染页面所采用的版本;
如果你想要了解更多,请点击这里;
不同 doctype 在不同浏览器下会触发不同的渲染模式(这篇文章总结的很到位);
除非有强烈的特殊需求,否则最好设置为 Edge 模式,从而通知 IE 采用其所支持的最新的模式。
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
根据 HTML5 规范,在引入 CSS 和 JavaScript 文件时不需要指定 type 属性,因为 text/css
和 text/javascript
分别是它们的默认值。
HTML5 规范链接:
<!-- 引入外部样式表 -->
<link rel="stylesheet" href="styles/layout.css" />
<!-- 内部样式表 -->
<style>
/* ... */
</style>
<!-- 引入外部脚本 -->
<script src="scripts/vue.js"></script>
<!-- 内部脚本 -->
<script>
...
</script>
属性应该按照特定的顺序出现以保证易读性;
class
id
name
data-*
src
,for
,type
,href
,value
,max-length
,max
,min
,pattern
placeholder
,title
,alt
aria-*
,role
required
,readonly
,disabled
class 是为高可复用组件设计的,所以应处在第一位;
id 更加具体且应该尽量少使用,所以将它放在第二位。
<a class="..." id="..." data-modal="toggle" href="#">Example link</a>
<input class="form-control" type="text" />
<img src="..." alt="..." />
布尔型属性可在声明时不赋值(XHTML 规范要求为其赋值,但是 HTML5 规范不需要);
建议采用 属性值=属性名 的方式赋值;
了解更多内容,请参考 WhatWG section on boolean attributes。
<!-- 不写属性代表属性为false -->
<input type="checkbox" />
<!-- 属性值=属性名,代表属性为true -->
<input type="checkbox" checked="checked" />
<select>
<option value="1" selected="selected">1</option>
</select>
编写 HTML 代码时,尽量避免多余的父元素;
很多时候,这需要迭代和重构来实现。
<!-- 糟糕的实例 -->
<span class="avatar">
<img src="..." />
</span>
<!-- 好的实例 -->
<img class="avatar" src="..." />
选择合适的语义化标签,便于开发者阅读,同时能让浏览器和搜索引擎更好的解析;
- 少用无语义的
div
和span
标签 - 使用
h1-h6
定义页面对应级别的标题 - 在语义不明显时,既可以使用
div
或p
时,尽量使用p
标签 - 不要使用纯样式或已过时的标签,如:
b
、font
、u
、center
、strike
等 - 需要强调的文本包含在
strong
或em
标签中 - 使用表格时,标题使用
caption
,表头使用thead
,主体内容使用tbody
,尾部使用tfoot
,表头单元格使用th
,内容单元格使用td
- 表单域使用
fieldset
包裹起来,并使用legend
标签说明表单的用途 - 每个
input
标签对应的说明都应该使用label
标签,并为input
设置id
属性,在label
中设置for
属性使说明和input
关联起来 - 不要省略某些标签的的属性,如:
img
标签的alt
属性,a
标签的title
属性 - 任何时候都要用尽量小的复杂度和尽量少的标签来解决问题
这里有一个很好的文档结构供大家参考。
使4个空格代替 tab。
.element
{
position: absolute;
top: 10px;
left: 10px;
width: 50px;
height: 50px;
border-radius: 10px;
}
所有声明语句都应当以分号结尾,包括最后一条语句。
.element
{
width: 20px;
height: 20px;
background-color: red;
}
以下几种情况需要空格
- 声明值前,即
:
后,例:width: 50px
- 选择器
>
、+
、~
前后,例:header > h1
!important
前,例:color: red !important
- 属性值中的
,
后,例:background-color: rgba(0, 0, 0, .5)
- 注释
/*
后和*/
前,例:/* 头部导航 */
以下几种情况不需要空格
- 属性名后
- 多个规则的分隔符
,
前 !important
的!
后- 属性值中
(
后和)
前 - 行末不要有多余的空格
/* 糟糕的实例 */
.element{
color :red! important;
background-color: rgba(0,0,0,.5);
}
/* 好的实例 */
.element
{
color: red !important;
background-color: rgba(0, 0, 0, .5);
}
/* 糟糕的实例 */
.element ,
.dialog{
...
}
/* 好的实例 */
.element,
.dialog
{
...
}
/* 糟糕的实例 */
.element>.dialog{
...
}
/* 好的实例 */
.element > .dialog
{
...
}
/* 糟糕的实例 */
@if{
...
}@else{
...
}
/* 好的实例 */
@if
{
...
}
@else
{
...
}
以下几种情况需要空行:
- 文件最后保留一个空行
- 声明块的右花括号
}
后最好跟一个空行,包括 scss 中嵌套的规则 - 属性之间需要适当的空行,具体见属性声明顺序
/* 糟糕的实例 */
.element {
...
}
.dialog {
color: red;
&:after {
...
}
}
/* 好的实例 */
.element
{
...
}
.dialog
{
color: red;
&:after
{
...
}
}
- 在左大括号
{
和右大括号}
前后换行 - 每条声明都应该独占一行
- 多个规则的分隔符
,
后换行 - 为选择器分组时,将单独的选择器单独放一行
/* 糟糕的实例 */
.element
{color: red; background-color: black;}
/* 好的实例 */
.element
{
color: red;
background-color: black;
}
/* 糟糕的实例 */
.element, .dialog {
...
}
/* 好的实例 */
.element,
.dialog
{
...
}
代码是由人编写并维护的,请确保你的代码能够自然描述、注释良好并且易于他人理解; 好的代码注释能够传达上下文关系和代码目的,不要简单地重声明组件或 class 名称; 对于较长的注释,务必书写完整的句子,对于一般性注解,可以书写简洁的短语。
/* 糟糕的实例 */
/*
* Modal header
*/
.modal-header
{
...
}
/* 好的实例 */
/*
* 包含标题和关闭操作的容器。
*/
.modal-header
{
...
}
最外层统一使用双引号;
url 内容要用引号;
属性选择器中的属性值需要引号。
.element:after
{
content: "";
background-image: url("images/logo.png");
}
input[type="number"]
{
...
}
- 类名使用小写字母,以中划线分隔
- id 采用驼峰式命名(首字母小写)
- scss 中的变量、函数、混合、placeholder 采用驼峰式命名
- 避免过度任意的简写,如:
.s
不能表达任何意思 - 基于最近的父 class 或基本(base)class 作为新 class 的前缀
- 使用
.js-*
class 来标识行为(与样式相对),并且不要将这些 class 包含到 CSS 文件中
/* class */
.element-content
{
...
}
/* id */
#loginDialog
{
...
}
/* 变量 */
$colorBlack: #000;
/* 函数 */
@function pxToRem($px)
{
...
}
/* 混合 */
@mixin centerBlock
{
...
}
/* placeholder */
%loginDialog
{
...
}
- 以组件为单位组织代码段
- 制定一致的注释规范
- 使用一致的空白符将代码分隔成块,这样利于阅读较大的文档
- 如果使用了多个 CSS 文件,将其按照组件而非页面的形式分拆,因为页面会被重组,而组件只会被移动
/*
* Component section heading
*/
.element { ... }
/*
* Component section heading
*
* Sometimes you need to include optional context for the entire component.
* Do that up here if it's important enough.
*/
.element { ... }
/*
* Contextual sub-component or modifer
*/
.element-heading { ... }
- 对于通用元素使用 class ,这样利于渲染性能的优化
- 对于经常出现的组件,避免使用属性选择器(例如:
[class^="..."]
) - 选择器要尽可能短,并且尽量限制组成选择器的元素个数,建议不要超过 3 个
- 只有在必要的时候才将 class 限制在最近的父元素内(也就是后代选择器)
扩展阅读:
/* 糟糕的实例 */
span { ... }
.container #stream .stream-item .header .username { ... }
.avatar { ... }
/* 好的实例 */
.header .username { ... }
.header .avatar { ... }
相关的属性声明应当归为一组,并按照下面的顺序排列:
- Positioning(定位)
- Box model(盒模型)
- Typographic(排版)
- Visual(外观)
由于定位(positioning)可以从正常的文档流中移除元素,并且还能覆盖盒模型(box model)相关的样式,因此排在第一位。盒模型紧跟其后,因为他决定了一个组件的尺寸和位置。
其他属性只是影响组件的内部(inside)或者是不影响前两组属性,所以他们排在后面。
关于完整的属性以及他们的顺序,请参考 Recess。
.declaration-order
{
/* 定位 */
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 100;
/* 盒模型 */
display: block;
float: right;
width: 100px;
height: 100px;
/* 排版 */
font: normal 13px "Helvetica Neue", sans-serif;
line-height: 1.5;
color: #333;
text-align: center;
/* 外观 */
background-color: #f5f5f5;
border: 1px solid #e5e5e5;
border-radius: 3px;
/* 其他 */
opacity: 1;
}
为了方便查阅,我们将 Recess 的顺序贴了一份出来:
"position",
"top",
"right",
"bottom",
"left",
"z-index",
"display",
"float",
"width",
"height",
"max-width",
"max-height",
"min-width",
"min-height",
"padding",
"padding-top",
"padding-right",
"padding-bottom",
"padding-left",
"margin",
"margin-top",
"margin-right",
"margin-bottom",
"margin-left",
"margin-collapse",
"margin-top-collapse",
"margin-right-collapse",
"margin-bottom-collapse",
"margin-left-collapse",
"overflow",
"overflow-x",
"overflow-y",
"clip",
"clear",
"font",
"font-family",
"font-size",
"font-smoothing",
"osx-font-smoothing",
"font-style",
"font-weight",
"hyphens",
"src",
"line-height",
"letter-spacing",
"word-spacing",
"color",
"text-align",
"text-decoration",
"text-indent",
"text-overflow",
"text-rendering",
"text-size-adjust",
"text-shadow",
"text-transform",
"word-break",
"word-wrap",
"white-space",
"vertical-align",
"list-style",
"list-style-type",
"list-style-position",
"list-style-image",
"pointer-events",
"cursor",
"background",
"background-attachment",
"background-color",
"background-image",
"background-position",
"background-repeat",
"background-size",
"border",
"border-collapse",
"border-top",
"border-right",
"border-bottom",
"border-left",
"border-color",
"border-image",
"border-top-color",
"border-right-color",
"border-bottom-color",
"border-left-color",
"border-spacing",
"border-style",
"border-top-style",
"border-right-style",
"border-bottom-style",
"border-left-style",
"border-width",
"border-top-width",
"border-right-width",
"border-bottom-width",
"border-left-width",
"border-radius",
"border-top-right-radius",
"border-bottom-right-radius",
"border-bottom-left-radius",
"border-top-left-radius",
"border-radius-topright",
"border-radius-bottomright",
"border-radius-bottomleft",
"border-radius-topleft",
"content",
"quotes",
"outline",
"outline-offset",
"opacity",
"filter",
"visibility",
"size",
"zoom",
"transform",
"box-align",
"box-flex",
"box-orient",
"box-pack",
"box-shadow",
"box-sizing",
"table-layout",
"animation",
"animation-delay",
"animation-duration",
"animation-iteration-count",
"animation-name",
"animation-play-state",
"animation-timing-function",
"animation-fill-mode",
"transition",
"transition-delay",
"transition-duration",
"transition-property",
"transition-timing-function",
"background-clip",
"backface-visibility",
"resize",
"appearance",
"user-select",
"interpolation-mode",
"direction",
"marks",
"page",
"set-link-source",
"unicode-bidi",
"speak"
- 十六进制值应该全部小写,例如:
#abcdef
- 使用简写形式的十六进制值,例如:用
#fff
代替#ffffff
/* 糟糕的实例 */
.element
{
color: #ABCDEF;
background-color: #001122;
}
/* 好的实例 */
.element
{
color: #abcdef;
background-color: #012;
}
在需要显示地设置所有值的情况下,应当尽量限制使用简写形式的属性声明。常见的滥用简写属性声明的情况如下:
padding
margin
font
background
border
border-radius
大部分情况下,我们不需要为简写形式的属性声明指定所有值。例如,HTML 的 heading 元素只需要设置上、下边距(margin)的值,因此,在必要的时候,只需覆盖这两个值就可以。过度使用简写形式的属性声明会导致代码混乱,并且会对属性值带来不必要的覆盖从而引起意外的副作用。
Mozilla Developer Network 有一篇对不熟悉属性简写及其行为的人来说很棒的关于 shorthand properties 的文章。
/* 糟糕的实例 */
.element
{
margin: 0 0 10px;
background: red;
background: url("image.jpg");
border-radius: 3px 3px 0 0;
}
/* 好的实例 */
.element
{
margin-bottom: 10px;
background-color: red;
background-image: url("image.jpg");
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
尽量将媒体查询的规则靠近与他们相关的规则,不要将他们一起放到一个独立的样式文件中,或者丢在文档的最底部,这样做只会让大家以后更容易忘记他们。
.element
{
...
}
.element-avatar
{
...
}
@media(min-width: 480px)
{
.element
{
...
}
.element-avatar
{
...
}
}
- 同个属性不同前缀的写法需要在垂直方向保持对齐,具体参照下边的写法
- 无前缀的标准属性应该写在有前缀的属性后面
.element
{
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .15);
box-shadow: 0 1px 2px rgba(0, 0, 0, .15);
}
- 不允许有空的规则
- 元素选择器用小写字母
- 对于属性值或颜色参数,省略小于 1 的小数前面的 0,例如:
.5
代替0.5
;-.5px
代替-0.5px
- 避免为 0 值指定单位,例如:用
margin: 0
代替margin: 0px
- 不要在同个规则里出现重复的属性,如果重复的属性是连续的则没关系
- 不要在一个文件里出现两个相同的规则
- 用
border: 0
代替border: none
- 发布的代码中不要有
@import
- 尽量少用
*
选择器
更多规则请参考 Wikipedia 中的 CSS语法部分
/* 糟糕的实例 */
.element
{
}
/* 糟糕的实例 */
LI
{
...
}
/* 好的实例 */
li
{
...
}
/* 糟糕的实例 */
.element
{
color: rgba(0, 0, 0, 0.5);
}
/* 好的实例 */
.element
{
color: rgba(0, 0, 0, .5);
}
/* 糟糕的实例 */
.element
{
width: 50.0px;
}
/* 好的实例 */
.element
{
width: 50px;
}
/* 糟糕的实例 */
.element
{
width: 0px;
}
/* 好的实例 */
.element
{
width: 0;
}
/* 糟糕的实例 */
.element
{
border-radius: 3px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
background: linear-gradient(to bottom, #fff 0, #eee 100%);
background: -webkit-linear-gradient(top, #fff 0, #eee 100%);
background: -moz-linear-gradient(top, #fff 0, #eee 100%);
}
/* 好的实例 */
.element
{
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
background: -webkit-linear-gradient(top, #fff 0, #eee 100%);
background: -moz-linear-gradient(top, #fff 0, #eee 100%);
background: linear-gradient(to bottom, #fff 0, #eee 100%);
}
/* 糟糕的实例 */
.element
{
color: rgb(0, 0, 0);
width: 50px;
color: rgba(0, 0, 0, .5);
}
/* 好的实例 */
.element
{
color: rgb(0, 0, 0);
color: rgba(0, 0, 0, .5);
}
缩进的单位为4个空格,规则也很简单——花括号里面的东西。
function outer(a, b)
{
let c = 1,
d = 2,
inner;
if(a > b)
{
inner = function()
{
return {
r: c - d
};
};
}
else
{
inner = function()
{
return {
r: c + d
};
};
}
return inner;
}
以下几种情况后需加分号:
- 变量声明
- 表达式
- return
- throw
- break
- continue
- do-while
以下几种情况需要空格:
- 操作符
+
,-
,*
,/
,=
,<
,>
,<=
,>=
,===
,!==
,&&
,||
,+=
前后 - 三元运算符
?
和:
前后 - 单行注释
//
后(若单行注释和代码同行,则//
前也需要),多行注释*
后 - 对象的属性值前,例:
{a: 1, b: 2};
- 分隔数组项的逗号后面,例:
[1, 2, 3];
- for 循环分号分开后的的部分,例:
for(let i = 0; i < 10; i++) {...}
- for 循环中初始化的多变量(i 和 max):
for(let i = 0, max = 10; i < max; i++) {...}
- 函数的参数之间
以下几种情况不需要空格:
- 对象的属性名后
- 前缀一元运算符后
- 后缀一元运算符前
- 函数调用括号前
- 无论是函数声明还是函数表达式,
(
前不要空格 - 数组的
[
后和]
前 - 对象的
{
后和}
前 - 运算符
(
后和)
前
// 糟糕的实例
let a =
{
b :1
};
// 好的实例
let a =
{
b: 1
};
// 糟糕的实例
++ x;
y ++;
z = x?1:2;
// 好的实例
++x;
y++;
z = x ? 1 : 2;
// 糟糕的实例
let a = [ 1, 2 ];
// 好的实例
let a = [1, 2];
// 糟糕的实例
let a = ( 1+2 )*3;
// 好的实例
let a = (1 + 2) * 3;
// 声明函数时 `(` 前面没有空格
let doSomething = function(a, b, c)
{
// do something
};
// 调用函数时 `(` 前面没有空格
doSomething(item);
// 糟糕的实例
for(i=0;i<6;i++)
{
x++;
}
// 好的实例
for(i = 0; i < 6; i++)
{
x++;
}
以下几种情况需要空行:
- 变量声明后(当变量声明在代码块的最后一行时,则无需空行)
- 注释前(当注释在代码块的第一行时,则无需空行)
- 代码块后(在函数调用、数组、对象中则无需空行)
- 逻辑块之间加空行增加可读性
- 文件最后保留一个空行
// 变量声明后需要空行
let x = 1;
// 当变量声明在代码块的最后一行时,则无需空行
if(x >= 1)
{
let y = x + 1;
}
let a = 2;
// 在行注释前添加一个空行
a++;
function b()
{
// 当注释在代码块的第一行时,则无需空行
return a;
}
// 代码块后面需要添加空行
for(let i = 0; i < 2; i++)
{
if(true)
{
return false;
}
continue;
}
let obj =
{
foo: function()
{
return 1;
},
bar: function()
{
return 2;
}
};
func
(
2,
function()
{
a++;
},
3
);
let foo =
[
2,
function()
{
a++;
},
3
];
let foo =
{
a: 2,
b: function()
{
a++;
},
c: 3
};
换行的地方,行末必须有 ,
或者运算符;
以下几种情况需要换行:
- 代码块
{
和}
前后 - 下列关键字后:
else
、catch
、finally
- 变量赋值后
// 糟糕的实例
let a =
{
b: 1
, c: 2
};
x = y
? 1 : 2;
// 好的实例
let a =
{
b: 1,
c: 2
};
x = y ? 1 : 2;
x = y ?
1 : 2;
if(condition)
{
...
}
else
{
...
}
try
{
...
}
catch(e)
{
...
}
finally
{
...
}
function test()
{
...
}
// 糟糕的实例
let a, foo = 7, b,
c, bar = 8;
// 好的实例
let foo = 7,
bar = 8;
a,
b,
c;
双斜线后,必须跟一个空格;
缩进与下一行代码保持一致;
可位于一个代码行的末尾,与代码间隔一个空格。
if(condition)
{
// 条件成立,执行 allowed 函数。
allowed();
}
let name = "jason"; // 双斜线距离分号一个缩进,双斜线后始终保留一个空格。
什么时候使用多行注释?
- 难于理解的代码段
- 可能存在错误的代码段
- 浏览器特殊的 HACK 代码
- 业务逻辑相关的代码
多行注释的标准?
- 在注释前面保留一个空行
- 最少三行,格式如下:
/*
* 注释内容与星号前保留一个空格
*/
let x = 1;
请按照如下场景添加文档注释,具体用到的标签(例如:@param
)请参考 JSDoc。
- 文件头部
- 所有常量
- 所有函数
- 所有类
- 所有类成员(字段、属性、方法)
/**
* 天干地支之地支速查表<=>生肖
* @const
* @description ["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"]
* @returns Array<string>
*/
const ANIMALS = ["\u9f20", "\u725b", "\u864e", "\u5154", "\u9f99", "\u86c7", "\u9a6c", "\u7f8a", "\u7334", "\u9e21", "\u72d7", "\u732a"];
/**
* 根据农历数字日期获取对应的汉字表示法。
* @param {number} day 农历日期
* @example let day = LunarUtils.getChinaDay(25); day = "廿五"
* @returns string
*/
function getChinaDay(day)
{
...
}
最外层统一使用双引号 "" 或模板字符串 ``。
let name = "jason",
time = "today";
// 普通字符串
let str1 = "In JavaScript '\n' is a line-feed.";
// 模板字符串
let str2 = `Hello ${name}, how are you ${time}?`;
- 变量名和方法名使用 Camel(首字母小写)命名方式,如:
let name = p1.getName();
- 常量名采用全大写加下划线连接形式,如:
const PI = 3.141592653;
- 类名(构造函数名)使用 Pascal(首字母大写)命名方式,如:
function Animal() {...}
- 使用一个下划线前缀来表示一个私有字段,如:
this._name = "jason";
- DOM 对象以
$
开头命名,如:let $passwordInput = $("#txtPassword");
let thisIsMyName;
let goodID;
let reportURL;
let androidVersion;
let iOSVersion;
const MAX_COUNT = 10;
function Person(name)
{
this._name = name;
}
Person.prototype.showName = function()
{
alert(this._name);
}
let $passwordInput = document.getElementById("txtPassword");
如果没有用到 es6 的语法,那么在一个函数作用域中所有的变量声明尽量提到函数首部,用一个 var
声明。
function doSomethingWithItems(items)
{
var value = 10,
result = value + 10,
i,
len;
for(i = 0, len = items.length; i < len; i++)
{
result += 10;
}
}
函数调用括号前不需要空格;
立即执行函数外必须包一层括号;
不要给inline function命名;
参数之间用 ,
分隔,注意逗号后有一个空格。
// 括号 '(' 前面不需要添加空格
let doSomething = function(item)
{
// do something
};
function doSomething(item)
{
// do something
}
// 糟糕的实例
doSomething (item);
// 好的实例
doSomething(item);
// 立即执行函数外必须包一层括号
(function()
{
return 1;
})();
// 糟糕的实例
[1, 2].forEach(function x()
{
...
});
// 好的实例
[1, 2].forEach(function()
{
...
});
// 糟糕的实例
let a = [1, 2, function a()
{
...
}];
// 好的实例
let a = [1, 2, function()
{
...
}];
// 参数之间用 ',' 分隔,逗号后有一个空格
let doSomething = function(a, b, c)
{
// do something
};
对象属性名不需要加引号;
对象以缩进的形式书写,不要写在一行;
数组、对象最后不要有逗号。
// 糟糕的实例
let a =
{
'b': 1
};
let a = {b: 1};
let a =
{
b: 1,
c: 2,
};
// 好的实例
let a =
{
b: 1,
c: 2
};
花括号 {}
应总被使用,即使在它们为可选的时候。虽然在 if
或者 for
中如果语句仅一条,花括号是不需要的,但是你还是应该总是使用它们,这会让代码更有持续性和易于更新。
想象下你有一个只有一条语句的 for 循环,你可以忽略花括号,而没有解析的错误。
// 糟糕的实例
for(let i = 0; i < 10; i++)
alert(i);
但是,如果,后来,主体循环部分又增加了行代码:
// 糟糕的实例
for(let i = 0; i < 10; i++)
alert(i);
alert(i + " is " + (i % 2 ? "odd" : "even"));
第二个 alert 已经在循环之外,缩进可能欺骗了你。为了长远打算,最好总是使用花括号,即使只有一行代码:
// 好的实例
for(let i = 0; i < 10; i++)
{
alert(i);
}
因此,涉及 if
,for
,while
,do...while
,try...catch...finally
的地方都必须使用花括号。
适用场景:
- 初始化一个将来可能被赋值为对象的变量
- 与已经初始化的变量做比较
- 作为一个参数为对象的函数的调用传参
- 作为一个返回对象的函数的返回值
不适用场景:
- 不要用 null 来判断函数调用时有无传参
- 不要与未初始化的变量做比较
// 糟糕的实例
function test(a, b)
{
if (b === null)
{
...
}
}
let a;
if(a === null)
{
...
}
// 好的实例
let a = null;
if(a === null)
{
...
}
永远不要直接使用 undefined 进行变量判断;
使用 typeof 和字符串 "undefined"
对变量进行判断。
// 糟糕的实例
if(person === undefined)
{
...
}
// 好的实例
if(typeof person === "undefined")
{
...
}
不要混用 tab 和空格;
对上下文 this 的引用只能使用 _this
、that
、self
其中一个来命名;
switch
的穿透和没有默认判断的情况一定要有注释特别说明;
不允许有空的代码块;
尽量减少全局变量的使用,不要让局部变量覆盖全局变量;
eval
和 with
非特殊场景,应避免使用他们;
不要给 setTimeout
或者 setInterval
传递字符串参数;
使用 {}
代替 new Object()
;
使用 []
代替 new Array()
;
应该总是使用分号,即使他们可由 JavaScript 解析器隐式创建;
use strict
必须放在函数的第一行,可以用自执行函数包含大的代码段;
使用 ===
和 !==
操作符代替 ==
和 !=
;
for in
循环里一定要有 hasOwnProperty
的判断;
不要在内置对象的原型上添加方法,如:Array
、Date
、Number
;
不要在内层作用域的代码里声明了变量,之后却访问到了外层作用域的同名变量;
变量不要先使用后声明;
不要在一句代码中单单使用构造函数,记得将其赋值给某个变量;
不要在同个作用域下声明同名变量;
不要在一些不需要的地方加括号,例:delete(a.b);
不要使用未声明的变量;
不要声明了变量却不使用;
不要在应该做比较的地方做赋值;
debugger不要出现在提交的代码里;
数组中不要存在空元素;
不要在循环内部声明函数;
不要像这样使用构造函数,例:new function () { ... }, new Object。
// 糟糕的实例
let a = 1;
function Person()
{
// 糟糕的实例
let me = this;
// 好的实例
let _this = this;
// 好的实例
let that = this;
// 好的实例
let self = this;
}
// 好的实例
switch (condition)
{
case 1:
case 2:
...
break;
case 3:
...
// 因为xxx原因这里故意穿透
case 4
...
break;
// 因为xxx原因这里没有做默认判断
}
// 糟糕的实例,空的代码快
if(condition)
{
}
// 糟糕的实例
if(a == 1)
{
a++;
}
// 好的实例
if(a === 1)
{
a++;
}
// 好的实例
for(key in obj)
{
if(obj.hasOwnProperty(key))
{
// 确保 obj[key] 是自有属性而不是原型链上的
console.log(obj[key]);
}
}
// 糟糕的实例
Array.prototype.count = function(value)
{
return 4;
};
// 糟糕的实例
var x = 1;
function test()
{
if(true)
{
var x = 0;
}
x += 1;
}
// 糟糕的实例
function test()
{
console.log(x);
var x = 1;
}
// 糟糕的实例
new Person();
// 好的实例
let person = new Person();
// 糟糕的实例
delete(obj.attr);
// 好的实例
delete obj.attr;
// 糟糕的实例
if(a = 10)
{
a++;
}
// 糟糕的实例
let a = [1, , , 2, 3];
// 糟糕的实例
let nums = [];
for(let i = 0; i < 10; i++)
{
(function(i)
{
nums[i] = function(j)
{
return i + j;
};
}(i));
}
// 糟糕的实例
let singleton = new function()
{
let privateVar;
this.publicMethod = function()
{
privateVar = 1;
};
this.publicMethod2 = function()
{
privateVar = 2;
};
};