JavaScript编码风格指南(中文版)


Posted in Javascript onAugust 26, 2016

前言:

程序语言的编码风格对于一个长期维护的软件非常重要,特别是在团队协作中。如果一个团队使用统一规范的编码分风格,可以提高团队的协作水平和工作效率。编程风格指南的核心是基本的格式化规则,这些规则决定了如何编写高水准的代码。本指南来自于《编写可维护的JavaScript》这本书,基于"Java语言编码规范"和Crockford的JavaScript编程规范,还有Nicbolas的一些个人经验和喜好。写作本文旨在加深自己印象,也为了更多人的了解到JS编码风格,提高自己的编码质量。想了解更多的内容请阅读《编写可维护的JavaScript》。

1.缩进

每一行的层级由4个空格组成,避免使用Tab进行缩进。

// 好的写法
if (true) {
  doSomeThing();
}

2.行的长度

每行长度不应超过80个字符。如果一行超过80个字符,应当在一个运算符后换行。下一行应当增加两级缩进(8个字符)。

// 好的写法
doSomeThing(argument1, argument2, aegument3, argument4,
    argument5);

// 不好的写法:第二行只有4个空格的缩进
doSomeThing(argument1, argument2, aegument3, argument4,
  argument5);

3.原始值

字符串应当始终使用双引号且保持一行,避免在字符串中使用斜线另起一行。

数字应当使用十进制整数,科学计算法表示整数,十六进制整数,或者十进制浮点小数,小数前后应当至少保留一位数字。避免使用八进制直接量。

特殊值null除了下述情况下应当避免使用。
•用来初始化一个变量,这个变量可能被赋值为一个对象。
•用来和一个已经初始化的变量比较,这个变量可以是也可以不是一个对象。
•当函数的参数期望是对象时,被用作参数传入。
•当函数的返回值期望是对象时,被用作返回值传出。

避免使用特殊值undefined。判断一个变量是否定义应当使用typeof操作符。

4.运算符间距

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

// 好的写法
for (var i = 0; i < count; i++) {
  process(i);
}

// 不好的写法:丢失了空格
for (var i=0; i<count; i++) {
  process(i);
}

5.括号间距

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

// 好的写法
for (var i = 0; i < count; i++) {
  process(i);
}
 
// 不好的写法:参数两边有额外的空格
for (var i = 0; i < count; i++) {
  process( i );
}

6.对象直接量

对象直接量应当有如下格式。
•起始左花括号应当同表达式保持同一行。
•每个属性的名值对应当保持一个缩进,第一个属性应当在左花括号后另起一行。
•每个属性的名值对应当使用不含引号的属性名,其后紧跟一个冒号(之前不舍空格),其后是值。
•倘若属性值是函数类型,函数体应当在属性名之下另起一行,而且其前后均应保留一个空行。
•一组相关的属性前后可以插入空行以提升代码的可读性。
•结束的右花括号应当独占一行。

// 好的写法
var object = {

  key1: value1,
  key2: value2,

  func: function() {
  // doSomeThing
  },

  key3: value3
};

// 不好的写法:不恰当的缩进
var object = {
    key1: value1,
    key2: value2
  };

// 不好的写法:函数体周围缺少空行
var object = {

  key1: value1,
  key2: value2,
  func: function() {
  // doSomeThing
  },
  key3: value3
};

当对象字面量作为函数参数时,如果值是变量,起始花括号应当同函数名在同一行。所有其余先前列出的规则同样适用。

// 好的写法
doSomeThing({
  key1: value1,
  key2: value2
});
// 不好的写法:所有代码在一行上
doSomeThing({ key1: value1, key2: value2 });

7.注释

使用简洁明了注释有助于他人理解你的代码。如下情况应当使用注释。
•代码晦涩难懂。
•可能被误认为错误的代码。
•必要但不明显的针对特定浏览器的代码。
•对于对象、方法或者属性,生成文档是有必要的(使用恰当的文档注释)。

单行注释

单行注释应当用来说明一行代码或者一组相关的代码。单行注释可能有三种使用方式。
•独占一行的注释,用来解释下一行代码。
•在代码行的尾部的注释,用来解释它之前的代码。
•多行,用来注释掉一个代码块。

// 好的写法
if (condition) {

  // 如果代码执行到这里,则表明通过了所有安全检查
  allowed();
}

// 不好的写法:注释之前没有空行
if (condition) {
  // 如果代码执行到这里,则表明通过了所有安全检查
  allowed();
}

// 不好的写法:错误的缩进
if (condition) {

// 如果代码执行到这里,则表明通过了所有安全检查
  allowed();
}

// 不好的写法:应当使用多行注释
// 这段代码进行**判断
// 然后执行
if (condition) {

  // 如果代码执行到这里,则表明通过了所有安全检查
  allowed();
}

// 好的写法:在行尾注释时,代码结尾和注释间应保留一个空格
if (condition) {

  // 如果代码执行到这里,则表明通过了所有安全检查
  allowed(); // 执行**函数
}

// 不好的写法:代码和注释间没有足够的空格
if (condition) {

  // 如果代码执行到这里,则表明通过了所有安全检查
  allowed();// 执行**函数
}

// 好的写法:在注释掉一个代码块时,应联系使用单行注释,多行注释不应当使用在此种情况下。
// if (condition) {
//   allowed();//执行**函数
// }

多行注释

多行注释应当在代码需要更多文字去解释的时候使用。每个多行注释都至少有如下三行:
1.首行仅仅包括/*注释开始。该行不应当有其他文字。
2.接下来的行以*开头并保持左对齐。这些可以有文字描述。
3.最后一行以*/开头并同先前行保持对齐。也不应有其他文字。

多行注释的首行应当保持同它描述代码的相同层次的缩进。后续的每行应当有同样层次的缩进并附加一个空格(为了适当保持*字符的对齐)。每一个多行代码之前应当预留一个空行。

// 好的写法、
if (condition) {

  /*
  * 如果代码执行到这里
  * 说明通过了所有的安全检测
  */
  allowed();
}

注释声明

注释有时候也可以用来给一段代码声明额外的信息。这些声明的格式以单个单词打头并紧跟一个冒号。可以使用的声明如下。

TODO:说明代码还未完成。应当包含下一步要做的事情。

HACK:表明代码实现走了一个捷径。应当包含为何使用hack的原因。这也可能表明该问题可能会有更好的解决办法。

XXX:说明代码是有问题的并应当尽快修复。

FIXME:说明代码是有问题的并应尽快修复。重要性略次于XXX。

REVIEW:说明代码在任何可能的改动都需要评审。

这些声明可能在一行或者多行注释中使用,并且应当遵循同一般注释类型相同的格式规则。

8.命名

变量和函数在命名时应当小心。命名应紧限于数字字母字符,某些情况下可以使用下划线(_)。最好不要在任何命名中使用美元符号($)或者反斜杠(\)。

变量命名应当采用驼峰命名格式,首字母小写,每个单词首字母大写。变量名的第一个单词应当是一个名词(而非动词)以避免同函数混淆。不要在变量名中使用下划线。

// 好的写法
var accountNumber = "test001";
 
// 不好的写法:大写字母开头
var AccountNumber = "test001";

// 不好的写法:动词开头
var getAccountNumber = "test001";

// 不好的写法:使用下划线
var account_number = "test001";

函数名也应当采用驼峰命名格式。函数名的第一个单词应当是动词(而非名词)来避免同变量混淆。函数名中最好不要使用下划线。

// 好的写法
function doSomething() {
  // code
}

// 不好的写法:大写字母开头
function DoSomething() {
  // code
}

// 不好的写法:名词开头
function something() {
  // code
}

// 不好的写法:使用下划线
function do_something() {
  // code
}

构造函数--通过new运算符创建新对象的函数--也应当以驼峰格式命名并且首字符大写。构造函数名称应当以非动词开头,因为new代表着创建一个对象实例的操作。

// 好的写法
function MyObject() {
  // code
}

// 不好的写法:小写字母开头
function myObject() {
  // code
}

// 不好的写法:使用下划线
function my_object() {
  // code
}

// 不好的写法:动词开头
function getMyObject() {
  // code
}

常量(值不会被改变的变量)的命名应当是所有大写字母,不同单词之间单个下划线隔开。

// 好的写法
var TOTAL_COUNT = 10;

// 不好的写法:驼峰形式
var totalCount = 10;

// 不好的写法:混合形式
var total_COUNT = 10;

对象的属性同变量的命名规则相同。对象的方法同函数的命名规则相同。如果属性或者方法是私有的,应当在之前加上一个下划线。

// 好的写法
var object = {
  _count: 10,4 
  _getCount: function() {
    return this._count;
  }
}

9.变量与函数声明

变量声明

所有的变量在使用前都应当事先定义。变量定义应当放在函数开头,使用一个var表达式每行一个变量。除了首行,所有行都应当多一层缩进以使变量名能够垂直方向对齐。变量定义时应当初始化,并且赋值操作符应当保持一致的缩进。初始化的变量应当在未初始化变量之前。

// 好的写法
 var count = 10,
   name = "jeri",
   found = false,
   empty;

函数声明

函数应当在使用前提前定义。一个不是作为方法的函数(也就是说没有作为一个对象的属性)应当使用函数定义的格式(不是函数表达式和Function构造器格式)。函数名和开始圆括号之间不应当有空格。结束的圆括号和右边的花括号之间应当留一个空格。右侧的花括号应当同function关键字保持同一行。开始和结束括号之间不应该有空格。参数名之间应当在逗号之后保留一个空格。函数体应当保持一级缩进。

// 好的写法
function outer() {
  var count = 10,
    name = "jeri",
    found = false,
    empty;
  function inner() {
    // code
  }
  // 调用inner()的代码
}

匿名函数可能作为方法赋值给对象,或者作为其他函数的参数。function关键字同开始括号之间不应有空格。

// 好的写法
object.method = function() {
  // code
};

// 不好的写法:不正确的空格
object.method = function () {
  // code
};

立即被调用的函数应当在函数调用的外层用园括号包裹。

// 好的方法
var value = (function() {

  // 函数体

  return {
    message:"hi"
  }
}());

严格模式

严格模式应当仅限在函数内部使用,千万不要在全局使用。

// 不好的写法:全局使用严格模式
"use strict";

function doSomething() {
  // code
}
 
// 好的写法
function doSomething() {
  "use strict";
 
  // code
}

10.运算符

赋值

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

// 好的写法
var flag = (i < count);

// 不好的写法:遗漏圆括号
var flag = i < count;

等号运算符

使用===(严格相等)和!==(严格不相等)代替==(相等)和!=(不等)来避免弱类型转换错误。

// 好的写法
var same = (a === b);

// 好的写法
var same = (a == b);

三元操作符

三元运算符应当仅仅用在条件赋值语句中,而不要作为if语句的替代品。

// 好的写法
var value = condition ? value1 : value2;

// 不好的写法:没有赋值,应当使用if表达式
condition ? doSomething() : doSomethingElse;

11.语句

简单语句

每一行最多只包含一条语句。所有简单的语句都应该以分号(;)结束。

// 好的写法
count++;
a = b;

// 不好的写法:多个表达式写在一行
count++; a = b;

返回语句

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

return;

return collection.size();

return (size > 0 ? size : defaultSize);

复合语句

复合语句是大括号括起来的语句列表。
•括起来的语句应当较复合语句多缩进一个层级。
•开始的大括号应当在复合语句所在行的末尾;结束的大括号应当独占一行且同复合语句的开始保持同样的缩进。
•当语句是控制结构的一部分时,诸如if或者for语句,所有语句都需要用大括号括起来,也包括单个语句。这个约定使得我们更方便地添加语句而不用担心忘记加括号而引起bug。
•像if一样的语句开始的关键词,其后应该紧跟一个空格,起始大括号应当在空格之后。

if 语句

if 语句应当是下面的格式。

if (condition) {
  statements
}

if (condition) {
  statements
} else {
  statements
}

if (condition) {
  statements
} else if (condition) {
  statements
} else {
  statements
}

绝不允许在if语句中省略花括号。

// 好的写法
if (condition) {
  doSomething();
}

// 不好的写法:不恰当的空格
if (condition){
  doSomething();
}

// 不好的写法:所有代码都在一行
if (condition) { doSomething(); }

// 不好的写法:所有代码都在一行且没有花括号
if (condition) doSomething();

for 语句

for类型的语句应当是下面的格式。

for (initialization; condition; update) {
  statements
}

for (variable in object) {
  statements
}

for语句的初始化部分不应当有变量声明。

// 好的方法
var i,
  len;

for (i=0, len=0; i < len; i++) {
  // code
}

// 不好的写法:初始化时候声明变量
for (var i=0, len=0; i < len; i++) {
  // code
}

// 不好的写法:初始化时候声明变量
for (var prop in object) {
  // code
}

当使用for-in语句时,记得使用hasOwnProperty()进行双重检查来过滤对象的成员。

while 语句

while 类的语句应当是下面的格式。

while (condition) {
  statements
}

do 语句

do 类的语句应当是下面的格式。

do {
  statements
} while (condition);

switch 语句

switch 类的语句应当是如下格式。

switch (expression) {
  case expression:
    statements

  default:
    statements
}

switch下的第一个case都应当保持一个缩进。除第一个之外包括default在内的每一个case都应当在之前保持一个空行。

每一组语句(除了default)都应当以break、return、throw结尾,或者用一行注释表示跳过。

// 好的写法
switch (value) {
  case 1:
    /* falls through */

  case 2:
    doSomething();
    break;

  case 3:
    return true;

  default:
    throw new Error("Some error");
}

如果一个switch语句不包含default情况,应当用一行注释代替。

// 好的写法
switch (value) {
  case 1:
    /* falls through */

  case 2:
    doSomething();
    break;

  case 3:
    return true;

  default:
    // 没有default
}

try 语句

try类的语句应当格式如下。

try {
  statements
} catch (variable) {
  statements
}

try {
  statements
} catch (variable) {
  statements
} finally {
  statements
}

12.留白

在逻辑相关的代码之间添加空行代码可以提高代码的可读性。

两行空行仅限于在如下情况下使用:
•在不同的源代码文件之间。
•在类和接口定义之间。

单行空行仅限在如下情况中使用。
•方法之间。
•方法中局部变量和第一行语句之间。
•多行或者单行注释之前。
•方法中逻辑代码块之间以提升代码的可读性。

空格应当在如下的情况下使用。
•关键词后跟括号的情况应当用空格隔开。
•参数列表中逗号之后应当保留一个空格。
•所有的除了点(.)之外的二元运算符,其操作数都应当用空格隔开。单目运算符的操作数之间不应该用空白隔开,例如一元减号,递增(++),递减(--)。
•for 语句的表达式之间应当用空格隔开。

13.需要避免的

•切勿使用像String一类的原始包装类型创建新的对象。
•避免使用eval()。
•避免使用with语句。该语句在严格模式中不复存在,可能在未来的ECMAScript标准中也将去除。

写在最后

上述指南并不是在开发过程中必须完全遵守的,我们可以只汲取其中的一部分来改善自己的编码风格,让自己的代码易读、可维护。关于编码风格,每个团队都有自己的特色,只要保持团队一致性,可以高效的开发就OK了。有些规则也并不是我们必须一成不变地遵守的,比如在缩进方面,我们使用Tab键很多时候更加地便捷,但是我们不能保证在任何环境下Tab都代表4个空格,为了在缩进方面保持一致性,如果使用Tab键那么在整个过程中都要使用;还有关于""和‘'的使用,我们也不必都使用"",使用''也是可以的,只要保持一致的风格就可以了。还有很多其他类似的风格问题,全凭个人选择。

没有绝对的准则,只有适不适合。

Javascript 相关文章推荐
用javascript实现的仿Flash广告图片轮换效果
Apr 24 Javascript
JQuery 选择和过滤方法代码总结
Nov 19 Javascript
asp.net刷新本页面的六种方法总结
Jan 07 Javascript
JavaScript调用传递变量参数的相关问题及解决办法
Nov 01 Javascript
搭建Bootstrap离线文档的方法
Dec 02 Javascript
记录一次开发微信网页分享的步骤
May 07 Javascript
微信小程序实现搜索指定景点周边美食、酒店
May 18 Javascript
Vue+ElementUI项目使用webpack输出MPA的方法
Aug 27 Javascript
在layui框架中select下拉框监听更改事件的例子
Sep 20 Javascript
Vue为什么要谨慎使用$attrs与$listeners
Aug 27 Javascript
vue3.0中友好使用antdv示例详解
Jan 05 Vue.js
js实现上传图片到服务器
Apr 11 Javascript
JavaScript使用forEach()与jQuery使用each遍历数组时return false 的区别
Aug 26 #Javascript
ES6中的数组扩展方法
Aug 26 #Javascript
jQuery实现微信长按识别二维码功能
Aug 26 #Javascript
XMLHttpRequest Level 2 使用指南
Aug 26 #Javascript
js HTML5多图片上传及预览实例解析(不含前端的文件分割)
Aug 26 #Javascript
JavaScript组合模式学习要点
Aug 26 #Javascript
前端面试题及答案整理(二)
Aug 26 #Javascript
You might like
PHP 面向对象详解
2012/09/13 PHP
体育彩票排列三组选三算法分享
2014/03/07 PHP
phpcms手机内容页面添加上一篇和下一篇
2015/06/05 PHP
PHP编译configure时常见错误的总结
2017/08/17 PHP
php实现解析xml并生成sql语句的方法
2018/02/03 PHP
PHP给源代码加密的几种方法汇总(推荐)
2018/02/06 PHP
PHP ADODB实现分页功能简单示例
2018/05/25 PHP
php实现单笔转账到支付宝功能
2018/10/09 PHP
Yii框架引入coreseek分页功能示例
2019/02/08 PHP
解决js数据包含加号+通过ajax传到后台时出现连接错误
2013/08/01 Javascript
JS控件ASP.NET的treeview控件全选或者取消(示例代码)
2013/12/16 Javascript
jquery动态切换背景图片的简单实现方法
2016/05/14 Javascript
js实现div模拟模态对话框展现URL内容
2016/05/27 Javascript
Vuex模块化实现待办事项的状态管理
2017/03/15 Javascript
requirejs按需加载angularjs文件实例
2017/06/08 Javascript
js + css实现标签内容切换功能(实例讲解)
2017/10/09 Javascript
vue router demo详解
2017/10/13 Javascript
JavaScript时间与时间戳的转换操作实例分析
2018/12/07 Javascript
webpack 最佳配置指北(推荐)
2020/01/07 Javascript
JavaScript数组排序小程序实现解析
2020/01/13 Javascript
javascript实现计算器功能
2020/03/30 Javascript
原生js实现html手机端城市列表索引选择城市
2020/06/24 Javascript
vue 获取元素额外生成的data-v-xxx操作
2020/09/09 Javascript
Swiper实现导航栏滚动效果
2020/10/16 Javascript
vue3弹出层V3Popup实例详解
2021/01/04 Vue.js
python使用tkinter实现简单计算器
2018/01/30 Python
浅谈keras使用中val_acc和acc值不同步的思考
2020/06/18 Python
python excel多行合并的方法
2020/12/09 Python
css3动画效果小结(推荐)
2016/07/25 HTML / CSS
美国浴缸、水槽和水龙头购物网站:Vintage Tub & Bath
2019/11/05 全球购物
extern在函数声明中是什么意思
2014/01/19 面试题
《晏子使楚》教学反思
2014/02/08 职场文书
导游个人求职信范文
2014/03/23 职场文书
开学典礼观后感
2015/06/15 职场文书
Lakehouse数据湖并发控制陷阱分析
2022/03/31 Oracle