java script代码规范(Google)
变量必须使用var关键字
没写var,则变量会暴露在全局上下文中,可能与现有变量冲突。
常量声明使用大写字符,并用下划线分隔,例如NAMES_LIKE_THIS
分号,为避免隐式分隔,总是使用分号
嵌套函数可以使用
不要在块内声明函数
if(x){
function foo(){
}
}
// 这种容易出问题
标准特性总是优于非标准特性
例如使用string.charAt(3)而不用string[3]
不要封装基本类型
// 不能去封装基本类型,下面做法是不被允许的
var x = new Boolean(false);
多级原型结构
多级原型结构指JavaScript中的继承关系,当你自定义一个D类,把B类作为其原型,就获得了一个多级原型结构
尽量不要直接定义继承。
方法定义
// 如下形式给构造器添加方法或成员
Foo.prototype.bar = function(){
/*...*/
}
闭包
官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。示例如下
var Circle = function() { var obj = new Object();
obj.PI = 3.14159;
obj.area = function( r ) {
return this.PI * r * r;
}
return obj;
}
var c = new Circle();
alert( c.area( 1.0 ) );
这种写法是声明一个变量,将一个函数当作值赋给变量。
闭包需要小心使用。因为闭包保留了一个指向它封闭作用域的指针,所以在给DOM元素附加闭包时,很可能会产生循环引用,进一步导致内存泄漏。比如下述代码
function foo(element,a,b){
element.onclick = function{/* uses a and b */};
}
// 上述即使没有使用element,闭包也保留了element,a和b的引用。由于element也保留了对闭包的引用,这就产生了循环引用,因此不能被GC回收。可以将代码重构为以下形式
function foo(element,a,b){
element.onclick = bar(a,b);
}
function bar(a,b){
return function(){ /* uses a and b*/}
}
eval()慎用
eval()会让程序执行的比较混乱,当eval()里面包含用户输入的话就更加危险。
但当需要解析序列化串的情况下可以使用eval.
with(){}不要使用
//使用with会让你的代码在语义上变得不清晰,因为with的对象,可能会与局部变量产生冲突,从而改变你程序原本的用意
this仅在对象构造器,方法,闭包中使用
for-in循环,只用于object/map/hash的遍历
// 对array使用for-in循环有时会出错,因为for-in不是从0到len-1遍历的,而是所有出现在对象及其原型链的键值。失败案例如下:
function prinArray(arr){
for(var key in arr){
print(arr[key])
}
}
printArray([0,1,2,3]);
var a = new Array(10);
printArray(a);//运行就出错了
多行字符串不要使用
// 它不是ECMAScript的标准规范,所以这种写法容易出现奇怪的错误。
var ms = 'fsfsdfds\
sdfdsfsd\
fdsfs
'
避免使用array及Object构造器
//以下代码在构造器里传入数据时可能会出现问题
var a = new Array(x1,x2);
var o = new Object();
//最好都改成直接量
var a = [x1,x2];
var o = {};
JavaScript编码风格
命名
- 属性和方法
- 类中的私有属性,变量和方法应以下划线“_”开头
- 类中的保护属性,变量和方法和公共变量名一样
- 方法和函数参数
可选参数以opt_开头;函数参数个数不定时,最后一个参数var_args为参数的个数。 - Getters和Setters
命名get/set+参数首字母大写。例如getName()/setName() - 全局代码命名
//使用一个唯一的,与工程/库相关的名字作为前缀标识。例如工程是Project Sloth,那么命名为sloth.*。具体示例如下
var sloth = {};
sloth.sleep = function() {
...
};
- 外部代码和内部代码使用不同的命名空间
外部代码指的是来自你代码体系的外部,可以独立编译。如果外部代码都在foo.hats.*里,那么自己的代码就不能在foo.hats.*下命名
- 不要对命名空间创建别名
- 文件名应该使用小写字符,不要包含除-和_外的标点符号(-优于_)
可以延迟初始化变量
代码格式化
- 同行插入大括号
if (something) {
}
- 数组和对象初始化
- 长度不长,写在一行
- 初始值占多行,缩进2个空格
- 不要试图手工对齐初始值
- 函数参数
尽量在同一行上,如果一行超过80字符,以4个空格缩进或者与括号对齐。 - 传递匿名函数
函数体从调用该函数的左边开始缩进2个空格,而不是从function这个关键字开始。示例如下
var names = items.map(
funtion(item){
return item.name;
};
)
- 使用空行划分一组逻辑上相关联的代码片段
- 二元和三元操作符
直接看示例
var x = a ? b : c;
var y = a ?
LongButSimpleOperandB : LongButSimpleOperandC
字符串
单引号优于双引号
可见性
使用JsDoc中的两个标记@private和@protected,标记为@private的全局变量和函数,表示它们只能在当前文件中访问。标记为@private的构造器,表示该类只能在当前文件或是其静态/普通成员中实例化。
另外,永远不要为全局变量,函数,构造器加@protected标记。
注释
- 对于基本类型的常量注释,只需说明类型
/**
* 一分钟的秒数
* @type {number}
SECONDS_IN_A_MINUTE = 60
- 对于非基本类型的常量注释,使用@const标记
/**
* 秒数对应的时间列表
* @type {Object.<number>}
* @const
SECONDS_TABLE = {
minute:60,
hour:60*60,
day:60*60*24
}
- 文件注释
顶层开头注释用于告诉不熟悉代码的读者这个文件包含哪些东西,应该提供文件的大体内容,它的作者,依赖关系和兼容性信息。如下:
// Copyright 2009 Google Inc. All Rights Reserved
/**
* @fileoverview 文件描述,他的使用和必要信息
* 存在的依赖
* 作者
- 类注释
类注释描述类的功能和用法,也需要说明说明构造器参数,如果该类继承自其他类,应该使用@extends标记,如果该类是对接口的实现,应用使用@implements标记。示例如下:
/**
* 类的功能
* @param {string} arg1 参数一的描述
* @param {Array.<number>} arg2 参数二的描述
* @constructor
* @extends {goog.Disposable}
- 方法和函数的注释
提供参数的说明,使用完整的句子,并用第三人称来书写说明
/**
* 函数功能描述
* @param {string} arg1 参数一的描述
* @param {Array.<number>} arg2 参数二的描述
* @return {string} 返回值描述
- 属性注释
提供参数的说明,使用完整的句子,并用第三人称来书写说明
/**
* 参数描述
* @type {string} 值描述
- 类型转换注释
添加类型标记注释来明确,必须要在表达式和类型注释外面包裹括号。
/** @type {number} */ (x)