基本书写
使用两个空格进行缩进
不要混合使用空格与制表符作为缩进
function hello (name) {console.log('hi', name) // ✓ 正确console.log('hello', name) // ✗ 错误}
除了缩进,不要使用多个空格
const id = 1234 // ✗ 错误const id = 1234 // ✓ 正确
在句末使用分号
const a = 'a' // 有风险const a = 'a'; //
字符串统一使用单引号
console.log('hello there')// 如果遇到需要转义的情况,请按如下三种写法书写const x = 'hello "world"'const y = 'hello \'world\''const z = `hello 'world'`
代码块中避免多余留白
if (user) {// ✗ 错误const name = getName()}if (user) {const name = getName() // ✓ 正确}
关键字后面加空格
if (condition) { ... } // ✓ 正确if(condition) { ... } // ✗ 错误
函数声明时括号与函数名间加空格
function name (arg) { ... } // ✓ 正确function name(arg) { ... } // ✗ 错误run(function () { ... }) // ✓ 正确run(function() { ... }) // ✗ 错误
展开运算符与它的表达式间不要留空白
fn(... args) // ✗ 错误fn(...args) // ✓ 正确
遇到分号时空格要后留前不留
for (let i = 0 ;i < items.length ;i++) {...} // ✗ 错误for (let i = 0; i < items.length; i++) {...} // ✓ 正确
代码块首尾留空格
if (admin){...} // ✗ 错误if (admin) {...} // ✓ 正确
圆括号间不留空格
getName( name ) // ✗ 错误getName(name) // ✓ 正确
属性前面不要加空格
user .name // ✗ 错误user.name // ✓ 正确
一元运算符前面跟一个空格
typeof!admin // ✗ 错误typeof !admin // ✓ 正确
注释首尾留空格
//comment // ✗ 错误// comment // ✓ 正确/*comment*/ // ✗ 错误/* comment */ // ✓ 正确
模板字符串中变量前后不加空格
const message = `Hello, ${ name }` // ✗ 错误const message = `Hello, ${name}` // ✓ 正确
逗号后面加空格
// ✓ 正确const list = [1, 2, 3, 4]function greet (name, options) { ... }
// ✗ 错误const list = [1,2,3,4]function greet (name,options) { ... }
不允许有连续多行空行
// ✓ 正确const value = 'hello world'console.log(value)
// ✗ 错误const value = 'hello world'console.log(value)
单行代码块两边加空格
function foo () {return true} // ✗ 错误function foo () { return true } // ✓ 正确if (condition) { return true } // ✓ 正确
不要使用非法的空白符
function myFunc () /*<NBSP>*/{} // ✗ 错误
始终将逗号置于行末
const obj = {foo: 'foo',bar: 'bar' // ✗ 错误}const obj = {foo: 'foo',bar: 'bar' // ✓ 正确}
点号操作符须与属性需在同一行
console.log('hello') // ✓ 正确console.log('hello') // ✗ 错误console.log('hello') // ✓ 正确
文件末尾留一空行
函数调用时标识符与括号间不留间隔
console.log ('hello') // ✗ 错误console.log('hello') // ✓ 正确
键值对当中冒号与值之间要留空白
const obj = { 'key' : 'value' } // ✗ 错误const obj = { 'key' :'value' } // ✗ 错误const obj = { 'key':'value' } // ✗ 错误const obj = { 'key': 'value' } // ✓ 正确
变量定义
使用 const/let 定义变量
当前作用域不需要改变的变量使用
const,反之则使用let
const a = 'a'a = 'b' // ✗ 错误,请使用 let 定义let test = 'test'var noVar = 'hello, world' // ✗ 错误,请使用 const/let 定义变量
每个 const/let 关键字单独声明一个变量
// ✓ 正确const silent = truelet verbose = true// ✗ 错误const silent = true, verbose = true// ✗ 错误let silent = true,verbose = true
不要重复声明变量
let name = 'John'let name = 'Jane' // ✗ 错误let name = 'John'name = 'Jane' // ✓ 正确
不要使用 undefined 来初始化变量
let name = undefined // ✗ 错误let namename = 'value' // ✓ 正确
对于变量和函数名统一使用驼峰命名法
function my_function () { } // ✗ 错误function myFunction () { } // ✓ 正确const my_var = 'hello' // ✗ 错误const myVar = 'hello' // ✓ 正确
不要定义未使用的变量
function myFunction () {const result = something() // ✗ 错误}
避免将变量赋值给自己
name = name // ✗ 错误
基本类型
不要省去小数点前面的 0
const discount = .5 // ✗ 错误const discount = 0.5 // ✓ 正确
字符串拼接操作符 (Infix operators) 之间要留空格
// ✓ 正确const x = 2const message = 'hello, ' + name + '!'
// ✗ 错误const x=2const message = 'hello, '+name+'!'
不要使用多行字符串
const message = 'Hello \world' // ✗ 错误
检查 NaN 的正确姿势是使用 isNaN()
if (price === NaN) { } // ✗ 错误if (isNaN(price)) { } // ✓ 正确
用合法的字符串跟 typeof 进行比较操作
typeof name === undefined // ✗ 错误typeof name === 'undefined' // ✓ 正确
对象与数组
对象中定义了存值器,一定要对应的定义取值器
const person = {set name (value) { // ✗ 错误this._name = value}}const person = {set name (value) {this._name = value},get name () { // ✓ 正确return this._name}}
使用数组字面量而不是构造器
const nums = new Array(1, 2, 3) // ✗ 错误const nums = [1, 2, 3] // ✓ 正确
不要解构空值
const { a: {} } = foo // ✗ 错误const { a: { b } } = foo // ✓ 正确
对象字面量中不要定义重复的属性
const user = {name: 'Jane Doe',name: 'John Doe' // ✗ 错误}
不要扩展原生对象
Object.prototype.age = 21 // ✗ 错误
外部变量不要与对象属性重名
let score = 100function game () {score: while (true) { // ✗ 错误score -= 10if (score > 0) continue scorebreak}}
对象属性换行时注意统一代码风格
const user = {name: 'Jane Doe', age: 30,username: 'jdoe86' // ✗ 错误}const user = { name: 'Jane Doe', age: 30, username: 'jdoe86' } // ✓ 正确const user = {name: 'Jane Doe',age: 30,username: 'jdoe86'}
避免使用不必要的计算值作对象属性
const user = { ['name']: 'John Doe' } // ✗ 错误const user = { name: 'John Doe' } // ✓ 正确
函数
避免使用 arguments.callee 和 arguments.caller
function foo (n) {if (n <= 0) returnarguments.callee(n - 1) // ✗ 错误}function foo (n) {if (n <= 0) returnfoo(n - 1)}
不要定义冗余的函数参数
function sum (a, b, a) { // ✗ 错误// ...}function sum (a, b, c) { // ✓ 正确// ...}
避免多余的函数上下文绑定
const name = function () {getName()}.bind(user) // ✗ 错误const name = function () {this.getName()}.bind(user) // ✓ 正确
不要使用 eval()
eval( "var result = user." + propName ) // ✗ 错误const result = user[propName] // ✓ 正确
不要使用多余的括号包裹函数
const myFunc = (function () { }) // ✗ 错误const myFunc = function () { } // ✓ 正确
避免对声明过的函数重新赋值
function myFunc () { }myFunc = myOtherFunc // ✗ 错误
注意隐式的 eval()
setTimeout("alert('Hello world')") // ✗ 错误setTimeout(function () { alert('Hello world') }) // ✓ 正确
嵌套的代码块中禁止再定义函数
if (authenticated) {function setAuthUser () {} // ✗ 错误}
禁止使用 Function 构造器
const sum = new Function('a', 'b', 'return a + b') // ✗ 错误
禁止使用 Object 构造器
let config = new Object() // ✗ 错误
自调用匿名函数 (IIFEs) 使用括号包裹
const getName = function () { }() // ✗ 错误const getName = (function () { }()) // ✓ 正确const getName = (function () { })() // ✓ 正确
不使用 Generator 函数语法
使用
Promise或者async functions来实现异步编程
function* helloWorldGenerator() { // ✗ 错误yield 'hello';yield 'world';return 'ending';}
正则
正则中不要使用控制符
const pattern = /\x1f/ // ✗ 错误const pattern = /\x20/ // ✓ 正确
正则中避免使用多个空格
const regexp = /test value/ // ✗ 错误const regexp = /test {3}value/ // ✓ 正确const regexp = /test value/ // ✓ 正确
类定义
类名要以大写字母开头
class animal {}const dog = new animal() // ✗ 错误class Animal {}const dog = new Animal() // ✓ 正确
避免对类名重新赋值
class Dog {}Dog = 'Fido' // ✗ 错误
子类的构造器中一定要调用 super
class Dog {constructor () {super() // ✗ 错误}}class Dog extends Mammal {constructor () {super() // ✓ 正确}}
使用 this 前请确保 super() 已调用
class Dog extends Animal {constructor () {this.legs = 4 // ✗ 错误super()}}
禁止多余的构造器
class Car {constructor () { // ✗ 错误}}class Car {constructor () { // ✗ 错误super()}}
类中不要定义冗余的属性
class Dog {bark () {}bark () {} // ✗ 错误}
无参的构造函数调用时要带上括号
function Animal () {}const dog = new Animal // ✗ 错误const dog = new Animal() // ✓ 正确
new 创建对象实例后需要赋值给变量
new Character() // ✗ 错误const character = new Character() // ✓ 正确
模块
同一模块有多个导入时一次性写完
import { myFunc1 } from 'module'import { myFunc2 } from 'module' // ✗ 错误import { myFunc1, myFunc2 } from 'module' // ✓ 正确
import, export 和解构操作中,禁止赋值到同名变量
import { config as config } from './config' // ✗ 错误import { config } from './config' // ✓ 正确
语句
避免在 return 语句中出现赋值语句
function sum (a, b) {return result = a + b // ✗ 错误}
禁止使用 with
with (val) {...} // ✗ 错误
不要使用标签语句
label:while (true) {break label // ✗ 错误}
不要随意更改关键字的值
let undefined = 'value' // ✗ 错误
return,throw,continue 和 break 后不要再跟代码
function doSomething () {return trueconsole.log('never called') // ✗ 错误}
逻辑与循环
始终使用 === 替代 ==
例外: obj == null 可以用来检查 null || undefined
if (name === 'John') // ✓ 正确if (name == 'John') // ✗ 错误
if (name !== 'John') // ✓ 正确if (name != 'John') // ✗ 错误
避免将变量与自己进行比较操作
if (score === score) {} // ✗ 错误
if/else 关键字要与花括号保持在同一行
// ✓ 正确if (condition) {// ...} else {// ...}
// ✗ 错误if (condition){// ...}else{// ...}
多行 if 语句的的括号不能省略
// ✓ 正确if (options.quiet !== true) console.log('done')
// ✓ 正确if (options.quiet !== true) {console.log('done')}
// ✗ 错误if (options.quiet !== true)console.log('done')
对于三元运算符 ? 和 : 与他们所负责的代码处于同一行
// ✓ 正确const location = env.development ? 'localhost' : 'www.api.com'// ✓ 正确const location = env.development? 'localhost': 'www.api.com'// ✗ 错误const location = env.development ?'localhost' :'www.api.com'
请书写优雅的条件语句(avoid Yoda conditions)
if (42 === age) { } // ✗ 错误if (age === 42) { } // ✓ 正确
避免使用常量作为条件表达式的条件(循环语句除外)
if (false) { // ✗ 错误// ...}if (x === 0) { // ✓ 正确// ...}while (true) { // ✓ 正确// ...}
循环语句中注意更新循环变量
for (let i = 0; i < items.length; j++) {...} // ✗ 错误for (let i = 0; i < items.length; i++) {...} // ✓ 正确
如果有更好的实现,尽量不要使用三元表达式
let score = val ? val : 0 // ✗ 错误let score = val || 0 // ✓ 正确
switch 语句中不要定义重复的 case 分支
switch (id) {case 1:// ...case 1: // ✗ 错误}
switch 一定要使用 break 来将条件分支正常中断
switch (filter) {case 1:doSomething() // ✗ 错误case 2:doSomethingElse()}switch (filter) {case 1:doSomething()break // ✓ 正确case 2:doSomethingElse()}switch (filter) {case 1:doSomething()// fallthrough // ✓ 正确case 2:doSomethingElse()}
避免不必要的布尔转换
const result = trueif (!!result) { // ✗ 错误// ...}const result = trueif (result) { // ✓ 正确// ...}
避免使用逗号操作符
if (doSomething(), !!test) {} // ✗ 错误
变量命名规范
- 变量名区分大小写,允许包含字母、数字、美元符号($)和下划线,但第一个字符不允许是数字,不允许包含空格和其他标点符号
- 变量命名长度应该尽可能的短,并抓住要点,尽量在变量名中体现出值的类型
- 尽量避免使用没有意义的命名
- 禁止使用JavaScript关键词、保留字全名
- 变量名区分大小写。(javascript是区分大小写的语言)
关键字
以下这些关键字用于执行特定操作等。按照规则,关键字也是语言保留的,不能用做标识符。
| break | do | instanceof | typeof |
|---|---|---|---|
| case | else | new | var |
| catch | finally | return | void |
| continue | for | switch | while |
| debugger* | function | this | with |
| default | if | throw | delete |
| in | try |
保留字:未来可能做为关键字的存在
| abstract | enum | int | short |
|---|---|---|---|
| boolean | export | interface | static |
| byte | extends | long | super |
| char | final | native | synchronized |
| class | float | package | throws |
| const | goto | private | transient |
| debugger | implements | protected | volatile |
| double | import | public |
驼峰式命名
当变量名和函数名称是由二个或多个单字链接在一起,而构成的唯一识别字时,利用“驼峰式大小写”来表示,可以增加变量和函数的可读性。
“驼峰式大小写(Camel-Case)一词来自Perl语言中普遍使用的大小写混合格式,而Larry Wall等人所著的畅销书《Programming Perl》(O’Reilly出版)的封面图片正是一匹骆驼。”
“驼峰式大小写”命名规则可视为一种惯例,并无绝对与强制,为的是增加识别和可读性。一旦选用或设置好命名规则,在程序编写时应保持一致格式。
语法
变量名或函数名是由一个或多个单词连结在一起,其中第一个单词以小写字母开始,后面的所有单词的首字母都采用大写字母,这样的变量名看上去就像骆驼峰一样此起彼伏,故得名。
示例
var myName = "zhuyujia";var formSubmit = document.getElementById(" submit");function timeCount(){}
// ✓ 正确run(function (err) {if (err) throw errwindow.alert('done')})
命名规则
| 结构 | 规则 |
|---|---|
| 公有方法和属性 | 混合,例子: mixedCase |
| 私有方法和属性 | 混合,例子: _mixedCase |
| 方法( method )参数 | 混合,例子: mixedCase |
| 本地( local )变量 | 混合,例子: mixedCase |
其他规则
| 结构 | 规则 |
|---|---|
| 公有方法和属性 | 混合,例子: mixedCase |
| 私有方法和属性 | 混合,例子: _mixedCase |
| 方法( method )参数 | 混合,例子: mixedCase |
| 本地( local )变量 | 混合,例子: mixedCase |
基本规则
1 所有语句结束后,必须使用 ; 号结束
2 所有变量必须是有意义的英文,严厉禁止拼音
3 变量允许使用公认英文缩写
4 类命名必须是驼峰式
5 常量必须所有单词大写,并且每个单词间加下划线
6 枚举类型时,枚举的命名必须有意义,枚举与枚举成员必须以驼峰式
7 常量和枚举必须在最前端定义,
merge 时注意,必须把常量与枚举定义的文件放在文件列表的第一位
8 变量内的简写单词如果在开头则全小写:
xmlDocument ,如果不在开头则全大写: loadXML !!!
9 “on” 只能用作事件的命名
10 函数开头必须是有意义的动词或动词短语
11 私有类的变量属性成员 建议 使用混合式命名,并前面下下划线
12 临时的全局变量放到一个全局的哈希表里,方便变量回收
13 所有全局变量必须初始化,尽量少用全局变量
14 大括号前面不能有换行符
15 保留字以及特有的 dom 属性不能作为变量名
特殊命名约定
16 前面加 “is” 的变量名应该为布尔值,亦可使用 “can” “has” “should”
17 前面加 ”str” 的变量名应该为字符串
18 前面加 “arr” 的变量名应该为数组
19 前面加 “num” 或 “count”
的变量名应该为数字
20 “o” 作为局部变量或参数,表示为 Object
21 “e” 作为局部变量或参数,表示为 Element
22 “evt” 作为局部变量或参数,表示为 event
23 “err” 作为局部变量或参数,表示为 error
24 重复变量建议使用 “i”, “j”,
“k” (依次类推)等名称的变量 ( 全世界公认 )
25 能缩写的单词尽量缩写
26 避免产生令人误解的布尔值 isNotNumber isNan
27 处理错误的变量,必须在后面跟着 “Error”
28 初始化用的函数 必须使用 “init” 开头,如果一个页面只有初始化可以单独使用 init()
29 尽量做有意义的代码折行,不要让一行代码过长。
(HTML 字符串除外 )
30 操作符 建议 使用空格隔开
31 函数调用和方法 避免 使用空白
32 逗号( , ) 建议 使用空白隔开。
33 不允许频繁使用 previousSibling 和 nextSibling
词法结构
34 普通代码段应该看起来如下:
while (! isDone ){
doSomething ();
isDone
= moreToDo ();
}
35 变量定义方法如下:
var a
= null,
b = 1,
c = 0;
36 函数定义方法如下:
var funcA
= function(){
var a = 0;
…
}
37 if 语句应该看起来像这样:
if ( someCondition ){
statements ;
} else if ( someOtherCondition) {
statements ;
} else {
statements ;
}
38 for 语句应该看起来像这样:
for ( initialization ; condition ;
update ){
statements ;
}
39 while 语句应该看起来像这样:
while (! isDone ){
doSomething ();
isDone
= moreToDo ();
}
40 do … while 语句应该看起来像这样:
do {
statements ;
} while ( condition );
41 switch 语句应该看起来像这样:
switch ( condition ){
case
“ A” :
statements ; // 注释
case
“ B” :
statements ;
break ;
default :
statements ;
break ;
}
42 try … catch 语句应该看起来像这样:
try {
statements ;
} catch ( ex ){
statements ;
} finally {
statements ;
}
43 单行的 if - else , while
或者 for 语句也必须加入括号:
if ( condition ){
statement ;
}
while ( condition ){
statement ;
}
for ( intialization ; condition ; update ){
statement ;
}
注释规范
44 一些你不打算给其他人使用的函数,建议添加 @ignore
让文档输出时可以忽略这段注释
45 一些相关的功能相关的函数,建议加上 @see
Function 来对上下文做索引
46 对于一些函数不建议或则需要注意的使用方法,必须加上 @deprecated 作为提醒
47 每个 js 文件的文件头都必须包含 @fileoverview @author, 建议加上 @version
48 每个函数都必须使用 JsDoc 来注释他的用意
49 每个带参数的函数必须包含 @param
50 每个有返回值的函数必须包含 @return
51 构造函数必须加上 @constructor
52 继承函数建议加上 @base 表示其继承于哪个类
53 常用全局变量建议使用 JsDoc 的注释方式
54 一般的变量及局部变量才用 // 方式进行注释,建议在需要做注释的语句的上一行
55 其他详情请参考 JsDoc 注释方法
其他
56 String 优化
循环体内的字符串累加使用 join 方式。 例如 :
var
r = [];
for ( var i = 0 ; i < 100 ; i ++){
r . push ( “hello” );
}
var k = r . join ( “” );
57 Switch 建议采用 hash-table
switch
可以才用 Object 代替 例如 :
var
a = {
“1” : doAction1 ,
“2” : doAction2 ,
}
function doAction1 (){
}
function doAction2 (){
}
a 1 ;
58 不建议使用 eval
不推荐使用 eval 来执行脚本。除非用来解释已经确定安全的 json 数据。
59 不要使用 Function 构造器。
60 不要给 setTimeout 或者 setInterval 传递字符串参数。
61 注意 IE 的内存泄露问题
62 JavaScript 代码独立
Javascript 不应该被包含在 HTML 文件中 , 除非这是段特定只属于此部分的代码。在 HTML 中的 JavaScript 代码会明显增加文件大小,而且也不能对其进行缓存和压缩。
错误处理
不要丢掉异常处理中 err 参数
// ✓ 正确run(function (err) {if (err) throw errwindow.alert('done')})
// ✗ 错误run(function (err) {window.alert('done')})
catch 中不要对错误重新赋值
try {// ...} catch (e) {e = 'new value' // ✗ 错误}try {// ...} catch (e) {const newVal = 'new value' // ✓ 正确}
用 throw 抛错时,抛出 Error 对象而不是字符串
throw 'error' // ✗ 错误throw new Error('error') // ✓ 正确
finally 代码块中不要再改变程序执行流程
try {// ...} catch (e) {// ...} finally {return 42 // ✗ 错误}
使用 Promise 一定要捕捉错误
asyncTask('google.com').catch(err => console.log(err)) // ✓ 正确
