JavaScript编码规范
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
产品源代码质量检测:JavaScript
编码规范
(A0)
目录
前言 ................................................................. 错误!未定义书签。
1概述 (4)
2文件引用及参考 (4)
3声明规则 (4)
3.1变量 (4)
3.2函数 (6)
4命名规则 (7)
4.1构造函数/类 (7)
4.2变量/对象属性 (7)
4.3常量 (8)
4.4命名空间 (8)
4.5函数/对象方法 (8)
4.6事件 (9)
5注释规则 (9)
5.1通用注释规则 (9)
5.2 JavaScript文件注释 (10)
5.3函数/方法注释 (10)
5.4变量/属性注释 (11)
6排版规则 (11)
6.1文件结构 (11)
6.2缩进 (11)
6.3分号 (11)
6.4空格 (12)
6.5行排版 (12)
6.6空行 (12)
6.7语句 (12)
6.7.1表达式语句 (12)
6.7.2复合语句 (13)
6.7.3 if-else语句 (13)
6.7.4 for语句 (13)
6.7.5 for-in语句 (13)
6.7.6 while语句 (13)
6.7.7 do-while语句 (13)
6.7.8 switch语句 (14)
6.7.9 try-catch-finally语句 (14)
7字符集编码规则 (14)
8编码健壮性遵循原则 (14)
8.1合理使用闭包 (14)
8.2合理使用for和for-in循环 (15)
8.3避免无限循环 (16)
8.4区分===和== (16)
8.5禁止使用with(){} (16)
8.6字符串拼接 (16)
8.7避免在函数中定义全局变量 (17)
8.8避免在JavaScript中包含过多的HTML、CSS内容 (17)
8.9异常处理 (17)
9安全 (18)
9.1 JSON串的安全过滤 (18)
9.2 JavaScript脚本攻击 (18)
9.3 Cookie泄露 (18)
9.4防止js代码泄露 (18)
10性能优化 (18)
10.1合理使用prototype (18)
10.2本地缓存对象属性 (18)
10.3减少操作HTML DOM结构的次数 (19)
10.4引用JavaScript文件 (19)
10.5事件代理 (19)
11第三方框架引入规范 (19)
12安全性要求 (19)
13附录 (19)
13.1一致性约束 (19)
13.2保留字 (20)
13.3 JSON格式 (21)
13.4常用类型值举例 (22)
13.5数据处理建议 (23)
13.5.1数据处理控件 (23)
13.5.2数据格式与处理 (23)
13.5.3缓存使用 (23)
JavaScript编码规范
1 概述
本规范适用于公司产品JavaScript程序开发。
2 文件引用及参考
《JavaScript权威指南V5》。
《JavaScript高级程序设计V2》。
《JavaScript高性能》。
《Google JavaScript开发规范》。
《国家电网公司JavaScript编码规范》。
3 声明规则
3.1 变量
局部变量和全局变量均使用var关键字进行声明。
示例:
var name =””;
在同一作用域(在JavaScript中共三种作用域:全局作用域、局部作用域、嵌套局部作用域)的起始位置声明变量,避免出现重复声明变量,for、for-in语句的循环变量除外。
示例:
//全局变量
var globalV = ”global”;
function printUserProperty () {
//局部变量
var users = [{name:”用户1”}, {name:”用户2”}];
//for语句变量i, user
for( var i = 0, user; user = users[i]; i++ ) {
printUserProperty(user);
}
function printUserProperty(user) {
//嵌套局部变量
var count = 10;
//for-in语句变量prop
for ( var prop in user ) {
alert(prop);
}
}
}
声明全局变量、对象属性、函数参数时需注释变量类型并赋初值(通过初值确定变量类型),由于局部变量是在代码块内部定义,作用范围有限,因此不做要求。
示例:
//全局变量
var isSuccess = false; //推荐的布尔类型初始值:false
var count = -1; //推荐的number类型初始值:-1
var name = ””; //推荐的字符串类型初始值:””
var user = null; //推荐的对象类型初始值:null
var obj = {
//对象属性
name = ””
};
//函数参数
/**
* 设置名称
* @param {string} name 名称
* @return
*/
function setName(name) {
}
可以一次声明多个变量,变量之间用“,”分隔,如果变量有初值或者注释则需换行,换行后与上一行的第一个变量左对齐。
示例:
var name, password, age, sex;
//有注释或者初值应换行
var name, password,
age, //年龄
sex = ”男”;
采用直接量的方式声明对象,提高对象声明的代码可读性,对象属性和方法行前空4格,对象的属性或者方法以“,”分隔,最后一个属性或者方法不应出现“,”, 属性之间不空行,方法之间空两行。
示例:
//优
var user = {
id:””,
name:””,
setName: function(name) {
= name;
},
getName: function() {
return ;
}
}
//劣
var user = new Object();
user.id = ””;
= ””;
user.setName = function(name) {
= name;
}
user.getName = function() {
return ;
}
3.2 函数
使用function关键字声明函数。
示例:
function getUser() {
}
//函数变量
var getUser = function() {
}
函数参数之间用“,”分隔。
示例:
function createUser(id, name, password) {
}
函数代码行前空4格。
示例:
function getUser() {
return {name:”用户”};
}
相邻函数之间空2行。
示例:
function setUser() {
}
function setUser(user) {
}
函数的左花括号的右端不应有代码,右花括号的左端不应有代码。
示例:
excute('whatever', function(p1, p2) {
});
在<script>、function的根下声明函数,避免在if等语句块下声明函数。
示例:
//劣:
if (x) {
function foo() {}
}
//替代方案:使用函数变量
if (x) {
var foo = function() {}
}
4 命名规则
4.1 构造函数/类
构造函数:指初始化一个对象的属性并且专门和new运算符一起使用的函数,通常采用构造函数实现类的概念,构造函数采用首字母大写的驼峰式命名。
示例:
function User(id, name, password) {
this.id = id;
= name;
this.password = password;
}
var user = new User(”id1”, ”用户”, ”111111”);
alert();
4.2 变量/对象属性
在本小节变量代指:变量/对象属性。
变量由字母、数字或下划线组成,变量的第一个字符不能是数字。
示例:
//正确
var user = null;
var _user = null;
var _user1 = null;
//错误
var 1user = null;
变量采用首字母小写的驼峰式命名。
示例:
var userName = ””;
var user = {
userName:””
};
变量名称应具有一定的含义,能准确体现变量的含义。
示例:
//优
var userName = ””;
//劣
var aa = ””;
4.3 常量
在JavaScript中没有常量的语法,但是可以采取特殊的命名方式把一个变量表示为常量:所有字母大写,单词之间用“_”连接。
示例
var MAX_WIDTH = 1024;
4.4 命名空间
命名空间的名称全部由小写字母和数字组成,类似于Java语言中的包名,如果是一个可数单词,则应使用其复数形式;如果是一个动词,则应使用其名词或动名词形式,并且应尽量使用约定俗成的缩写。
示例:
mx.ds(mx.datasources);
mx.utils(mx.utilities)
4.5 函数/对象方法
对象方法是作为对象属性的函数,在此函数代指:函数/对象方法。
函数名称由字母、数字或下划线组成,第一个字符不能是数字。
示例:
//正确
function getUser() {
}
function _getUser2() {
}
//错误
function 1getUser() {
}
function get&User() {
}
函数名称采用首字母小写的驼峰式命名。
示例:
function getUser() {
}
函数名称应具有一定的含义,能够准确体现函数的职责。
示例:
//优
function getUser() {
}
//劣
function aa() {
}
函数名称通常以动词开头。
示例:
//优
function getUser() {
}
//劣
function user() {
}
变量/对象属性对应的存值、取值方法分别通过set、get命名,如果变量/对象属性是boolean类型,则建议使用is替代get。
4.6 事件
处理事件的函数名称以“Handler”后缀结尾,在名称中需要包含事件的类型和代表触发事件的HTML 元素名称。
示例:
//在页面中有一个输入用户名称的input框,则处理它的onchange事件的函数命名如下:
function userNameInputOnChangeHandler(e) {
}
5 注释规则
5.1 通用注释规则
1)文件、函数/方法、变量/属性要加以注释。
2)用于完成单个任务的多行代码应该在前面填加描述任务的注释。
3)在使用复杂算法的代码处添加注释,以便下次查阅代码时帮助理解。
4)块注释:块注释以“/**”开头或者“/*”开头,以“*/”结尾,文档注释以“/**”开头,例如:注释在JavaScript文件开头、函数、变量上,通常会用于生成文档;非文档注释的多行注释以“/*”开头。
在文档注释中需要注明类型,常见的类型包括:Object、Array、Function、Number、String、
注:在注释中的Number包装类型代指Number类型或者number基本类型,其它包装类型类似。
示例:
/**
*{Object} 用户对象
*/
var user = {};
/**
*通过用户对象获取用户名称
*@param {Object} user 用户对象
*@return {String} 用户名称
*/
function getUserName(user) {
/*
*如果user为null,则该方法会出现异常,需要对输入参数user进行可靠性校验
*需判断user变量是否是user对象
*/
return ;
}
//如果没有返回值,可以不用在注释中写@return
/**
*设置用户名称
*@param {Number} age 用户名称
*/
function setUserName(name) {
= name;
}
5)单行注释:以”//”开头,非文档注释时使用。
示例:
function getUserName(user) {
//返回用户名称
return ;
}
5.2 JavaScript文件注释
在文件头位置对JavaScript文件进行注释,说明该文件的主要内容、版权、版本、作者、创建时间、重要变更日志等信息。
示例:
/**
*本文件是UI VERSION的一部分
*Copyright(C)2000-2008 NARI Information and CommunicationTechnology Branch. All
*rights reserved.
*版本信息:PI3000-V1.000-002
*作者:张三
*创建时间:2008-05-30
*修改时间修改人变更说明
*2009-09-09李四增加saveBusinessData2方法
*/
5.3 函数/方法注释
规则:描述函数/方法功能或者算法逻辑、输入、输出及返回值。
示例:
/**
*通过用户对象获取用户名称
*@param {Object} user 用户对象 *@return {String} 用户名称
*/
function getUserName(user) { return ;
}
5.4 变量/属性注释
规则:描述变量的含义。
示例:
var user = {}; //用户
/*用户*/
var user = {};
6 排版规则
6.1 文件结构
6.2 缩进
以4个空格为一个缩进单元。
示例:
function getUser(id) {
if ( !id ) {
throw new Error(””);
}
}
6.3 分号
在语句末尾处添加分号。
6.4 空格
在以下情况下需要添加空格:中文与数字、两个英文单词之间,逗号之后,所有运算符前后,function 语句之后,控制语句后。
6.5 行排版
避免一行超过120个字符,避免影响查看程序的效率。
如果一段描述不能放在一行中,依据下列规则将其拆分成多行:
1)在分隔符(比如空格)后换行;
2)在运算符之前换行;
3)不拆分完整的单词;
4)换行后如果需要缩进则不应缩进超过行中间位置,以美观为准。
示例:
if ((condition1 && condition2) || (condition3 && condition4)
||!(condition5 && condition6)) {
}
6.6 空行
函数之间空2行,get/set方法除外。
示例:
function createUser() {
}
function destoryUser() {
}
function getUser() {
return er;
}
function setUser(user) {
er = user;
}
代码逻辑段之间空一行。
变量和函数声明之间空一行。
示例:
function getUser(id) {
//判断参数id的合法性
if ( !id ) {
throw new Error(””);
}
//根据参数id查找user对象
findUser(id);
}
6.7 语句
6.7.1 表达式语句
表达式语句以分号结束。
示例:
var i = 0;
alert(”提示信息”);
Math.cos(x);
6.7.2 复合语句
复合语句是包含在花括号中的一个语句或者语句块,复合语句遵循如下排版规则:
1)左花括号“{ ”位于复合语句起始行的行尾, 右大括号"}"应另起一行并与复合语句首行对齐;
2)花括号中的语句缩进一个层次(4个空格)。
示例:
{
var x = 0;
}
6.7.3 if-else语句
if-else语句用"{"和"}"括起来,避免发生错误。
示例:
if ( expression1 ) {
statement1;
} else if ( expression2 ) {
statement2;
} else {
statement3;
}
6.7.4 for语句
示例:
for (initialize; test; increment) {
statement;
}
空for语句按如下格式:
for (initialize; test; increment);
6.7.5 for-in语句
示例:
for ( variable in object ) {
statement;
}
6.7.6 while语句
示例:
while ( expression ) {
statement;
}
6.7.7 do-while语句
示例:
do {
statement;
} while ( expression );
6.7.8 switch语句
示例:
switch ( expression ) {
case value1:
statement;
/*注释说明*/
case value2:
statement;
break;
default:
statement;
break;
}
当执行完一个case后需要继续往下执行(即没有break语句)时,应在break语句的位置添加注释。
6.7.9 try-catch-finally语句
示例:
try {
statement;
} catch ( e ) {
statement;
} finally {
statement;
}
7 字符集编码规则
统一使用字符集编码:UTF-8。
8 编码健壮性遵循原则
8.1 合理使用闭包
闭包容易导致内存泄露,尤其是使用闭包函数处理DOM事件时,经常会出现HTML元素与闭包函数的相互引用,从而导致无法释放HTML元素和闭包函数的内存,因此要合理地使用闭包,避免循环引用。
示例:
//劣
//在执行完foo方法后,局部变量element不会被垃圾回收,因为它的闭包函数被注册到element元素的
单击//事件中,被element引用,而闭包函数又持有foo函数内的所有变量包括element,如此形成
element和foo
//内的闭包函数的循环引用,从而element和foo均不能被垃圾回收,导致内存泄露。
function foo(element, a, b) {
element.onclick = function() {
/* 使用变量a、b */
};
}
//优
//改造后的正确用法如下:
// element会引用函数bar返回的函数,不会引用到foo,避免了循环引用,从而执行完foo方法后,element
//将被垃圾回收。
function foo(element, a, b) {
element.onclick = bar(a, b);
}
function bar(a, b) {
return function() {
/* 使用a、b */
}
}
8.2 合理使用for和for-in循环
使用普通的for语句循环数组,使用for-in语句循环对象。
示例:
//劣
function printArray(arr) {
for (var key in arr) {
alert(arr[key]);
}
}
printArray([0,1,2,3]); // 可以alert出正确的结果
var a = new Array(10);
printArray(a); // 错误:没有alert
a = document.getElementsByTagName('*');
printArray(a); // 错误:会alert出a的length值
a = [0,1,2,3];
a.buhu = 'wine';
printArray(a); // 错误:会alert出wine
a = new Array;
a[3] = 3;
printArray(a); // 错误:只alert一次
//优
//把以上示例的for-in语句改造成普通的for语句,则不存在以上问题
function printArray(arr) {
var l = arr.length;
for (var i = 0; i < l; i++) {
alert(arr[i]);
}
}
只在循环对象时使用for-in。
示例:
for ( var p in user ) {
alert(p);
}
//注意添加到对象的prototype中的成员将被包含在遍历中,可以通过使用hasOwnProperty方法来区分
是否对象自有属性或者方法。
8.3 避免无限循环
1)在使用for等循环语句进行循环时,要确保终止循环的条件一定能被触发,避免无限循环;
2)避免函数之间相互调用,形成隐式无限循环。
示例:
//错误
function f1() {
f2();
}
function f2() {
f1();
}
f1();
8.4 区分===和==
“===”是完全等于,即除了值必须相等外,类型也必须相等。
示例:
var v1 = 1;
var v2 = ”1”;
alert(v1 == v2); //true
alert( v1 === v2 );//false
8.5 禁止使用with(){}
在JavaScript编码中禁止使用with(){},with可能会与当前作用域的属性和方法产生冲突。
8.6 字符串拼接
在JavaScript中使用“+”进行字符串多行拼接效率低于利用数组方式拼接,所以应尽量的使用数组的join方法进行字符串拼接。
示例:
var arr = new Array();
with (arr)
{
push("I");
push(" Love");
push(" China");
}
var string = arr.join("");
8.7 避免在函数中定义全局变量
示例:
//劣
function doSomething() {
user = {}; //不使用var关键字会定义一个全局的user变量
}
8.8 避免在JavaScript中包含过多的HTML、CSS内容
在JavaScript中尽量少包含CSS样式、HTML的内容,如果必须使用CSS,应尽量把样式写入CSS文件,在JavaScript中对CSS进行操作,如果必须使用HTML,且HTML内容比较多,则应把HTML相关内容归集到一个文件中,并根据需要使用模板技术。
8.9 异常处理
1)把可能出现错误的程序块放入try语句中,把处理错误的代码放到catch或者finally语句中;
2)在finally子句中使用return语句时,return的返回值应为一个变量。
示例:
//劣
try {
return 2;
} catch( e ) {
} finally {
return 1; //最终返回的永远是1
}
//优
var rv = -1;
try {
rv = 2;
} catch( e ) {
rv = 1;
} finally {
return rv; //如果没有错误则返回2,有错误则返回1
}
3)使用throw抛出异常信息,应对异常转译,原始异常按异常链的方式抛出,为排错提供帮助。
示例:
//优
function process(values) {
if ( !values ) {
throw new Error(”xx.js process(): 参数values 必须有值”);
}
}
4)在服务器端记录JavaScript错误,形成日志文件,以便分析错误。
示例:
/**
* 通过Image元素记录错误到服务器端
* @param {String} level 错误级别,可选值:debug、info、warn、erorr
* @param {String} msg 错误信息
*/
function logError(level, msg) {
var img = new Image();
img.src = ”/context/log.so?level=” + encodeURIComponent(level) + ”&msg=” +
encodeURLComponent(msg);
}
for ( var i = 0; i < 100; i++ ) {
try {
//Code
} catch ( error ) {
logError(”info”, “处理…时发生错误,错误时的状态是…”);
}
}
9 安全
9.1 JSON串的安全过滤
在使用eval()函数时可能存在安全问题,eval()函数可以执行脚本和JSON字符,但是当用eval执行通过界面输入的JSON内容时,JSON字符串中可能包含一些恶意代码,从而导致安全问题,因此建议在使用eval前先对JSON内容进行安全处理,建议使用一些成熟的过滤JSON字符串的工具库进行处理,例如:Crockford的JavaScript JSON库。
9.2 JavaScript脚本攻击
在服务器端通过filter统一过滤用户输入,避免恶意脚本进入系统,避免JavaScript脚本攻击。
9.3 Cookie泄露
Cookie安全的问题多数情况下采用的应对措施是不要在Cookie里存放涉及安全的信息。
9.4 防止js代码泄露
1)避免页面上直接出现关键性的js代码,关键的js代码需要统一放在js文件中,然后在页面中引入js文件使用;
2)引入的js文件可以使用压缩或代码混淆技术。
10 性能优化
10.1 合理使用prototype
在使用prototype实现继承时,不应层级太多,否则会影响到在子类中使用父类方法时的性能。
10.2 本地缓存对象属性
在多次使用对象属性的程序块中,应为属性定义本地变量,在后续程序只使用本地变量,这样可以减少JavaScript引擎在对象中查找属性的次数,提高访问性能,在循环中使用引用时尤其有效。
示例:
var obj = {name:’’};
var name = ;
var obj2 = {};
for ( var i = 0; i < 100; i++ ) {
= name + i;
}
10.3 减少操作HTML DOM结构的次数
减少JavaScript操作DOM的次数,在对DOM进行新增、替换节点时,可以先把相应的内容准备好后,通过innerHTML方式一次完成对DOM的操作。
10.4 引用JavaScript文件
<script src=”filename.js”>标签可以放在body的最后,以减少由于加载script文件而导致其它页面组件的延迟显示问题。
10.5 事件代理
在为HTML添加较多事件函数时,建议采用事件代理机制,例如:为表格的每个单元格注册事件处理器时采用代理机制对性能改善尤为明显。
11 第三方框架引入规范
引入的框架只能是不对系统内部造成影响的前端框架,推荐使用jQuery框架。
12 安全性要求
安全性要求遵从《国家电网公司信息系统全生命周期安全管控系列规范四安全编程规范》。
13 附录
13.1 一致性约束
13.2 保留字
const float long short volatile
13.3 JSON格式
在JSON中对象是一个无序的“‘名称/值’对”集合。
一个对象以“{”(左括号)开始,“}”(右括号)结束。
每个“名称”后跟一个“:”(冒号);“‘名称/值’对”之间使用“,”(逗号)分隔,名称必须在双引号“”内。
数组是值(value)的有序集合。
一个数组以“[”(左中括号)开始,“]”(右中括号)结束。
值之间使用“,”(逗号)分隔。
值(value)可以是双引号内的字符串(string)、数值(number)、true、false、 null、对象(object)或者数组(array)。
这些结构可以嵌套。
字符串(string)是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义。
一个字符(character)即一个单独的字符串(character string)。
字符串(string)与C或者Java的字符串非常相似。
数值(number)也与C或者Java的数值非常相似。
JSON格式的数据举例:
{
"anObject": {
"numericProperty": -122,
"stringProperty": "An offensive \" is problematic", "nullProperty": null,
"booleanProperty": true,
"dateProperty": "2011-09-23"
},
"arrayOfObjects": [
{"item": 1},
{"item": 2},
{"item": 3}
],
"arrayOfIntegers": [1,2,3,4,5]
}
13.4 常用类型值举例
13.5 数据处理建议
13.5.1 数据处理控件
后台请求:如果是IE浏览器,则采用new window.ActiveXObject( "Microsoft.XMLHTTP" )对象,如果是FireFox、Chrome等浏览器则采用new window.XMLHttpRequest()对象。
XML处理:如果是IE浏览器,则采用newActiveXObject("Microsoft.XMLDOM" )对象,如果是FireFox、Chrome等其他浏览器则采用new DOMParser()对象。
13.5.2 数据格式与处理
推荐采用JSON作为JavaScript的数据格式(JSON的格式描述请参看附录:《JSON格式》),通过操作数组或者对象可实现对JSON数据的处理。
如果是跨域数据,则可采用JSONP格式。
13.5.3 缓存使用
数据缓存通常有三种方式:
1)服务端缓存
通过在服务端设置响应头的Expires超期时间,在超期时间之前,该url不会再向服务端发起请求,直接从客户端获取缓存数据。
该方式主要用于缓存从不改变的内容,但是实际很难确定内容是否会在超期时间内不改变,因此不建议使用该方式,避免出现内容更新不及时的问题。
2)客户端本地缓存
在JavaScript中通过一个变量缓存来自服务端的数据,下次在使用时直接通过变量获取,该方式通常可以在当前窗口被卸载前使用缓存数据,当窗口被重新装载时缓存数据被替换成新的数据,因此该方式比较适合在窗口卸载前数据不变化的场景。
3)cookie缓存
通过cookie缓存的数据可以被多个窗口共享,且在客户端能很方便的控制其超期时间,该方式通常被用到跨窗口共享缓存数据的场景,但是需要注意浏览器会限制cookie的大小,因此不建议向cookie里存放过多的数据,如果是缓存到cookie文件中,则需要注意缓存数据中不应保护涉及安全的数据。