最佳JS代码编写的14条技巧


Posted in Javascript onJanuary 09, 2011

写任何编程代码,不同的开发者都会有不同的见解。但参考一下总是好的,下面是来自Javascript Toolbox发布的14条最佳JS代码编写技巧。

1. 总是使用 var

在javascript中,变量不是全局范围的就是函数范围的,使用var关键词将是保持变量简洁明了的关键。当声明一个或者是全局或者是函数级(function-level)的变量,需总是前置var关键词,下面的例子将强调不这样做潜在的问题。

不使用 Var 造成的问题

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 定义一个函数范围的变量。下面这两个方法在功能上是相同的:

正确的函数

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

 正确的函数

  

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

2. 特性检测而非浏览器检测

一些代码是写来发现浏览器版本并基于用户正使用的客户端的对其执行不同行为。这个,总的来说,是一个非常糟的实践。更好的方法是使用特性检测,在使用一个老浏览器可能不支持的高级的特性之前,首先检测(浏览器的)是否有这个功能或特性,然后使用它。这单独检测浏览器版本来得更好,即使你知道它的性 能。你可以在这里找到一个深入讨论这个问题的文章。

例子:

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

3. 使用方括号记法

当访问由执行时决定或者包括要不能用.号访问的对象属性,使用方括号记法。如果你不是一个经验丰富的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 则是由页面所定义的。这页是句法让人非常容易理解(代码的内容),是一个推荐遵循的习惯用法,但不是严格原则。

4. 避免 eval

在Javascript中,eval()功能是一个在执行期中执行任意代码的方法。在几乎所有的情况下,eval 都不应该被使用。如果它出现在你的页面中,则表明你所做的有更好的方法。举一个例子,eval 通常被不知道要使用方括号记法的程序员所使用。

原则上,Eval is evil(Eval是魔鬼)。别使用它,除非你是一个经验丰富的开发者并且知道你的情况是个例外。

5. 正确地引用表单和表单元素

所有的 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");

}

}

通过对表单元素的引用来访问表单的属性,你可以写一个不包含硬代码的函数来引用这个页面中任何一个有特定名的表单。这是一个非常好的做法,因为函数变得可重用。

6 避免 with

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";

7. 在锚点中使用 onclick 替代 javascript: Pseudo-Protocol

如果你想在 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 href="javascript_required.html"go/a

在这个实例中,doSomething() 函数(定义于页面的某个角落)将在被点击时调用。href 将永远不会被启用了Javascript 的浏览器访问。在你可以提醒Javascript 是必须的、而用户未启用之的浏览器中,文档 javascript_required.html 才会被加载。通常,当你确保用户将会开启 Javascript 支持,为尽量简化,链接将只包含 href=#。 而这个做法是不被鼓励的。通常有一个不错的做法是:可以提供没用启用 javascript 一个返回本地的页面。

有时,众多想要分情况来访问一个链接。例如,当一个用户要离开你的一个表单页面,而想先验证来确保没有东西被改变。在这个情况下,你的 onclick 将会访问一个返回询问链接是否应该被遵循的函数:

有条件的链接访问:

a href="/"Home/a
function validate() {

return prompt("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="#"link/a

a href="#"link/a

a href="#"link/a

8. 使用一元 + 号运算符使类型转向Number

在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
}

9. 避免 document.all

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 的原则:

•同尝试其他方法
•当其作为最后的选择
•当需要支持 5.0 版本以下的 IE 浏览器
•总是使用 if (document.all) { } 来查看是否支持.

10. 不要在脚本代码块中使用HTML注释

在 Javascript 的旧日子(1995)里,诸如 Netscape 1.0 的一些浏览器并不支持或认识 script 标签。所以,当 Javascript 第一次被发布,需要有一个技术来让实些代码不被当做文本显示于旧版浏览器上。有一个hack 是在代码中使用 HTML 注释来隐藏这些代码。

使 HTML 注释并不好:

script language="javascript"
!--
// code here
//--
/script

在今天,没有任何一个常用的浏览器会忽略掉 script 标签。因此,再没必要隐藏 Javascript 源代码。事实上,它还可以因为下面的理由,被认为是无益的:

•在 XHTML 文档中,源代码将向所有浏览器隐藏并被渲染成无用的(内容);
•? 在 HTML 注释并不允许 ,这个会让任何递减操作将失效。
  11. 避免乱用全局命名空间

一般很少需要全部变量和函数。全局使用将可能导致 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中。

12. 避免同步的 ajax 调用

当使用Ajax请求时,你要么选择异步模式,要么使用同步模式。当浏览器行为可以继续执行,异步模式将请求放在后台执行,同步模式则会等待请求完成后才继续。

应该避免同步模式做出的请求。这些请求将会对用户禁用浏览器,直至请求返回。一旦服务器忙,并需要一段时间来完成请求,用户的浏览器(或者 OS)将不能做任何其他的事,直至请求超时。

如果你觉得自己的情况需要同步模式,最大的可能是你需要时间来重新想一下你的设计。很少(如果有的话)实际上需要同步模式的 Ajax 请求。

13. 使用 JSON

当需要将数据结构存储成纯文本,或者通过 Ajax 发送/取回数据结构,尽可能使用 JSON 代替 XML。JSON (JavaScript Object Notation) 是一个更简洁有效的数据存储格式,并且不依赖任何语言(and is a language-neutral)。

14. 使用正确的 script 标签

不造成在 script 中的使用LANGUAGE 属性。一个合适的方式是创建如下的 Javascript 代码块:

<script type="text/javascript">
// code here
</script>
Javascript 相关文章推荐
学习从实践开始之jQuery插件开发 菜单插件开发
May 03 Javascript
jquery和javascript的区别(常用方法比较)
Jul 04 Javascript
从数组中随机取x条不重复数据的JS代码
Dec 24 Javascript
js toFixed()方法的重写实现精度的统一
Mar 06 Javascript
js实现的点击数量加一可操作数据库
May 09 Javascript
jquery结婚电子请柬特效源码分享
Aug 21 Javascript
基于jQuery实现鼠标点击导航菜单水波动画效果附源码下载
Jan 06 Javascript
javascript解决小数的加减乘除精度丢失的方案
May 31 Javascript
Node.js连接MongoDB数据库产生的问题
Feb 08 Javascript
微信小程序图片自适应支持多图实例详解
Jun 21 Javascript
Vue.js的模板语法详解
Feb 16 Javascript
vue实现滚动鼠标滚轮切换页面
Dec 13 Vue.js
JavaScript定义类或函数的几种方式小结
Jan 09 #Javascript
javascript中用星号表示预录入内容的实现代码
Jan 08 #Javascript
js中访问html中iframe的文档对象的代码[IE6,IE7,IE8,FF]
Jan 08 #Javascript
js中top、clientTop、scrollTop、offsetTop的区别 文字详细说明版
Jan 08 #Javascript
Jquery Ajax请求代码(2)
Jan 07 #Javascript
JQuery 绑定select标签的onchange事件,弹出选择的值,并实现跳转、传参
Jan 06 #Javascript
神奇的7个jQuery 3D插件整理
Jan 06 #Javascript
You might like
php5.3 废弃函数小结
2010/05/16 PHP
FireFox浏览器使用Javascript上传大文件
2013/10/30 PHP
PHP随机数函数rand()与mt_rand()的讲解
2019/03/25 PHP
效率高的Javscript字符串替换函数的benchmark
2008/08/02 Javascript
JavaScript constructor和instanceof,JSOO中的一对欢喜冤家
2009/05/25 Javascript
jQuery 行背景颜色的交替显示(隔行变色)实现代码
2009/12/13 Javascript
js控制浏览器全屏示例代码
2014/02/20 Javascript
javascript实现字符串反转的方法
2015/02/05 Javascript
jquery实现鼠标滑过显示提示框的方法
2015/02/05 Javascript
js带点自动图片轮播幻灯片特效代码分享
2015/09/07 Javascript
分享几种比较简单实用的JavaScript tabel切换
2015/12/31 Javascript
nodejs简单实现操作arduino
2016/09/25 NodeJs
jquery pagination插件动态分页实例(Bootstrap分页)
2016/12/23 Javascript
AngularJS 异步解决实现方法
2017/06/12 Javascript
JavaScript实现设置默认日期范围为最近40天的方法分析
2017/07/12 Javascript
js定时器实现倒计时效果
2017/11/05 Javascript
nodejs使用redis作为缓存介质实现的封装缓存类示例
2018/02/07 NodeJs
Vue+Element UI 树形控件整合下拉功能菜单(tree + dropdown +input)
2020/08/28 Javascript
微信小程序实现文件预览
2020/10/22 Javascript
[55:16]Mski vs VGJ.S Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
在Python的Flask框架中实现单元测试的教程
2015/04/20 Python
pandas值替换方法
2018/07/10 Python
浅谈Pandas:Series和DataFrame间的算术元素
2018/12/22 Python
浅谈Python批处理文件夹中的txt文件
2019/03/11 Python
python实现文本进度条 程序进度条 加载进度条 单行刷新功能
2019/07/03 Python
python使用 zip 同时迭代多个序列示例
2019/07/06 Python
Python + Flask 实现简单的验证码系统
2019/10/01 Python
Django Admin 上传文件到七牛云的示例代码
2020/06/20 Python
英国领先的男士美容护发用品公司:Mankind
2016/08/31 全球购物
亚马逊中国官方网站:amazon.cn
2017/05/25 全球购物
英国女鞋购物网站:Moda in Pelle
2019/02/18 全球购物
广州一家公司的.NET面试题
2016/06/11 面试题
地震慰问信
2015/02/14 职场文书
护士医德考评自我评价
2015/03/03 职场文书
2015年乡镇环保工作总结
2015/04/22 职场文书
Pytorch中使用ImageFolder读取数据集时忽略特定文件
2022/03/23 Python