JavaScript 文件引用编辑本段回目录
JavaScript 程序应该尽量放在 .js 的文件中,需要调用的时候在 HTML 中以 <script src="filename.js"> 的形式包含进来。JavaScript 代码若不是该 HTML 文件所专用的,则应尽量避免在 HTML 文件中直接编写 JavaScript 代码。因为这样会大大增加 HTML 文件的大小,无益于代码的压缩和缓存的使用。另外,<script src="filename.js"> 标签应尽量放在文件的后面。这样会降低因加载 JavaScript 代码而影响页面中其它组件的加载时间。
代码排版编辑本段回目录
行长度
每行代码应小于 80 个字符。如果代码较长,应尽量选择换行,下一行代码应缩进8 个空格。这样可以使代码排版整齐,减轻阅读代码的疲劳感。换行缩进 8 个空格可以和代码段的缩进 4 个空格区分开,以增强代码的可阅读性。
行结束
JavaScript 语句应该以分号结束。但大多数浏览器允许不写分号,只要在本应是分号的地方有一个换行符就行。但是如果代码行较长需要换行的时候,有哪些注意事项呢?换行应选择在操作符和标点符号之后,最好是在逗号','之后,而不要在变量名、字符串、数字、或')' ']' '++' '--'等符号之后换行。这样可以有效的防止拷贝、粘贴而引起的错误,并可有效地增强代码的可阅读性。
缩进
用 4 个空格来进行缩进,将编辑器里的 TAB 快捷键重新设置为 4 个空格。据了解 Eclipse, Vi, Nodepad++,Editplus, UltraEdit 等流行的编辑器,均提供了此功能。
空行
使用空行来划分一组逻辑上相关联的代码片段
标识符命名编辑本段回目录
- 变量、参数、成员变量、函数等名称均以小写字母开头
- 构造器的名称以大写字母开头。
- 常量及全局变量采用全部大写的形式,单词间用下划线分隔。例如DEFAULT_FRAME_LAYOUT
- 下划线'_'开头的变量一般习惯于标识私有 / 局部成员。而美元符号'$'开头的变量习惯于标识系统相关,比如系统进程等。应避免用下划线'_'或美元符号'$'来命名标识符。尽可能地降低代码的阅读负担。
- 函数名尽量采用 “动词+名词”的命名方式
- 函数名称中的动词前缀必须是和函数功能相关的完整动词
- 函数名称的第一个单词全部小写,后面的单词首字母大写,例:getUserName()
声明编辑本段回目录
变量的声明
在函数的开始应先用 var 关键字声明函数中要使用的局部变量,注释变量的功能及代表的含义,且应以字母顺序排序。每个变量单独占一行,以便添加注释。这是因为 JavaScript 中只有函数的 {} 表明作用域,用 var 关键字声明的局部变量只在函数内有效,而未经 var 声明的变量则被视为全局变量。声明变量必须加上 var
函数的声明
函数也应在调用前进行声明,内部函数应在 var 声明内部变量的语句之后声明,可以清晰地表明内部变量和内部函数的作用域。此外,函数名紧接左括号'('之间,而右括号')'和后面的'{'之间要有个空格,以清楚地显示函数名以其参数部分,和函数体的开始。若函数为匿名 / 无名函数,则 function 关键字和左括号'('之间要留空格,否则可能误认为该函数的函数名为 function。不要在语句块内声明函数。
常量的声明
常量的使用包括但不仅限于以下场景:
- URLs - 可能会变动的url
- Settings - 全局或局部的配置信息
- Repeated strings - 多次使用的字符串
语句编辑本段回目录
对于简单语句而言,需要提及的仍然是分号必要性,同时,一行最多有一个语句。如果一个赋值语句是用函数和对象来赋值,可能需要跨多行,一定切记要在赋值语句末加上分号。这是因为 JavaScript 中,所有表达式都可以当语句,遇换行符时会解析为表达式的结束,此时不规范的换行和分号的丢失,可能引入新的错误。对于复合语句,if, for, while, do, switch, try … catch 等代码体,函数定义的函数体,对象的定义等都需要放在花括号'{}'里面。
- '{' 应在行末,标志代码块的开始。
- '}' 应在一行开头,标志代码块的结束,同时需要和'{'所在行的开始对齐,以表明一个完整的复合语句段。这样可以极大地提高代码的可阅读性,控制逻辑能清晰地表现出来。
- 被包含的代码段应该再缩进 4 个空格。
- 即使被包含的代码段只有一句,也应该用花括号'{}'包含。尽管不用花括号代码也不会错,但如若需要增加语句的话,则较容易因花括号遗漏而引起的编译错误或逻辑错误。
return语句在使用时也需慎重,如果用表达式的执行作为返回值,请把表达式和 return 放在同一行中,以免换行符被误解析为语句的结束而引起返回错误。return 关键字后若没有返回表达式,则返回 undefined。构造器的默认返回值为 this。
特殊符号编辑本段回目录
空白符
适当的空白行可以大大提高代码的可阅读性,可以使代码逻辑更清晰易懂。同时,在表达式中适当的留空白,也会给代码的阅读带来方便。
关键字的后面如有括号,则最好在关键字和左括号'('之间留空白,如 for, if, while 等。而函数名和括号之间则不宜留空白,但若是匿名函数,则必须在 function 和左括号'('之间留空白,否则,编辑器会误认为函数名为 function。
在表达式中,二元运算符 ( 除左括号'(',左方括号'[',作用域点'.') 和两个操作数之间最好留空白。一元运算符(若不是词 typeof 等)和其操作数之间不宜留空白。
逗号','的后面需要留空白,以显示明确的参数间隔,变量间隔等。
分号';'之后通常表明表达语句的结束,而应空行。在 for 的条件语句中,分号之后则应该留空白。
{ } 和 [ ]
使用{}和[]定义空对象和空数组
== 和 ===
使用'==='来进行逻辑等的判断,用'!=='进行逻辑不等的判断。永远不要使用==和!=。
'和"
优先使用单引号 (‘)
当你创建一个包含 HTML 代码的字符串时就知道它的好处了.
注释编辑本段回目录
顶层/文件注释
顶层注释用于告诉不熟悉这段代码的读者这个文件中包含哪些东西.应该提供文件的大体内容, 它的作者, 依赖关系和兼容性信息. 如下:
// Copyright © 2009 - 2011 DBank网盘 All Rights Reserved
/**
* @fileoverview Description of file, its uses and information
* about its dependencies.
* @author user@google.com (Firstname Lastname)
*/
类注释
每个类的定义都要附带一份注释, 描述类的功能和用法.
也需要说明构造器参数.
如果该类继承自其它类, 应该使用 @extends 标记.
如果该类是对接口的实现, 应该使用 @implements 标记.
/**
* Class making something fun and easy.
* @param {string} arg1 An argument that makes this more interesting.
* @param {Array.<number>} arg2 List of numbers to be processed.
* @constructor
* @extends {goog.Disposable}
*/
project.MyClass = function(arg1, arg2) {
// ...
};
goog.inherits(project.MyClass, goog.Disposable);
方法与函数的注释
提供参数的说明. 使用完整的句子, 并用第三人称来书写方法说明.
/**
* Converts text to some completely different text.
* @param {string} arg1 An argument that makes this more interesting.
* @return {string} Some return value.
*/
project.MyClass.prototype.someMethod = function(arg1) {
// ...
};
/**
* Operates on an instance of MyClass and returns something.
* @param {project.MyClass} obj Instance of MyClass which leads to a long
* comment that needs to be wrapped to two lines.
* @return {boolean} Whether something occured.
*/
function PR_someMethod(obj) {
// ...
}
对于一些简单的, 不带参数的 getters, 说明可以忽略.
/**
* @return {Element} The element for the component.
*/
goog.ui.Component.prototype.getElement = function() {
return this.element_;
};
属性注释
也需要对属性进行注释.
/**
* Maximum number of things per pane.
* @type {number}
*/
project.MyClass.prototype.someProperty = 4;
JSDoc 缩进
如果你在 @param,
@return, @supported, @this 或
@deprecated 中断行, 需要像在代码中一样, 使用4个空格作为一个缩进层次.
/**
* Illustrates line wrapping for long param/return descriptions.
* @param {string} foo This is a param with a description too long to fit in
* one line.
* @return {number} This returns something that has a description too long to
* fit in one line.
*/
project.MyClass.prototype.method = function(foo) {
return 5;
};
jsdoc jsdoc3
Javascript小技巧编辑本段回目录
布尔表达式
下面的布尔表达式都返回 false:
- null
- undefined
- '' 空字符串
- 0 数字0
- NaN
- false
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);
}
使用 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 List
Node lists 是通过给节点迭代器加一个过滤器来实现的.
这表示获取他的属性, 如 length 的时间复杂度为 O(n), 通过 length 来遍历整个列表需要 O(n^2).
var paragraphs = document.getElementsByTagName('p');
for (var i = 0; i < paragraphs.length; i++) {
doSomething(paragraphs[i]);
}
这样做会更好:
var paragraphs = document.getElementsByTagName('p');
for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) {
doSomething(paragraph);
}
这种方法对所有的 collections 和数组(只要数组不包含 falsy 值) 都适用.
在上面的例子中, 也可以通过 firstChild 和 nextSibling 来遍历孩子节点.
var parentNode = document.getElementById('foo');
for (var child = parentNode.firstChild; child; child = child.nextSibling) {
doSomething(child);
}
禁止使用的东西编辑本段回目录
- 禁止使用with
- 禁止使用eval
- 禁止使用位运算符
- 禁止使用++和--
- 禁止使用void
- 禁止使用new Number、new String、new Boolean、new Array、new Object
- 禁止使用==和!=
Jslint检查编辑本段回目录
所有javascript代码都要经过jslint检查