如何编写高质量的Javascript代码(4)
来源:rockux 发布时间:2011-03-07 16:04:00
滥用了的var
JavaScript允许你在函数内部有多个var语句,但是却都表现的如同在函数的顶部声明一样。这个特性在你使用一个变量然后在后面又声明了这个变量时会导致一些奇怪的逻辑问题。对于JavaScript来说,只要变量在同一个作用域,那么就认为是声明了的,就算是在var语句之前使用也一样。看看这个例子:
myname = "global"; // global variable
function func() {
alert(myname); // "undefined"
var myname = "local";
alert(myname); // "local"
}
func();
在这个例子中,或许你期望第一次会弹出global,第二次弹出local。因为第一次的时候没有还没有使用var声明myname,这是应该是全局变量的myname,第二次声明了,然后alert之后应该是local的值。而事实上不是这样的,只要你在函数中出现了var myname,那么js就认为你在这个函数中声明了这个变量,但是在读取这个变量的值的时候,因为var语句还没有执行,所以是undefined,很奇怪的逻辑吧。上面的代码相当于:
myname = "global"; // global variable
function func() {
var myname; // same as -> var myname = undefined;
alert(myname); // "undefined"
myname = "local";
alert(myname); // "local"
}
func();
我们来解释一下这个现象,在代码的解析中,分两个步骤,第一步先处理变量函数的声明,这一步处理整个代码的上下文。第二步就是代码的运行时,创建函数表达式以及未定义的变量。实际上,我们只是假设了这个概念,这并不在ECMAScript的规范中,但是这个行为常常就是这样解释的。
for循环
在for循环中你会去迭代一些数组元素或者一些HTML元素。for循环常常如此:
for (var i = 0; i < myarray.length; i++) {
// do something with myarray[i]
}
这样写的问题在于,每一次迭代的时候都会计算数组的长度,尤其在这个参数不是一个数组而是一组HTML元素的时候会降低你的程序的性能。
HTML元素的集合在页面上,这样每次都会去再页面上查找相应的元素,这是非常耗时的。所以对于for循环,你需要预先保存数组的长度,这样写:
for (var i = 0, max = myarray.length; i < max; i++) {
// do something with myarray[i]
}
这样缓存了参数的长度,在每次迭代的时候就不用再去查找计算了。
在查找HTML元素集合的时候,缓存参数长度可以带来可观的性能提升,Safari下面提高两倍的速度,在IE7下面提高190倍的速度。
需要注意的是,当你需要操作修改DOM元素的数量的时候,你肯定希望这个值是随时更新的而不是一个常量。
使用下面的单一var模式,你也可以把var提到循环之外:
function looper() {
var i = 0,
max,
myarray = [];
// ...
for (i = 0, max = myarray.length; i < max; i++) {
// do something with myarray[i]
}
}
这个模式可以增强整个代码的连续性,但是不好的一点是当你重构代码的时候复制粘贴就没那么容易了。例如:如果你想在其他函数中也使用这个循环,那你需要确定在新的函数中处理好了i和max(或许还需要删掉这个)。
这个函数还有两个点可以优化的:
可以少一个变量(不需要max)
递减到0,一个数字与0比较比这个数字与另外一个数字比较更快
所以就可以写为:
var i, myarray = [];
for (i = myarray.length; i--;) {
// do something with myarray[i]
}
针对第二点:
var myarray = [],
i = myarray.length;
while (i--) {
// do something with myarray[i]
}
这是两个比较微小的点的优化。另外,JSLint可能对于i–会有意见。
猜你喜欢
- 本文描述通过统计分析出医院信息系统需分区的表,对需分区的表选择分区键,即找出包括在你的分区键中的列(表的属性),对大型数据的管理比较有意义,
- 对于windows平台来说安装完MySQL后,系统就已经默认生成了许可表和账户,你不需要像在Unix平台上那样执行 mysql_instal
- select for update 这个是行级锁 当 commit或者rollback时,锁释放 记得打开事务,比如jdbc里面 setAu
- 代码如下:---这是一个人事系统中的示例,要求记录一下员工的缺勤情况 ---1.要在表中记录一下缺勤计分,是对经常缺勤者的一种处
- 实这本是说明一个问题 : 每个人在提高自己能力这件事情上, 需要持续不断地努力。以最典型的例子来看,只有通过学习,程序员才能保证不断进步。
- 国外纷纷传言IE8将是Internet Explorer的最后一个版本,这个猜测来源于Microsoft的CEO Steve
- 这个目前还是有个别无法显示,翻了下msdn貌似没看到更好的解决方案,暂时放弃继续研究,有晓得完全解决的朋友不妨回复说一声。 先附bat创建畸
- 本游戏程序实现的功能为本地二人对弈中国象棋,实现语言为javascript+VML,在windows 2000 pro+IE 6sp1的环境
- 简单的仿图片验证码,适合新手简单的仿图片验证码演示,很容易被破解,实用性不大,但拿出来给新手学习一下还是不错的:JScript.Asp代码示
- 首先,啰嗦几句废话如下: (1)触发器(trigger)是个特殊的存储过程,它的执行并不需要我们去显式调用,而是由一些事件触发,这有点类似C
- 用下面代码可实现:<%Dim writeDim fileSysObj, tf, readrea
- 老外真是聪明,这个方法也想得到,有兴趣的不妨试试,但是如果对方的服务器安全搞的很好的话,这个代码也许就不能用了,但不管怎么样,学习一下也是好
- 在我的前一篇教程《九宫格基本布局》中,我介绍了用相对定位加绝对定位的方法来制作九宫格的基本布局。这是一种比较符合人们惯性思维的方法,好像制作
- 原理:自定义javascript中的oncontextmenu事件,然后使用div层模拟菜单。知道了这个原理结合美工相信你可以做出很漂亮的自
- 如何获知用户的IP?<% Dim ValidLog ' 日志变量 Valid
- 有时候需要在网页中某个div载入之后,动态引入一段javascript,IE下的解决方案: newjs. onreadystatechang
- 一个动态数组 a,如果你已经使用redim 语句给它设定了大小,那么在此之后使用 ubound(a) 就可以得到它的上边界。如果你没有使用
- IE 开发团队更改了 IE8 的 User-agent ,更改的部分信息如下:IE8 on Windows Vista (Compatibi
- 在推广Web标准的今天,那些崇尚Web标准的人经常说XHTML比HTML更加严格,当然从某种意义上说是的,比如它要求所有的标签关闭并且所有的
- 有时候,我们需要替换指定标签外的内容,而保留标签里面的内容不替换。比如当我们要在浏览器中显示出编辑器显示的原始格式时、需要将普通换行符“\n