浅谈Javascript编码规范

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 等流行的编辑器,均提供了此功能。 

空行

使用空行来划分一组逻辑上相关联的代码片段

标识符命名编辑本段回目录

  1. 变量、参数、成员变量、函数等名称均以小写字母开头
  2. 构造器的名称以大写字母开头
  3. 常量及全局变量采用全部大写的形式,单词间用下划线分隔。例如DEFAULT_FRAME_LAYOUT
  4. 下划线'_'开头的变量一般习惯于标识私有 / 局部成员。而美元符号'$'开头的变量习惯于标识系统相关,比如系统进程等。应避免用下划线'_'或美元符号'$'来命名标识符。尽可能地降低代码的阅读负担。
  5. 函数名尽量采用 “动词+名词”的命名方式
  6. 函数名称中的动词前缀必须是和函数功能相关的完整动词
  7. 函数名称的第一个单词全部小写,后面的单词首字母大写,例:getUserName()

声明编辑本段回目录

变量的声明

在函数的开始应先用 var 关键字声明函数中要使用的局部变量,注释变量的功能及代表的含义,且应以字母顺序排序。每个变量单独占一行,以便添加注释。这是因为 JavaScript 中只有函数的 {} 表明作用域,用 var 关键字声明的局部变量只在函数内有效,而未经 var 声明的变量则被视为全局变量。声明变量必须加上 var 关键字。

函数的声明

函数也应在调用前进行声明,内部函数应在 var 声明内部变量的语句之后声明,可以清晰地表明内部变量和内部函数的作用域。此外,函数名紧接左括号'('之间,而右括号')'和后面的'{'之间要有个空格,以清楚地显示函数名以其参数部分,和函数体的开始。若函数为匿名 / 无名函数,则 function 关键字和左括号'('之间要留空格,否则可能误认为该函数的函数名为 function。不要在语句块内声明函数。

常量的声明

常量的使用包括但不仅限于以下场景:

  1. URLs  - 可能会变动的url
  2. Settings - 全局或局部的配置信息
  3. Repeated strings -  多次使用的字符串

语句编辑本段回目录

对于简单语句而言,需要提及的仍然是分号必要性,同时,一行最多有一个语句。如果一个赋值语句是用函数和对象来赋值,可能需要跨多行,一定切记要在赋值语句末加上分号。这是因为 JavaScript 中,所有表达式都可以当语句,遇换行符时会解析为表达式的结束,此时不规范的换行和分号的丢失,可能引入新的错误。对于复合语句,if, for, while, do, switch, try … catch 等代码体,函数定义的函数体,对象的定义等都需要放在花括号'{}'里面。

  1. '{' 应在行末,标志代码块的开始。
  2. '}' 应在一行开头,标志代码块的结束,同时需要和'{'所在行的开始对齐,以表明一个完整的复合语句段。这样可以极大地提高代码的可阅读性,控制逻辑能清晰地表现出来。
  3. 被包含的代码段应该再缩进 4 个空格。
  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:
  1. null
  2. undefined
  3. '' 空字符串
  4. 0 数字0
  5. NaN
  6. false
但小心下面的, 可都返回 true:
  1. '0' 字符串0
  2. [] 空数组
  3. {} 空对象
下面段比较糟糕的代码:
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);
}

禁止使用的东西编辑本段回目录

  1. 禁止使用with
  2. 禁止使用eval
  3. 禁止使用位运算符
  4. 禁止使用++和--
  5. 禁止使用void
  6. 禁止使用new Number、new String、new Boolean、new Array、new Object
  7. 禁止使用==和!=

Jslint检查编辑本段回目录

所有javascript代码都要经过jslint检查

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值