前端开发规范-javascript规范
1.通用约定
注释原则
- As short as possible(如无必要,勿增注释):尽量提高代码本身的清晰性、可读性。
- As long as necessary(如有必要,尽量详尽):合理的注释、空行排版等,可以让代码更易阅读、更具美感。
单行注释
必须独占一行。 // 后跟一个空格,缩进与下一行被注释说明的代码一致。
单行注释
避免使用 /*...*/ 这样的多行注释。有多行注释内容时,使用多个单行注释。
函数/方法注释
- 函数/方法注释必须包含函数说明,有参数和返回值时必须使用注释标识。;
- 参数和返回值注释必须包含类型信息和说明;
- 当函数是内部函数,外部不可访问时,可以使用 @inner 标识;
/** * 函数描述 * * @param {string} p1 参数1的说明 * @param {string} p2 参数2的说明,比较长 * 那就换行了. * @param {number=} p3 参数3的说明(可选) * @return {Object} 返回值描述 */function foo(p1, p2, p3) { var p3 = p3 || 10; return { p1: p1, p2: p2, p3: p3 };}
文件注释
文件注释用于告诉不熟悉这段代码的读者这个文件中包含哪些东西。 应该提供文件的大体内容, 它的作者, 依赖关系和兼容性信息。如下:
/** * @fileoverview Description of file, its uses and information * about its dependencies. * @author user@meizu.com (Firstname Lastname) * Copyright 2009 Meizu Inc. All Rights Reserved. */
2.命名
变量, 使用 Camel 命名法。
var loadingModules = {};
私有属性、变量和方法以下划线 _ 开头。
var _privateMethod = {};
常量, 使用全部字母大写,单词间下划线分隔的命名方式。
var HTML_ENTITY = {};
- 函数, 使用 Camel 命名法。
- 函数的参数, 使用 Camel 命名法。
function stringFormat(source) {}function hear(theBells) {}
- 类, 使用 Pascal 命名法
- 类的 方法 / 属性, 使用 Camel 命名法
function TextNode(value, engine) { this.value = value; this.engine = engine;}TextNode.prototype.clone = function () { return this;};
- 枚举变量 使用 Pascal 命名法。
- 枚举的属性, 使用全部字母大写,单词间下划线分隔的命名方式。
var TargetState = { READING: 1, READED: 2, APPLIED: 3, READY: 4};
由多个单词组成的 缩写词,在命名中,根据当前命名法和出现的位置,所有字母的大小写与首字母的大小写保持一致。
function XMLParser() {}function insertHTML(element, html) {}var httpRequest = new HTTPRequest();
命名语法
类名,使用名词。
function Engine(options) {}
函数名,使用动宾短语。
function getStyle(element) {}
boolean 类型的变量使用 is 或 has 开头。
var isReady = false;var hasMoreCommands = false;
Promise 对象用动宾短语的进行时表达。
var loadingData = ajax.get('url');loadingData.then(callback);
接口命名规范
- 可读性强,见名晓义;
- 尽量不与 jQuery 社区已有的习惯冲突;
- 尽量写全。不用缩写,除非是下面列表中约定的;(变量以表达清楚为目标,uglify 会完成压缩体积工作)
常用词 | 说明 |
options | 表示选项,与 jQuery 社区保持一致,不要用 config, opts 等 |
active | 表示当前,不要用 current 等 |
index | 表示索引,不要用 idx 等 |
trigger | 触点元素 |
triggerType | 触发类型、方式 |
context | 表示传入的 this 对象 |
object | 推荐写全,不推荐简写为 o, obj 等 |
element | 推荐写全,不推荐简写为 el, elem 等 |
length | 不要写成 len, l |
prev | previous 的缩写 |
next | next 下一个 |
constructor | 不能写成 ctor |
easing | 示动画平滑函数 |
min | minimize 的缩写 |
max | maximize 的缩写 |
DOM | 不要写成 dom, Dom |
.hbs | 使用 hbs 后缀表示模版 |
btn | button 的缩写 |
link | 超链接 |
title | 主要文本 |
img | 图片路径(img标签src属性) |
dataset | html5 data-xxx 数据接口 |
theme | 主题 |
className | 类名 |
classNameSpace | class 命名空间 |
True 和 False 布尔表达式
类型检测优先使用 typeof。对象类型检测使用 instanceof。null 或 undefined 的检测使用 == null。
下面的布尔表达式都返回 false:
- null
- undefined
- '' 空字符串
- 0 数字0
但小心下面的, 可都返回 true:
- '0' 字符串0
- [] 空数组
- {} 空对象
不要在 Array 上使用 for-in 循环
for-in 循环只用于 object/map/hash 的遍历, 对 Array 用 for-in 循环有时会出错. 因为它并不是从 0 到 length - 1 进行遍历, 而是所有出现在对象及其原型链的键值。
// Not recommendedfunction printArray(arr) { for (var key in arr) { print(arr[key]); }}printArray([0,1,2,3]); // This works.var a = new Array(10);printArray(a); // This is wrong.a = document.getElementsByTagName('*');printArray(a); // This is wrong.a = [0,1,2,3];a.buhu = 'wine';printArray(a); // This is wrong again.a = new Array;a[3] = 3;printArray(a); // This is wrong again.// Recommendedfunction printArray(arr) { var l = arr.length; for (var i = 0; i < l; i++) { print(arr[i]); }}
二元和三元操作符
操作符始终写在前一行, 以免分号的隐式插入产生预想不到的问题。
var x = a ? b : c;var y = a ? longButSimpleOperandB : longButSimpleOperandC;var z = a ? moreComplicatedB : moreComplicatedC;
. 操作符也是如此:
var x = foo.bar(). doSomething(). doSomethingElse();
条件(三元)操作符 (?:)
三元操作符用于替代 if 条件判断语句。
// Not recommendedif (val != 0) { return foo();} else { return bar();}// Recommendedreturn val ? foo() : bar();
&& 和 ||
二元布尔操作符是可短路的, 只有在必要时才会计算到最后一项。
// Not recommendedfunction foo(opt_win) { var win; if (opt_win) { win = opt_win; } else { win = window; } // ...}if (node) { if (node.kids) { if (node.kids[index]) { foo(node.kids[index]); } }}// Recommendedfunction foo(opt_win) { var win = opt_win || window; // ...}var kid = node && node.kids && node.kids[index];if (kid) { foo(kid);}
3.性能优化
避免不必要的 DOM 操作
浏览器遍历 DOM 元素的代价是昂贵的。最简单优化 DOM 树查询的方案是,当一个元素出现多次时,将它保存在一个变量中,就避免多次查询 DOM 树了。
// Recommendedvar myList = "";var myListHTML = document.getElementById("myList").innerHTML;for (var i = 0; i < 100; i++) { myList += "" + i + "";}myListHTML = myList;// Not recommendedfor (var i = 0; i < 100; i++) { document.getElementById("myList").innerHTML += "" + i + "";}
缓存数组长度
循环无疑是和 JavaScript 性能非常相关的一部分。通过存储数组的长度,可以有效避免每次循环重新计算。
注: 虽然现代浏览器引擎会自动优化这个过程,但是不要忘记还有旧的浏览器。
var arr = new Array(1000), len, i;// Recommended - size is calculated only 1 time and then storedfor (i = 0, len = arr.length; i < len; i++) {}// Not recommended - size needs to be recalculated 1000 timesfor (i = 0; i < arr.length; i++) {}
异步加载第三方内容
当你无法保证嵌入第三方内容比如 Youtube 视频或者一个 like/tweet 按钮可以正常工作的时候,你需要考虑用异步加载这些代码,避免阻塞整个页面加载。
(function() { var script, scripts = document.getElementsByTagName('script')[0]; function load(url) { script = document.createElement('script'); script.async = true; script.src = url; scripts.parentNode.insertBefore(script, scripts); } load('//apis.google.com/js/plusone.js'); load('//platform.twitter.com/widgets.js'); load('//s.widgetsite.com/widget.js');}());
避免使用 jQuery 实现动画
- 禁止使用 slideUp/Down() fadeIn/fadeOut() 等方法;
- 尽量不使用 animate() 方法;