原文链接:http://www.javascripttoolbox.com/bestpractices/
翻译声明:非逐句逐字翻译,若有翻译不当,纯属搞笑。
翻译状态:未完成

介绍

这篇文档是一份清单,它罗列了一系列开发JavaScript代码的最佳的编程实践和首选的编程方法。文档中的每条内容都基于JavaScript社区中众多开发者的意见和经验总结而来。但是,这些条款仅仅是一些建议,而并非需要绝对遵守的原则,一些经验丰富的开发者对于以下描述的内容,可能会持有些许不同的意见。

始终使用var关键字

JavaScript中变量只有两种作用域范围:全局作用域和函数作用域, 使用var关键字对于保持变量作用域清晰是至关重要的。当声明一个变量作为全局变量或者函数级的变量(译者注:函数内部声明的变量,也就是在函数内部的局部变量), 始终在声明的最前面添加var关键字。下面的例子强调不使用var关键字会造成的潜在问题:

不使用var造成的问题

var i=0; // 正确:通过声明创建了一个全局变量
function test() {
   for (i=0; i<10; i++) {
      alert("Hello World!");
   }
}
test();
alert(i); // 警告:全局变量i的当前值为10

由于函数内部的变量i没有使用var关键字声明为函数级变量,因此在函数循环体中初次使用变量i,它会往外层的名字空间寻找该变量名,在这个例子中它最终引用了全局变量i。始终使用var关键字声明全局变量是一个不错的编程习惯,但是要声明函数作用域的变量
var的使用却是必不可少的。下面的两种方法在功能上是等价的:

修正后的函数1

function test() {
   var i=0;
   for (i=0; i<10; i++) {
      alert("Hello World!");
   }
}

修正后的函数2

function test() {
   for (var i=0; i<10; i++) {
      alert("Hello World!");
   }
}

译者注:JavaScript是没有块级作用域的,所以修正后的函数1和2是一致的,变量i都被声明成函数级变量。

特性检测而不是浏览器检测

JavaScript中很常见的一种做法是,通过某种手段编写代码来检测浏览器的版本,并基于此结果而采取不同的动作。通常这是一种非常坏的习惯。即使某些代码通过查询navigator对象来检测,有时候依然是不可靠的(译者注:用户可以通过第三方工具轻松更改navigator.userAgent等属性)。

更好的方法是使用特性检测。也就是说,在使用一些旧式浏览器可能不支持的高级特性之前,首先检测这个函数或者属性是否存在,然后再使用它。这比专门去检测浏览器的版本并假定它拥有某种功能的方法更加合理而可靠。有一篇深入讨论这个话题的文章,你可以在这里找到它。下面是一个采用特性检测的方法的例子:

简单例子

if (document.getElementById) {
   var element = document.getElementById('MyId');
}
else {
   alert('Your browser lacks the capabilities required to run this script!');
}

使用中括号运算符

当所要访问的对象属性名,只有在运行时才能确定或者属性中包含非法的字符时(与点号运算符不兼容),请使用中括号运算符。如果你不是一位经验丰富的JavaScript程序员,总是使用中括号运算符访问对象的属性不失为一种好的习惯。
JavaScript中对象属性主要有两种访问方式:点号运算符和中括号运算符。它们的语法如下所示:

点号

MyObject.property

中括号

MyObvject['property']

使用点号运算符,属性名称是固定的,不能够在运行时改变;而相对地若使用中括号运算符,属性名可以是一个固定的属性名,或者是一个变量,甚至是一个返回字符串属性名的函数调用。

如果对象拥有属性"value1", "value2", "value3”, 而你想通过一个整数变量i(例如i=2)来确定访问具体的某个属性:

正确的做法

MyObject["value"+i]

错误的做法

MyObject.value+i

有时在一些服务端环境中(如PHP、Struts等等),表单字段名称后面会追加"[]",表明该字段应该被当成一个数组来处理。然而在客户端环境下,点号运算符访问带有"[]"的属性名是不合法的,这种情况下会抛出"Synatax error"的异常,原因是在JavaScript中"[]"是用来引用一个数组元素。在这种情况下,必须使用中括号运算符。

正确的做法

formref.elements["name[]"]

错误的做法

formref.elements.name[]

建议在必须使用中括号运算符的场合,一定要使用它,而在某些非必须场合,可以按个人的喜好和编程风格选择是否使用。一个好的经验原则是,访问对象的标准属性的时候使用点号运算符,而访问页面中定义的属性时则使用括号运算符。因此,虽然document["getElementById"]()也是合法的,但最好还是使用document.getElementById这种语法来访问,因为getElementById是在DOM规范中定义的document对象的标准属性。混合使用这两种运算符来访问对象的属性,可以清楚地区分哪个属性是标准定义的,哪个属性是页面内容中定义的:

document.forms["myformname"].elements["myinput"].value

在这里,formsdocument对象的标准属性,而表单名称myformname是在页面中定义的。类似地,elementsvalue是规范中标准定义的属性,而myinput同样是页面中定义的属性名称。这种语法非常清楚并且容易理解,是一种推荐遵循的风格,但并非是严格的原则。

避免使用eval函数

JavaScript中的eval()函数是一种在运行时执行任意代码的方法。在几乎所有的情况下,eval都不应该被使用。如果它存在你的页面脚本中,几乎总会有一种更加合适的方法来完成你正在做的事情。例如,eval经常被不了解中括号运算符的程序员使用。

记住一条原则是,"eval是邪恶的"。千万不要使用它,除非你是一个经验丰富的开发者,并且你知道你的情况是一个例外。

正确地访问表单和表单元素

避免使用with语句

锚链接中使用onclick代替JavaScript伪协议

使用一元+运算符转换为数字

避免使用document.all

不要在script标记中使用HTML注释

不要污染全局名字空间

避免同步Ajax调用

当创建Ajax请求时,可以选择同步或者异步模式。在异步模式,Ajax请求在后台执行,而其它的浏览器操作能够继续处理;在同步模式,浏览器会一直等待,直到Ajax请求完成返回后,才继续处理其它操作。

应该避免创建同步的Ajax请求。这些请求会导致浏览器阻塞直到请求返回。在服务器繁忙的情况下,回应需要一段时间,用户的浏览器在这段时间内将不允许做任何其它的事情。在回应无法正确接收的情况下,浏览器可能会一直阻塞直到请求超时。

如果你认为你的情况确实需要使用同步模式,你可能是时候重新思考你的设计了。实际上很少(如果有的话)的情况下需要同步模式的Ajax请求。

使用JSON

当将数据存储为文本内容或者通过Ajax发送/请求数据时,如果可能请考虑用JSON代替XML格式。JSON(JavaScript Object Notation)是一种更加紧凑和高效的数据格式,并且不依赖特定的某种语言(译者注:是指语言无关吗?)。

使用正确的<script>标记

在script标记中LANGUAGE属性已经被废弃,创建JavaScript代码块的正确方法是:

<script type="text/javascript">
// code here
</script>