js规范
Array 和 Object 直接量
- 为了避免这些歧义, 我们应该使用更易读的直接量来声明.
-
var a = [x1, x2, x3]; var a2 = [x1, x2]; var a3 = [x1]; var a4 = [];
- 虽然 Object 构造器没有上述类似的问题, 但鉴于可读性和一致性考虑, 最好还是在字面上更清晰地指明.
var o = new Object(); var o2 = new Object(); o2.a = 0; o2.b = 1; o2.c = 2; o2['strange key'] = 3;
编码
- 统一用 utf-8
长度
-
长度不超过 80 个字符。
-
参考:
pep8 为 79 个字符
npm 为 80 个字符
google 为 80 个字符
缩进
- 一般缩进4个字符,若层次比较多的可以缩进2个字符。
小括号
-
不要滥用括号, 只在必要的时候使用它.
-
对于一元操作符(如delete, typeof 和 void ), 或是在某些关键词(如 return, throw, case, new )之后, 不要使用括号.
花括号
- 花括号不换行
- 好
if (foo) { }
- 坏
if (foo) { }
- 好
- 不允许一行判断,一律换行
- 坏
if (foo) return;
- 坏
命名约定
-
常量 UPPERCASE_WORD
-
变量 camelName
-
类名 CamelName
-
属性和方法
- 文件或类中的私有属性, 变量和方法名应该以下划线 "_" 开头.
- 保护属性, 变量和方法名不需要下划线开头, 和公共变量名一样.
-
方法和函数参数
- 可选参数以 opt_ 开头.
- 函数的参数个数不固定时, 应该添加最后一个参数 var_args 为参数的个数. 你也可以不设置 var_args而取代使用 arguments.
- 可选和可变参数应该在 @param 标记中说明清楚. 虽然这两个规定对编译器没有任何影响, 但还是请尽量遵守
-
文件名
文件名应该使用小写字符, 以避免在有些系统平台上不识别大小写的命名方式. 文件名以.js结尾, 不要包含除 - 和 _ 外的标点符号(使用 - 优于 _).
空格
- 操作符之间需要空格
- 好
var x = y + z
- 坏
var x=y+z
- 好
- 只空一格
- 好
{ a: 'short', looooongname: 'long' }
- 坏
{ a : 'short', looooongname: 'long' }
- 好
逗号与换行
- 建议用自然人的处理方法
{ a: 'a', b: 'b', c: 'c' }
- 不建议使用 npm 风格的逗号与换行,即
{ a: 'a' ,b: 'b' ,c: 'c' }
变量声明
-
首先,变量在使用前必须声明。
-
对于单 var 模式和多 var 模式,不做强行约定,但同一个文件里,风格必须一致。
字符串
- 单引号 (') 优于双引号 (")
明确作用域
- 任何时候都要明确作用域 - 提高可移植性和清晰度. 例如, 不要依赖于作用域链中的 window 对象. 可能在其他应用中, 你函数中的 window 不是指之前的那个窗口对象.
注释
- 方法/函数注释:
/** * Converts text to some completely different text. * @param {string} arg1 An argument that makes this more interesting. * @return {string} Some return value. */
- 顶层/文件注释:
- 顶层注释用于告诉不熟悉这段代码的读者这个文件中包含哪些东西. 应该提供文件的大体内容, 它的作者, 依赖关系和兼容性信息. 如下:
// Copyright 2009 Google Inc. All Rights Reserved. /** * @fileoverview Description of file, its uses and information * about its dependencies. * @author user@google.com (Firstname Lastname) */
技巧:
-
下面的布尔表达式都返回 false:
- null
- undefined
- '' 空字符串
- 0 数字0
-
但小心下面的, 可都返回 true:
- '0' 字符串0
- [] 空数组
- {} 空对象
-
下面段比较糟糕的代码:
while (x != null) {
-
你可以直接写成下面的形式(只要你希望 x 不是 0 和空字符串, 和 false):
while (x) {
-
如果你想检查字符串是否为 null 或空:
if (y != null && y != '') {
-
但这样会更好:
if (y) {
-
注意: 还有很多需要注意的地方, 如:
Boolean('0') == true '0' != true 0 != null 0 == [] 0 == false Boolean(null) == false null != true null != false Boolean(undefined) == false undefined != true undefined != false Boolean([]) == true [] != true [] == false Boolean({}) == true {} != true {} != false
-
条件(三元)操作符 (?:)
- 三元操作符用于替代下面的代码:
if (val != 0) { return foo(); } else { return bar(); }
- 你可以写成:
return val ? foo() : bar();
- 在生成 HTML 代码时也是很有用的:
var html = '<input type="checkbox"' + (isChecked ? ' checked' : '') + (isEnabled ? '' : ' disabled') + ' name="foo">';
- 三元操作符用于替代下面的代码:
-
&& 和 ||
- 二元布尔操作符是可短路的, 只有在必要时才会计算到最后一项.
-
"||" 被称作为 'default' 操作符, 因为可以这样:
/** @param {*=} opt_win */ function foo(opt_win) { var win; if (opt_win) { win = opt_win; } else { win = window; } // ... }
-
你可以使用它来简化上面的代码:
/** @param {*=} opt_win */
function foo(opt_win) { var win = opt_win || window; // ... }
-
"&&" 也可简短代码.比如:
if (node) { if (node.kids) { if (node.kids[index]) { foo(node.kids[index]); } } }
-
你可以像这样来使用:
if (node && node.kids && node.kids[index]) { foo(node.kids[index]); }
-
或者:
var kid = node && node.kids && node.kids[index]; if (kid) { foo(kid); }
-
不过这样就有点儿过头了:
node && node.kids && node.kids[index] && foo(node.kids[index]);
-
使用 join() 来创建字符串
- 通常是这样使用的:
function listHtml(items) { var html = '<div class="foo">'; for (var i = 0; i < items.length; ++i) { if (i > 0) { html += ', '; } html += itemHtml(items[i]); } html += '</div>'; return html; }
- 但这样在 IE 下非常慢, 可以用下面的方式:
function listHtml(items) { var html = []; for (var i = 0; i < items.length; ++i) { html[i] = itemHtml(items[i]); } return '<div class="foo">' + html.join(', ') + '</div>'; }
- 你也可以是用数组作为字符串构造器, 然后通过 myArray.join('') 转换成字符串. 不过由于赋值操作快于数组的 push(), 所以尽量使用赋值操作.
- Node lists 是通过给节点迭代器加一个过滤器来实现的. 这表示获取他的属性, 如 length 的时间复杂度为 O(n), 通过 length 来遍历整个列表需要 O(n2).
var paragraphs = document.getElementsByTagName('p'); for (var i = 0; i < paragraphs.length; i++) { doSomething(paragraphs[i]); }
- 这种方法对所有的 collections 和数组(只要数组不包含 falsy 值) 都适用.
var paragraphs = document.getElementsByTagName('p'); for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) { doSomething(paragraph); }
- 在上面的例子中, 也可以通过 firstChild 和 nextSibling 来遍历孩子节点.
-
var parentNode = document.getElementById('foo'); for (var child = parentNode.firstChild; child; child = child.nextSibling) { doSomething(child); }
- 通常是这样使用的: