如何编写高质量的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–会有意见。


猜你喜欢
- 在前面的文章中,我分别介绍了基于列表元素柱状图和基于表格元素柱状图的实现方法,虽然方法比较简单,但是它却包含了基本的实现原理。在了解了前面两
- 一、图像直方图1.1 定义图像直方图是图像的基本属性之一,也是反映图像像素数据分布的统计学特征,其横坐标代表了图像像素点在[0,255]范围
- 一、简介Imageio是一个Python库,提供了一个简单的界面来读取和写入各种图像数据,包括动画图像,视频,体积数据和科学格式。它是跨平台
- 对于所有的需求,当你不知道怎么处理的时候,你就先用最简单的方法,或者说的明白一点,用最原始的方法,先实现业务需求再说。一、对提现队列数据表“
- 首先说明,伪造访问来路不是什么光明正大的事情,目的就是为了欺骗服务器。原本以为给 XMLHTTP 对象增加一个 Referer 的heade
- 一、项目视图分析通过上图,我们可以看到,一个完整的项目,基本包括三个部分:用户视图层、接口层、数据处理层,其中,用户视图层是用来接收用户的数
- 目录:分析和设计组件编码实现和算法用 Ant 构建组件测试 JavaScript 组件话说上期我们讨论了队列管理组件的设计,并且给它取了个响
- 业务场景由于项目需求,需要对相关类目进行多选,类目数据量又特别大,业务逻辑是使用懒加载方式加载各级类目数据,编辑时回显用户选择的类目。问题描
- 如下所示:import tensorflow as tftfe = tf.contrib.eagertf.enable_eager_exec
- I. 前言在上一篇文章深入理解PyTorch中LSTM的输入和输出(从input输入到Linear输出)中,我详细地解释了如何利用PyTor
- 一、renderer<meta name="renderer" content="webkit|ie-c
- 1、split()含义:split() 通过指定分隔符对字符串进行切片,如果参数 num 有指定值,则分隔 num+1 个子字符串
- 本文实例为大家分享了JavaScript实现鼠标经过显示下拉框的具体代码,供大家参考,具体内容如下代码:<!DOCTYPE html&
- 内容摘要:本文介绍了使用js来实现下拉伸缩导航菜单的功能,并带有渐显的效果,值得收藏。正好这几天公司不忙,学校又没有事情,所以想抽空架一个个
- 本文提供许多的滤波方法,这些方法放在filters.rank子模块内。这些方法需要用户自己设定滤波器的形状和大小,因此需要导入morphol
- 我就废话不多说了,大家还是直接看代码吧!file1 = 'C:\\Users\\Administrator\\Desktop\\te
- 多线程多线程是个提高程序运行效率的好办法,本来要顺序执行的程序现在可以并行执行,可想而知效率要提高很多。但是多线程也不是能提高所有程序的效率
- 要是XHTML与CSS能面向对象。。太阳应该从北边升起了。但是,凡事都应该带着OO的思想来看问题,也勉强可以凑数拉。其实,早在零几年就有人提
- 1. tqdm的介绍有时候在使用Python处理比较耗时操作的时候,为了便于观察处理进度,这时候就需要通过进度条将处理情况进行可视化展示,以
- 一、图像二值化1.效果2.源码import cv2import numpy as npimport matplotlib.pyplot as