这个文档是基于JavaScript社区众多开发者的意见和经验,在开发JavaScript代码上的最佳实践和首选的方案的明细表。由于这是一个推荐的表而非原则性的方案,经验丰富的开发者可能对下面的表达会有略有不一样的看法。javascript
在JavaScript中,变量不是全局范围的就是函数范围的,使用”var”关键词将是保持变量简洁明了的关键。当声明一个或者是全局或者是函数级(function-level)的变量,需老是前置”var”关键词,下面的例子将强调不这样作潜在的问题。php
不使用 var 形成的问题html
var i=0; // This is good - creates a global variable function test() { for (i=0; i<10; i++) { alert("Hello World!"); } } test(); alert(i); // The global variable i is now 10!
由于变量函数中变量 i 并无使用 var 使其成为函数级的变量,在这个例子中它引用了全局变量。老是使用 var 来声明全局变量是一个不少的作法,但相当重要的一点是使用 var 定义一个函数范围的变量。下面这两个方法在功能上是相同的:前端
正确的函数java
function test() { var i=0; for (i=0; i<10; i++) { alert("Hello World!"); } }
正确的函数程序员
function test() { for (var i=0; i<10; i++) { alert("Hello World!"); } }
一些代码是写来发现浏览器版本并基于用户正使用的客户端的对其执行不一样行为。这个,总的来讲,是一个很是糟的实践。更好的方法是使用特性检测,在使用一个老浏览器可能不支持的高级的特性以前,首先检测(浏览器的)是否有这个功能或特性,而后使用它。这单独检测浏览器版原本得更好,即便你知道它的性能。你能够在 http://www.jibbering.com/faq/faq_notes/not_browser_detect.html找到一个深刻讨论这个问题的文章。express
例子:数组
if (document.getElementById) { var element = document.getElementById('MyId'); } else { alert('Your browser lacks the capabilities required to run this script!'); }
当访问由执行时决定或者包括要不能用”.”号访问的对象属性,使用方括号记法。若是你不是一个经验丰富的JavaScript程序员,老是使用方括号是一个不错的作法浏览器
对象的属性由两种固定的方法来访问:”.”记法和”[ ]“方括号记法:服务器
“.”号记法
MyObject.property
“[ ]“方括号记法
MyObject["property"]
使用”.”号,属性名是硬代码,不能在执行时改变。使用”[ ]“方括号,属性名是一个经过计算属性名而来的字符串。字符串要以是硬代码,也多是变量,甚至能够是一个调回一个字母串值的函数。若是一个属性名在执行产生,方括号是必须,若是你有 “value1″, “value2″, 和 “value3″这样的属性,而且想利用变量 i=2来访问
这个能够运行:
MyObject["value"+i]
这个不能够:
MyObject.value+i
而且在某些服务器端环境(PHP、Struts等)下,Form 表单被附加了 [ ] 号来表示 Form 表单在服务器端必须被看成数组来对待。如此,用”.”号来引用一个包含 [ ] 号的字段将不会执行,由于 [ ] 是引用一个 JavaScript 数组的语法。因此,[ ] 号记法是必须的:
这个能够运行:
formref.elements["name[]"]
这个不能够:
formref.elements.name[]
推荐使用”[ ]“方括号记法是说当其须要时(明显地)老是使用它。当不是严格须要使用它的时候,它是一个私人的偏好和习惯。一个好的经验原则是,使用”.”号记法访问标准的对象属性,使用”[ ]“方括号记法访问由页面定义的对象属性。这样,document["getElementById"]() 是一个完美可行的”[ ]“方括号记法用法,但 document.getElementById() 在语法上是首选,由于 getElementById 是一个 DOM 规范中定义的一个标准文档对象属性。混合使用这两个记法使哪一个是标准对象属性,哪一个属性名是由上下文所定义的,在代码中显得清晰明了:
document.forms["myformname"].elements["myinput"].value
这里,forms 是 document 的一个标准属性,而表单名 myformname 则是由页面所定义的。同时,elements 和 value 属性都是由规范所定义的标准属性。而 myinput 则是由页面所定义的。这页是句法让人很是容易理解(代码的内容),是一个推荐遵循的习惯用法,但不是严格原则。
在JavaScript中,eval()功能是一个在执行期中执行任意代码的方法。在几乎全部的状况下,eval 都不该该被使用。若是它出如今你的页面中,则代表你所作的有更好的方法。举一个例子,eval 一般被不知道要使用方括号记法的程序员所使用。
原则上,”Eval is evil(Eval是魔鬼)”。别使用它,除非你是一个经验丰富的开发者而且知道你的状况是个例外。
全部的 HTML 表单都应该有一个 name 属性。对于 XHTML 文档来讲,name 属性是不被要求的,但 Form 标签中应有相应有 id 属性,并必须用 document.getElementById() 来引用。使用像 document.forms[0] 这样的索引方法来引用表单,在几乎全部状况下,是一个糟糕的作法。有些浏览器把文档中使用 form 来命名的元素看成一个可用的 form 属性。这样并不可靠,不该该使用。
下面这个例子用使用方括号和正确的对象引用方法来展现如何防止错误地引用一个表单的input:
正确引用表单 Input:
document.forms["formname"].elements["inputname"]
糟糕的作法:
document.formname.inputname
若是你要引用一个函数里的两个表单元素,较好的作法是先引用这个form对象,并将其储存在变量中。这样避免了重复查询以解决表单的引用:
var formElements = document.forms["mainForm"].elements; formElements["input1"].value="a"; formElements["input2"].value="b";
当你使用 onChange 或者其余相似的事件处理方法,一个好的作法是老是经过一个引来把 input 元素自己引用到函数中来。全部 input 元素都带有一个对包含其在内的Form表单有一个引用:
<input type="text" name="address" onChange="validate(this)"> function validate(input_obj) { // 引用包含这个元素的form var theform = input_obj.form; // 如今你能够不须要使用硬代码来引用表单自身 if (theform.elements["city"].value=="") { alert("Error"); } }
经过对表单元素的引用来访问表单的属性,你能够写一个不包含硬代码的函数来引用这个页面中任何一个有特定名的表单。这是一个很是好的作法,由于函数变得可重用。
JavaScript 中的 with 声明在一个做用域的前端插入一个对象,因此任何属性/变量的引用将会倚着对象被首先解决。这一般被用做一个避免重复引用的快捷方法:
使用 with 的例子:
with (document.forms["mainForm"].elements) { input1.value = "junk"; input2.value = "junk"; }
但问题在于程序员并无方法来验证 input1 或 input2 实际上已经被看成 Form 元素数组的属性来解决。它首先觉得这些名来检测属性,若是找不到,它将会继续(向下)检测这个做用域。最后,它在全局对象中尝试把input1 和 input2 做为一个全局对象来对待,而这以一个错误做为结尾。
变通的方法是:建立一个引用来减小引用的对象,并使用它来解决这些引用。
使用一个引用:
var elements = document.forms["mainForm"].elements; elements.input1.value = "junk"; elements.input2.value = "junk";
若是你想在<a>标签中触发JavaScript 代码,选择 onclick 而非 javascript: pseudo-protocol;使用 onclick 来运行的 JavaScript 代码必须返回 ture 或者false(or an expression than evalues to true or false [这句要怎么翻译呢? 我是这样理解的:一个优先性高于true 或 false 的表达式])来返回标签自己:若是返回 true,则锚点的 href 将被看成一个通常的连接;若是返回 false,则 href 会被忽略。这就是为何”return false;” 常常被包含在 onclick 所处理代码的尾部。
正确句法:
<a onclick="doSomething(); return false;" href="javascript_required.html>go</a>
在这个实例中,”doSomething()” 函数(定义于页面的某个角落)将在被点击时调用。href 将永远不会被启用了JavaScript 的浏览器访问。在你能够提醒JavaScript 是必须的、而用户未启用之的浏览器中,文档 JavaScript_required.html 才会被加载。一般,当你确保用户将会开启 JavaScript 支持,为尽可能简化,连接将只包含 href=”#”。 而这个作法是不被鼓励的。一般有一个不错的作法是:能够提供没用启用 JavaScript 一个返回本地的页面。
有时,众多想要分状况来访问一个连接。例如,当一个用户要离开你的一个表单页面,而想先验证来确保没有东西被改变。在这个状况下,你的 onclick 将会访问一个返回询问连接是否应该被遵循的函数:
有条件的连接访问:
<a href="/" onClick="return validate();">Home</a> function validate() { return confirm("Are you sure you want to exit this page?"); }
在这个实例中,validate() 函数必须只返回 ture 或 false。ture 的时候用户将被容许问题 home 页面,或 false 的时候连接不被访问。这个例子提示确认(其行为),以访问 ture 或 false,这彻底由用户点击”确实”或者”取消”决定。
下面是一些”不该该”的例子。若是你在本身的页面中看到下面这样的代码,这是不正确的,须要被修改:
什么是不该该作的:
<a href="javascript:doSomething()">link</a> <a href="#" onClick="doSomething()">link</a> <a href="#" onClick="javascript:doSomething();">link</a> <a href="#" onClick="javascript:doSomething(); return false;">link</a>
在JavaScript中,”+”号运算符同时充当数学加号和链接符。这会在form表单的域值相加时出现问题,例如,由于JavaScript是一个弱类型语言,form 域的值将会被看成数组来处理,而你把它们”+”一块儿的时候,”+”将被当成链接符,而非数学加号。
有问题的例子:
<form name="myform" action="[url]"> <input type="text" name="val1" value="1"> <input type="text" name="val2" value="2"> </form> function total() { var theform = document.forms["myform"]; var total = theform.elements["val1"].value + theform.elements["val2"].value; alert(total); // 这个将会弹出 "12", 但你想要的是 3! }
解决这个问题,JavaScript 须要一个提示来让它把这些值当作数字来处理。你可使用”+”号来把数组转换成数字。给变量或者表达式前置一个”+”号将会强制其看成一个数字来处理,而这也将使得数学”+”得以成功应用。
修改好的代码:
function total() { var theform = document.forms["myform"]; var total = (+theform.elements["val1"].value) + (+theform.elements["val2"].value); alert(total); // This will alert 3 }
document.all 是由Microsoft 的 IE 所引进的,并非一个标准的 JavaScript DOM 特性。尽管大多数新的浏览器支持它以支持依赖于它的糟糕代码,(而)还有不少浏览器是不支持的。
并无理由其余方法都不适用,而一个老的IE浏览器(<5.0)须要支持,而在JavaScript中使用 document.all 做为一个折衷方法。 你并不须要使用 document.all 来检测其是否是IE浏览器,由于其余浏览器如今通常都支持。
只把 document.all 当作最后的选择:
if (document.getElementById) { var obj = document.getElementById("myId"); } else if (document.all) { var obj = document.all("myId"); }
一些使用 document.all 的原则:
在 JavaScript 的旧日子(1995)里,诸如 Netscape 1.0 的一些浏览器并不支持或认识 <script> 标签。因此,当 JavaScript 第一次被发布,须要有一个技术来让实些代码不被当作文本显示于旧版浏览器上。有一个”hack” 是在代码中使用 HTML 注释来隐藏这些代码。
使 HTML 注释并很差:
<script language="javascript"> <!-- // code here //--> </script>
在今天,没有任何一个经常使用的浏览器会忽略掉 <script> 标签。所以,再不必隐藏 JavaScript 源代码。事实上,它还能够由于下面的理由,被认为是无益的:
通常不多须要所有变量和函数。全局使用将可能致使 JavaScript 源文件文档冲突,和代码停止。所以,一个好的作法是在一个全局命名空间内采用函数性的封装。有多个方法能够完成这个任务,有此相对比较复杂。最简单的方法是建立一个全局对象,并把属性和方法指派给这个对象:
建立一个命名空间:
var MyLib = {}; // global Object cointainer MyLib.value = 1; MyLib.increment = function() { MyLib.value++; } MyLib.show = function() { alert(MyLib.value); } MyLib.value=6; MyLib.increment(); MyLib.show(); // alerts 7
命名空间也可使用 Closures(闭包?) 来建立,而且 Private Member Variables (私有变量?) 也能够假装于 JavaScript中。
当使用”Ajax”请求时,你要么选择异步模式,要么使用同步模式。当浏览器行为能够继续执行,异步模式将请求放在后台执行,同步模式则会等待请求完成后才继续。
应该避免同步模式作出的请求。这些请求将会对用户禁用浏览器,直至请求返回。一旦服务器忙,并须要一段时间来完成请求,用户的浏览器(或者 OS)将不能作任何其余的事,直至请求超时。
若是你以为本身的状况须要同步模式,最大的多是你须要时间来从新想一下你的设计。不多(若是有的话)实际上须要同步模式的 Ajax 请求。
当须要将数据结构存储成纯文本,或者经过 Ajax 发送/取回数据结构,尽量使用 JSON 代替 XML。JSON (JavaScript Object Notation) 是一个更简洁有效的数据存储格式,而且不依赖任何语言(and is a language-neutral)。
不在 <script> 中的使用LANGUAGE 属性。一个合适的方式是建立以下的 JavaScript 代码块:
<script type="text/javascript"> // code here </script>