JavaScript编码规范

修改记录

Version.No

发版日期

编制人

批准人

修改说明

1.0.0

2018/11/7

 

 

初次编订

1.0.1

2018/11/13

 

 

  1. 增加“代码检查”章节
  2. 在“代码风格”章节中增加“协议”小节

 

 

 

目 录

前言.. 4

1命名规范.. 4

1.1文件命名.. 4

1.2变量命名.. 4

1.3常量命名.. 5

1.4函数(方法)命名.. 5

1.5类 & 构造函数命名.. 6

1.6类的成员命名.. 7

1.7缩写.. 7

2代码风格.. 8

2.1代码排版.. 8

2.1.1列宽.. 8

2.1.2缩进.. 9

2.1.3空行.. 9

2.1.4空格.. 9

2.1.5引号.. 10

2.1.6小括号-() 10

2.1.7大括号-{} 10

2.2代码注释.. 11

2.2.1文件的注释.. 12

2.2.2变量的注释.. 12

2.2.3函数的注释.. 13

2.2.4语句的注释.. 13

2.2.5段落的注释.. 14

2.3协议.. 14

3语言特性.. 15

3.1简单语句.. 15

3.2复句语句.. 15

3.3三元条件判断.. 15

3.4 eval函数.. 16

3.5 this关键字.. 16

3.6 with关键字.. 16

3.7 delete关键字.. 16

3.8动态执行代码.. 17

3.9定义域与作用域.. 17

3.9.1全局命名空间污染.. 17

3.9.2 IIFE(立即执行的函数表达式).. 18

3.10闭包.. 18

3.11异常.. 20

4代码检查.. 20

5参考文献.. 20

 

 

 

前言

JavaScript是一种语法灵活,简单易懂的脚本语言。正因为灵活,因此很多人在编写代码时,显得很随意,这就导致后期的修改、拓展和维护变得异常困难。遵循统一的编码规范,不仅对C++和Java这种编译型语言很重要,对JavaScript脚本语言也同样如此。编写此规范的目的是为大家编写清晰、易读、高效的代码提供良好的建议,同时也作为公司代码审阅的参考标准。此编码规范融合了多位程序员的编程经验,适用于开发和维护期间,发布代码时可以用工具进行优化处理,剔除注释和空格字符,以提高执行效率。

1命名规范

1.1文件命名

  1. 字母全部小写
  2. 不要带空格
  3. 用破折号(-)连接单词
  4. 库文件可用逗点(.),用于体现版本或从属关系

正例:

  • vue.min.js
  • vue-router.js
  • jquery.form.js
  • jquery-1.4.2.min.js

1.2变量命名

  1. 使用骆驼命名法(Camel):标识符的第一个单词首字母小写,后面的单词首字母大写
  2. 必须以字母或美元符号($)开头,不允许包含空格和其他标点符号,不使用下划线(_)
  3. 禁止使用JavaScript关键词、保留字全名
  4. 长度应该尽可能的短,并抓住要点,尽量体现出值的类型
  5. 尽量避免使用没有意义的命名

正例:

  • var name;  // 声明了一个变量name
  • var name = 'tony'// name表示名字,值为'tony',数据类型为字符串
  • var age = 27;  // age表示年龄,值为27,数据类型为number
  • var girlFriend = false// girlFriend表示女盆友,值为否,数据类型为布尔值
  • var fn = function(){};  // fn表示一个方法,值为一个函数,数据类型为对象;

1.3常量命名

  1. 名词全部大写
  2. 使用大写字母和下划线(_)来组合命名,下划线(_)用来分割单词
  3. 禁止使用JavaScript关键词、保留字全名
  4. 长度应该尽可能的短,并抓住要点,尽量体现出值的类型
  5. 尽量避免使用没有意义的命名

正例:

  • const MAX_COUNT = 10;
  • const  URL  =  '//www.huifenqi.com';

1.4函数(方法)命名

  1.       使用骆驼命名法(Camel):标识符的第一个单词首字母小写,后面的单词首字母大写
  2. 前缀应该为动词
  3. 禁止使用JavaScript关键词、保留字全名
  4. 长度应该尽可能的短,并抓住要点,尽量体现出值的类型
  5. 尽量避免使用没有意义的命名

常用动词约定:

动词

含义

can

判断是否可执行某个动作

has

判断是否含有某个值

is

判断是否为某个值

get

获取某个值

set

设置某个值

load

加载某些数据

正例:

  • // 是否可阅读

function canRead() {

}

  • // 获取名称

function getName() {

}

1.5类 & 构造函数命名

  1. 帕斯卡命名法(Pascal):首字母和后面连接的每个单词的首字母都大写
  2. 前缀为名称
  3. 禁止使用JavaScript关键词、保留字全名
  4. 长度应该尽可能的短,并抓住要点,尽量体现出值的类型
  5. 尽量避免使用没有意义的命名

正例:

      class Person {

      constructor(name) {

          ...

      }

}

 

let person = new Person('啦啦啦');

1.6类的成员命名

  1. 公共属性和方法: 跟变量和函数命名一样。
  2. 私有属性和方法:前缀为下划线(_), 后面跟公共属性和方法命名一样。

正例:

      class Person {

      // 私有属性

      _name: string;

      constructor() { }

 

      // 公共方法

      getName() {

          return this._name;

      }

      // 公共方法

      setName(name) {

          this._name = name;

      }

}

1.7缩写

      为了避免混淆和保证跨语言交互操作,请遵循下列规则:

  1. 建议】不要将缩写或缩略形式用作名称的组成部分。

       例如:使用getWindow(),而不是使用getWin()。

  1. 【建议】不要使用计算机领域中未被普遍接受的缩写。
  2. 【建议】在适当的时候,使用众所周知的缩写替代冗长的词组名称。

例如:用UI作User Interface的缩写,用Olap作On-line Analytical Processing的缩写

  1. 【建议】在使用缩写时,大写仅有两个字符的缩写,对于超过两个字符长度的缩写根据规范使用帕斯卡命名法(Pascal)或者骆驼命名法(Camel)。

例如:使用System.IO,而不是System.Io;使用HtmlButton,而不是HTMLButton。   

2代码风格

2.1代码排版

2.1.1列宽

      代码列宽控制在每行120个字符左右。超出需要换行,换行时遵循如下原则:

  1. 第二行相对第一行缩进4个空格,从第三行开始,不再继续缩进
  2. 运算符与上下文一起换行
  3. 方法调用的点符号与上下文一起换行
  4. 方法调用中的多个参数需要换行时,在逗号后进行
  5. 在括号前不要换行

正例:

      var html = '<input οnchange="dateChange();" '

      + 'οnfοcus="WdatePicker({readOnly:true})" '

      + 'class="Wdate" type="text" id="end-time" '

      + 'style="width: 150px;height: 34px;">';

反例:

   var html = '<input οnchange="dateChange();" ' +

      'οnfοcus="WdatePicker({readOnly:true})" ' +

      'class="Wdate" type="text" id="end-time" ' +

      'style="width: 150px;height: 34px;">';

2.1.2缩进

采用4个空格缩进,禁止使用tab字符

说明:如果使用tab缩进,必须设置1个tab为4个空格。IDEA设置tab为4个空格时,请勿勾选User tab character;而在eclipse中,必须勾选insert spaces for tabs(因为不同的编辑器可能对tab的渲染不同,有的编辑器将tab显示为8个空格宽度,而有的编辑器则显示为4个空格宽度,这样就会造成代码格式的不统一)。

2.1.3空行

不同逻辑、不同语义、不同业务的代码之间插入一个空行分割开来以提高可读性。

  1. 函数与函数之间
  2. 函数中不同的逻辑块之间
  3. 注释与它注释的语句间不空行,但与其他的语句间可空一行

说明:任何情形,没必要插入多个空行进行分隔开。

2.1.4空格

      以下情况中要使用到空格:

  1. 多个参数用逗号隔开,每个逗号后都加一个空格
  2. 任何二目、三目运算符的左右两边都需要加一个空格

说明:运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号等

  1. 单目运符与变量之间不加空格
  2. if/for/while/switch/do等保留字与括号之间都必须加空格
  3. 左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格;而左大括号前需要空格
  4. 关键字与左括号之间用空格隔开

正例:

  • while (true)
  • i++;
  • --i;
  • for (expr1; expr2; expr3)
  • var sBackColor = '#' + 'FF' + '00' + 'FF';

反例:

  • if(空格a == b空格)
  • while(true)
  • for(空格expr1; expr2; expr3空格)

2.1.5引号

      统一使用单引号('),而不使用双引号("),这在创建HTML字符串时非常有用。

正例:

  • var msg = 'This is some HTML<div class="makes-sense"></div>';

反例:

  • var msg = "This is some HTML<div class=\"makes-sense\"></div>";

2.1.6小括号-()

  1. 【建议】使用小括号划分表达式的段落,使之更容易理解

例如: // 表示RGB是一个整体,颜色值是'#'RGB的字符串

var sBackColor = '#' + ('FF' + '00' + 'FF');

  1. 【建议】使用小括号包含逻辑表达式

例如: var bBlack = (sBlackColer == '#000000');

2.1.7大括号-{}

  1. 如果大括号内为空,则简洁的写成{}即可,不需要换行;如果是非空代码块则:
  1. 左大括号前不换行
  2. 右大括号后换行
  3. 右大括号前换行
  4. 右大括号后还有else等代码则不换行,表示终止的右大括号必须换行
  1. 右大括号后建议加一个注释以便于方便的找到与之对应的左大括号

例如: while (1) {

               if (valid) {

               }// if valid

               else {

               }// not valid

}// end forever

  1. 大括号中没有或只有一条语句时,也不能省略大括号

例如: if (name === undefined) {   // 正确

               return;

}

if (name === undefined)    // 错误

            return;

  1. 使用大括号进行段落划分能够指定方法内的变量的生命区域,从而使得代码更少出现一些因为不小心或者拼写错误导致的bug

例如: // 段落1

{

               var i;

}

// 段落2

{

               var i, j;

}

2.2代码注释

一些注释工具可以帮助你写出更好的注释。JSDocYUIDoc就是用来写 JavaScript注释用的。你甚至可以使用工具来为这些注释生成文档,这也是激励开发者们写注释的一个好方法,因为一旦有了这样方便的生成文档的工具,他们通常会开始花更多时间在注释细节上。

2.2.1文件的注释

文件注释位于文件的最前面,每个工程文件的文件注释应包括以下信息:

  1. 描述(概要说明)
  2. 版本(必须)(格式为“v 主版本号.次版本号.修订版本号”,每个工程文件的更新记录的版本号信息必须与工程保持一致)
  3. 版权声明(必须)(这个版本中增删改了哪些内容)
  4. 项目地址(开源组件必须)
  5. 开源协议(开源组件必须)
  6. 作者
  7. 修改时间

正例:

/*!

 * 描述:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

 * 版本:v x.x.x

 * 版本声明:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

 *    1.xxxxxxxxxxxxxxxxxxxxxxxx

 *    2.xxxxxxxxxxxxxxxxxxxxxxxx

 *    3.xxxxxxxxxxxxxxxxxxxxxxxx

 * 项目地址:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

 * 开源协议:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

 * 作者:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

 * 修改时间:xxxx-xx-xx

    */

2.2.2变量的注释

  1. 用单行注释(//
  2. 放置在变量声明的右方,用tab隔开
  3. 相邻的多个变量注释用tab对其,代码会更美观

正例:

var sBackColor = '#' + ('FF' + '00' + 'FF');   // 表示RGB是一个整体,颜色值是"#"RGB的字符串

var bBlack = (sBlackColer == '#000000');       // 判断颜色是不是黑色

2.2.3函数的注释

  1. 用文档注释(/** ... */
  2. 放置在函数声明上方
  3. @param标签指定参数的名称。还可以包含参数的数据类型,使用大括号括起来,和参数的描述(非必须要项)
  4. @callback标签来定义回调类型(非必须要项)
  5. @return/@returns标签定义返回值的类型和描述(非必须要项)
  6. @author标签定义作者

正例:

   /**

    * xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    * @author xxx

    * @callback xxxxx

    * @param {?*} xxx - xxxxx.

    * @param {!string} xxx - xxxxx.

    * @param {!function} xxx - xxxxxx.

    * @return {!number} xxxxxx.

    */

2.2.4语句的注释

  1. 用单行注释或多行注释(///* */
  2. 语句的注释放在被注释语句的上方
  3. 在有较多“{}”嵌套的语句时,可以在“}”后面加上语句结束的注释,方便阅读和插入语句

正例:

  • // 改变背景颜色为白色

sBackColor = '#FFFFFF';

  •        } //End-for

      } //End-if

} //End-while

2.2.5段落的注释

  1.      用单行注释或多行注释(///* */
  2. 段落的注释放置在被注释的语句段的上方,在注释上下各空一行

正例:

   空行

   //段落注释,上下各空一行

空行

//语句注释

sBackColor = '#FFFFFF';

2.3协议

不要指定引入资源所带的具体协议。当获取图片、其它媒体文件或者数据时,URL所指向的具体路径,不要指定协议部分(http:、https:),除非这两个协议都不可用(不指定协议使得URL从绝对的获取路径转变为相对的,在请求资源协议无法确定时非常好用,而且还能为文件大小节省几个字节)。

正例:

    function changeData() {

      $('#flex').bootstrapTable('refresh', {

         url : '//deviceAccess/vmsDiary/getAllVmsDiaries.do'

      });

}

3语言特性

3.1简单语句

  1. 每行最多包含一个分号(;),放到每条简单语句的结尾处
  2. 【注意】函数赋值或对象赋值语句也是赋值语句,应该以分号结尾。JavaScript可以把任何表达式当作一条语句。这很容易隐藏一些错误,特别是误加分号的错误。只有在赋值和调用时,表达式才应被当作一条单独的语句

正例:

    a++;

b++;

反例:

a++; b++;

3.2复句语句

    符合语句是包含在大括号中的语句序列。

  1. 被括起来的语句必须缩进四个空格
  2. 左括号({)应在复合语句起始行的结尾处
  3. 右括号(})应与左括号({)的那一行的开头对齐
  4. 大括号应该在所有复合语句中使用,即使只有一条语句,当它是控制结构的一部分时,比如一个if或者for语句。这样可以避免以后添加语句时造成的错误

3.3三元条件判断

    用三元操作符分配或返回语句。在比较简单的情况下使用,避免在复杂的情况下使用。

正例:

return x === 10 ? 'valid' : 'invalid';

反例:

   if (x === 10) {

      return 'valid';

} else {

      return 'invalid';

}

3.4 eval函数

      eval()不但混淆语境还很危险,总会有比这更好、更清晰、更安全的另一种方案来写你的代码,因此尽量不要使用eval函数。

3.5 this关键字

      只在对象构造器、方法和设定的闭包中使用this关键字。

this的语义很容易被搞错。它时而指向全局对象(大多数时),时而指向调用者的定义域(在eval中),时而指向DOM树中的某个节点(当用事件处理绑定到HTML属性上时),时而指向一个新创建的对象(在构造器中),还时而指向其它的一些对象(如果函数被call()和apply()执行和调用时)。正因为它是如此容易地被搞错,请限制它的使用场景:

  1. 在构造函数中
  2. 在对象的方法中(包括由此创建出的闭包内)

3.6 with关键字

【建议】尽量不要使用with。

使用with可能会增加代码的复杂度,不利于阅读和管理;也会对性能有影响。大多数使用with的场景都能使用其他方式较好的替代。所以,尽量不要使用with。

3.7 delete关键字

  1. 【建议】减少delete的使用。

如果没有特别的需求,减少或避免使用delete。delete的使用会破坏部分JavaScript引擎的性能优化。

  1. 【建议】处理delete可能产生的异常。

对于有被遍历需求,且值null被认为具有业务逻辑意义的值的对象,移除某个属性必须使用delete操作。

在严格模式或IE下使用delete时,不能被删除的属性会抛出异常,因此在不确定属性是否可以删除的情况下,建议添加try-catch块。

例如: try {

               delete o.x;

} catch (deleteError) {

               o.x = null;

}

3.8动态执行代码

      【建议】使用new Function执行动态代码。

    通过new Function生成的函数作用域是全局使用域,不会影响当前的本地作用域。如果有动态代码执行的需求,建议使用new Function。

    例如:

var handler = new Function('x', 'y', 'return x + y;');

var result = handler($('#x').val(), $('#y').val());

3.9定义域与作用域

3.9.1全局命名空间污染

    应该总是将代码包裹成一个IIFE(Immediately-Invoked-Function Expression),用以创建独立隔绝的定义域。这一举措可以防止全局命名空间被污染。

      IIFE还可以确保你的代码不轻易被其他全局命名空间里的代码所修改(第三方库,windows引用,被覆盖的未定义的关键字等等)。

正例:

(function(log, w, undefined) {

   var x = 10, y = 100;

   log((w.x === undefined) + ' ' + (w.y === undefined));

}(window.console.log, window));

反例:

var x = 10, y = 100;

console.log((window.x === undefined) + ' ' + (window.y === undefined));

3.9.2 IIFE(立即执行的函数表达式)

  1. 无论何时,想要创建一个新的封闭的定义域,那就用IIFE。它不仅避免了干扰,也使得内存在执行完成后立即释放
  2. 所有脚本文件建议都从IIFE开始
  3. 立即执行函数表达式的执行括号应该写在外包括号内。虽然写在内还是写在外都是有效的,但是写在内使得整个表达式看起来更像一个整体,所以推荐这么做

正例:

   (function() {}());

反例:

   (function() {})();

  1. 如果你想引用全局变量或者是外层IIFE的变量,可以通过一下方式传

正例:

(function($, w, d) {

$(function() {

w.alert(d.querySelectorAll('div').length);

});

}(jQuery, window, document));

3.10闭包

      闭包是阻止垃圾回收器将变量从内存中移除的方法,使得在创建变量的执行环境的外面能够访问到该变量。

    JavaScript是实现了自动释放内存的系统,即垃圾回收器,简称gc(garbage collector),当函数执行完毕的时候,gc会将函数中创建的东西从内存中清除。

    但是如果函数执行完毕后,依旧有函数可以访问到这个变量,那么这个变量就不会被释放,这就是闭包。

正例:

var person = (function() {

      var age = 23;

      return {

getAge : function() {// getAge函数保存到person对象上,一个闭包就创建了

            return age;

         }

      }

}());

// 闭包因保存函数而被创建,在执行环境的外面,可以动态访问age变量,这就阻止gcage变量从内存中移除

console.log(person.getAge());

   闭包通常的使用场景和this对象有关,比如下面这个场景。

正例:

    var name = 'Here is Global';

var local = {

      name : 'Here id Local',

      getNameFunction : function() {

         var that = this;

         return function() {

            console.log(that.name);

            console.log(this.name);

         }

      }

};

local.getNameFunction()();

3.11异常

      基本上你无法避免出现异常,特别是在做大型开发时(使用应用开发框架等等)。

    在没有自定义异常的情况下,从有返回值的函数中返回错误信息一定非常的棘手,更别提多不优雅了。不好的解决方案包括了传第一个引用类型来接纳错误信息,或者总是返回一个对象列表,其中包含着可能的错误对象。以上方式基本上是比较简陋的异常处理方式。适时可做自定义异常处理。

在复杂的环境中,可以考虑抛出对象而不仅仅是字符串(默认的抛出值)。

正例:

    if (name === undefined) {

      throw {

         name : 'System Error',

         message : 'A name should always be specified!'

      }

4代码检查

      对于比较宽松自由的编程语言来说,严格遵循编码规范就显得极为重要。遵循规范固然很好,但是有自动化流程来确保其执行情况,岂不更佳。

对于 JavaScript,建议使用JSLintJSHint

5参考文献

      [1] 《阿里巴巴Java开发手册 v 1.4.0》,2018-05-20

    [2] 《彦集JavaScript编码规范 v1.0》,2016-06-02

    [3] 《金蝶JavaScript开发手册 v1.0》,2003-04-22

[4] 天涯孤雁. 前端编码规范(1)—— 一般规范[EB/OL]

https://www.css88.com/archives/5361,2015-01-30

[5] 天涯孤雁. 前端编码风格规范(3)—— JavaScript规范[EB/OL] https://www.css88.com/archives/5366,2015-10-30

[6] juedi. JavaScript编码规范[EB/OL]

https://www.cnblogs.com/xianglongsdu/p/5904826.html,2016-09-25

 

下载地址:

https://download.csdn.net/download/paulangsky/10784333

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

E%3Dmc%B2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值