- 浏览: 180375 次
- 性别:
- 来自: 福建
最新评论
-
卡殿Love:
你好! 谢谢你的文章让我知道其中的原因,目前正在做手机端上的项 ...
web手机开发(iPhone和Andriod)关于position:fixed 属性的讨论
在如何提高JavaScript性能这个问题上,大家最常听到的建议应该就是尽量使用局部变量(local variables)来代替全局变量(global variables)。在我从事Web开发工作的九年时间里,这条建议始终萦绕在我的耳边,并且从来没有质疑过,而这条建议的基础,则来自于 JavaScript处理作用域(scoping)和标识符解析(identifier resolution)的方法。
首先我们要明确,函数在JavaScript中具体表现为对象,创建一个函数的过程,其实也就是创建一个对象的过程。每个函数对象都有一个叫做 [[Scope]]的内部属性,这个内部属性包含创建函数时的作用域信息。实际上,[[Scope]]属性对应的是一个对象(Variable Objects)列表,列表中的对象是可以从函数内部访问的。比如说我们建立一个全局函数A,那么A的[[Scope]]内部属性中只包含一个全局对象(Global Object),而如果我们在A中创建一个新的函数B,那么B的[[Scope]]属性中就包含两个对象,函数A的Activation Object对象在前面,全局对象(Global Object)排在后面。
当一个函数被执行的时候,会自动创建一个可以执行的对象(Execution Object),并同时绑定一个作用域链(Scope Chain)。作用域链会通过下面两个步骤来建立,用于进行标识符解析。
1. 首先将函数对象[[Scope]]内部属性中的对象,按顺序复制到作用域链中。
2. 其次,在函数执行时,会创建一个新的Activation Object对象,这个对象中包含了this、参数(arguments)、局部变量(包括命名的参数)的定义,这个Activation Object对象会被置于作用域链的最前面。
在执行JavaScript代码的过程中,当遇到一个标识符,就会根据标识符的名称,在执行上下文(Execution Context)的作用域链中进行搜索。从作用域链的第一个对象(该函数的Activation Object对象)开始,如果没有找到,就搜索作用域链中的下一个对象,如此往复,直到找到了标识符的定义。如果在搜索完作用域中的最后一个对象,也就是全局对象(Global Object)以后也没有找到,则会抛出一个错误,提示用户该变量未定义(undefined)。这是在ECMA-262标准中描述的函数执行模型和标识符解析(Identifier Resolution)的过程,事实证明,大部分的JavaScript引擎确实也是这样实现的。需要注意的是,ECMA-262并没有强制要求采用这种结构,只是对这部分功能加以描述而已。
所以: * 仔细检查函数中所有使用的变量,如果有一个变量不是当前作用域定义的,而且使用了不止一次,那么我们就应该把这个变量保存在局部变量中,而使用这个局部变量来进行读写操作。这样可以帮助我们将作用域外的变量的搜索深度减少到1.这对全局变量尤为重要,因为全局变量总是被放到作用域链的最后位置来搜索。
* 避免使用with语句。因为它会修改执行上下文(Execution Context)的作用域链,在最前面添加一个对象(Variable Object)。这就意味着在执行with的过程中,实际上的局部变量都被移到作用域链上的第二个位置,这会带来性能上的损失。
* 如果你确定一段代码肯定会抛出异常,那么就要避免使用try-catch,因为catch分支在作用域链上的处理方法和with是一样的。但try分支的代码是没有性能损失的,所以还是建议用try-catch来捕获那些不可预知的错误
首先我们要明确,函数在JavaScript中具体表现为对象,创建一个函数的过程,其实也就是创建一个对象的过程。每个函数对象都有一个叫做 [[Scope]]的内部属性,这个内部属性包含创建函数时的作用域信息。实际上,[[Scope]]属性对应的是一个对象(Variable Objects)列表,列表中的对象是可以从函数内部访问的。比如说我们建立一个全局函数A,那么A的[[Scope]]内部属性中只包含一个全局对象(Global Object),而如果我们在A中创建一个新的函数B,那么B的[[Scope]]属性中就包含两个对象,函数A的Activation Object对象在前面,全局对象(Global Object)排在后面。
当一个函数被执行的时候,会自动创建一个可以执行的对象(Execution Object),并同时绑定一个作用域链(Scope Chain)。作用域链会通过下面两个步骤来建立,用于进行标识符解析。
1. 首先将函数对象[[Scope]]内部属性中的对象,按顺序复制到作用域链中。
2. 其次,在函数执行时,会创建一个新的Activation Object对象,这个对象中包含了this、参数(arguments)、局部变量(包括命名的参数)的定义,这个Activation Object对象会被置于作用域链的最前面。
在执行JavaScript代码的过程中,当遇到一个标识符,就会根据标识符的名称,在执行上下文(Execution Context)的作用域链中进行搜索。从作用域链的第一个对象(该函数的Activation Object对象)开始,如果没有找到,就搜索作用域链中的下一个对象,如此往复,直到找到了标识符的定义。如果在搜索完作用域中的最后一个对象,也就是全局对象(Global Object)以后也没有找到,则会抛出一个错误,提示用户该变量未定义(undefined)。这是在ECMA-262标准中描述的函数执行模型和标识符解析(Identifier Resolution)的过程,事实证明,大部分的JavaScript引擎确实也是这样实现的。需要注意的是,ECMA-262并没有强制要求采用这种结构,只是对这部分功能加以描述而已。
所以: * 仔细检查函数中所有使用的变量,如果有一个变量不是当前作用域定义的,而且使用了不止一次,那么我们就应该把这个变量保存在局部变量中,而使用这个局部变量来进行读写操作。这样可以帮助我们将作用域外的变量的搜索深度减少到1.这对全局变量尤为重要,因为全局变量总是被放到作用域链的最后位置来搜索。
* 避免使用with语句。因为它会修改执行上下文(Execution Context)的作用域链,在最前面添加一个对象(Variable Object)。这就意味着在执行with的过程中,实际上的局部变量都被移到作用域链上的第二个位置,这会带来性能上的损失。
* 如果你确定一段代码肯定会抛出异常,那么就要避免使用try-catch,因为catch分支在作用域链上的处理方法和with是一样的。但try分支的代码是没有性能损失的,所以还是建议用try-catch来捕获那些不可预知的错误
发表评论
-
LABjs、RequireJS、SeaJS 哪个最好用?为什么?
2013-10-28 16:36 676LABjs 的核心是 LAB(Loadin ... -
正则表达式
2011-03-26 09:00 856正则表达式可以: •测试字符串的某个模式。例如,可以对一个输入 ... -
offsetParent,parentNode,parentElement区别
2011-03-22 15:09 1326offsetParent 指与位置有关的上级元素 pare ... -
js中的preventDefault和stopPropagation
2011-01-07 13:57 1025首先讲解一下js中preventDefault和stopP ... -
javascrip编码(escape(), encodeURL(), encodeURIComponent())
2010-10-27 10:04 1032escape() 方法: 采用ISO-Latin字符集对指定 ... -
splice() 方法
2010-03-15 10:56 975splice() 方法用于插入、删除或替换数组的元素。 语法 ... -
ajax的原理和运行机制
2010-03-12 17:36 886关于ajax,是最近炒得非常火的一种技术,并且时下它也是非常流 ... -
HTML文档中小meta的大作用
2010-01-25 10:37 722meta 是用来在HTML文档中 ... -
JavaScript的陷阱
2010-01-22 13:38 782区分大小写 变量名和 ... -
连续字符自动换行的解决方案
2010-01-21 11:58 882http://dancewithnet.com/2008/12 ... -
JS判断脚本是否加载完成
2010-01-21 11:29 17011.function include_js(file) { 2 ... -
JavaScript程序编码规范
2010-01-20 15:27 830JavaScript文件 JavaScript程 ... -
js的nextSibling
2010-01-13 11:28 2521nextSilbling 属性的作用是:直接返回一个节点之后的 ... -
Javascript去掉字符串前后空格
2010-01-07 10:20 1398给string类型添加方法 String.prototype ... -
javascript中的location.reload() 和 location.replace()的区别和应用
2010-01-06 17:42 2451首先介绍两个方法的语法: reload 方法,该方法强迫浏览 ... -
javascript中substring()方法与substr()方法的区别
2010-01-06 16:45 21411 这两个方法都是String对象的方法 2 substr( ... -
关于IE和火狐下JS加载循序的问题
2009-12-16 10:42 1217FF是按照循序加载的,而IE却不是的,也就是说FF是同步加载, ... -
当嵌套iframe时,提供了一个统一的访问超时退出的UI界面
2009-12-16 09:04 3930Js代码:(来自Javaeye中的一段代码) functio ... -
异步加载组织结构树以及操作
2009-11-25 11:53 3316//============================= ... -
js中 break和 continue区别
2009-11-25 11:46 3928例子: <html> <body&g ...
相关推荐
通常,推荐使用局部变量和实例/类变量来代替全局变量。 ```ruby $global_var = "Greetings, Global!" puts $global_var # 输出 "Greetings, Global!" ``` 三、实例变量 实例变量以`@`开头,它们是对象的私有属性...
4. 考虑到代码的可读性和可扩展性,应尽量减少全局变量的数量,使用局部变量和对象属性代替。 综上所述,这个资料包提供了一个实用的方法来管理和操作MetaTrader 5中的全局变量,通过使用CGV类可以提高代码质量,...
2. 尽量避免全局变量:全局变量可能导致意外的副作用,尽量使用局部变量和类成员代替。如果必须使用全局变量,确保它们有适当的封装和访问修饰符。 3. 使用const和readonly:对于不会改变的常量,使用`const`关键字...
例如,在函数内部使用局部变量counts代替全局变量count,可以显著减少对存储器的访问次数,避免每次都需要将变量从存储器中加载到寄存器,再写回存储器。 再次,针对参数传递的效率问题,文章指出,在C语言与汇编...
9. 递增一个局部变量要比递增一个全局变量慢 2 倍。 10. 递增一个对象属性要比递增一个局部变量慢 3 倍。 文件和路径 11. include 文件时尽量使用绝对路径,因为它避免了 PHP 去 include_path 里查找文件的速度,...
尽量使用局部变量 局部变量存储在栈中,访问速度快于堆中的对象。因此,对于那些生命周期较短、不需要长时间存在的变量,优先考虑使用局部变量。 #### 6. 慎重处理包装类型和基本类型的使用场景 基本类型和包装...
3. **局部变量的使用**:为了更好地利用CPU寄存器,应尽量使用局部变量而非全局变量。局部变量更容易被编译器优化。 4. **模块内变量声明为static**:对于只在特定模块内部使用的变量,应该声明为 `static` 类型。...
19. 全局变量与局部变量:递增全局变量比递增局部变量慢约2倍。 20. 对象属性操作:递增对象属性比递增局部变量慢3倍。 21. 未定义变量:递增未定义的局部变量比递增已定义的局部变量慢9到10倍。 22. 未使用的...
因此,我们需要尽量减少全局变量的声明,使用局部变量来代替全局变量。在上面的代码中,我们可以看到作者是如何使用局部变量来缓存全局变量的。 缓存 DOM 节点查找结果 在 JS 代码中,我们经常需要查找 DOM 节点,...
- 避免使用局部变量的地址,因为这可能导致访问速度变慢。 8. 结构体的安排: - 小型成员放在结构体前面,大型成员放在后面,以优化内存对齐。 - 避免过大的结构体,使用层次化的子结构体代替。 - 为 API ...
因此,在不影响程序功能的前提下,应尽量使用局部变量而非全局变量。 ### 4. 减少函数调用 频繁的函数调用会增加程序的开销,包括参数传递、保存现场等操作。因此,对于简单的操作,应尽量减少函数调用次数,可以...
#### 五、用局部变量代替全局变量 定义局部变量比全局变量更为高效。这是因为编译器将局部变量存储在内部存储区中,而全局变量则存储在外部存储区,后者访问速度较慢。此外,过度依赖全局变量可能会导致程序维护...
- **使用本地数据保护全局数据**:如果需要使用全局数据,可重入函数应该使用局部变量来复制这些数据,或者通过信号量等方式来保护全局数据,确保数据的一致性和完整性。 - **避免调用不可重入函数**:可重入函数不...
总结,JavaScript开发规范是提升代码质量的关键,包括但不限于文件编码、变量声明规则、使用局部变量代替全局变量、匿名函数的格式等。遵循这些规范,能确保代码更加整洁、易于理解,同时降低维护成本。
21. 全局变量与局部变量:递增全局变量比递增局部变量慢约2倍。 22. 对象属性与局部变量:递增对象属性比递增局部变量慢3倍。 23. 预定义变量:递增未定义的局部变量比递增预定义的局部变量慢9到10倍。 24. 未...
递增局部变量通常比递增全局变量更快,且接近于函数内部变量的操作速度。 #### 19. 全局变量与局部变量的递增 递增全局变量的速度大约是递增局部变量的两倍。 #### 20. 对象属性与局部变量的递增 递增对象属性...
19. **全局变量与局部变量**:递增全局变量比递增局部变量慢大约两倍。 20. **对象属性操作**:递增对象属性比递增局部变量慢三倍。 21. **未定义变量**:递增未定义的局部变量比递增已定义的局部变量慢9到10倍。 ...
24. 定义但未使用的局部变量:即使未在函数中使用,定义局部变量也会降低性能,因为 PHP 会检查是否有同名的全局变量。 25. 方法调用的影响:方法调用的性能与类中方法的数量关系不大,但与具体的调用方式有关。 ...