- 浏览: 182030 次
- 性别:
- 来自: 福建
-
最新评论
-
卡殿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 685LABjs 的核心是 LAB(Loadin ... -
正则表达式
2011-03-26 09:00 881正则表达式可以: •测试字符串的某个模式。例如,可以对一个输入 ... -
offsetParent,parentNode,parentElement区别
2011-03-22 15:09 1353offsetParent 指与位置有关的上级元素 pare ... -
js中的preventDefault和stopPropagation
2011-01-07 13:57 1044首先讲解一下js中preventDefault和stopP ... -
javascrip编码(escape(), encodeURL(), encodeURIComponent())
2010-10-27 10:04 1051escape() 方法: 采用ISO-Latin字符集对指定 ... -
splice() 方法
2010-03-15 10:56 1011splice() 方法用于插入、删除或替换数组的元素。 语法 ... -
ajax的原理和运行机制
2010-03-12 17:36 894关于ajax,是最近炒得非常火的一种技术,并且时下它也是非常流 ... -
HTML文档中小meta的大作用
2010-01-25 10:37 747meta 是用来在HTML文档中 ... -
JavaScript的陷阱
2010-01-22 13:38 806区分大小写 变量名和 ... -
连续字符自动换行的解决方案
2010-01-21 11:58 908http://dancewithnet.com/2008/12 ... -
JS判断脚本是否加载完成
2010-01-21 11:29 17121.function include_js(file) { 2 ... -
JavaScript程序编码规范
2010-01-20 15:27 863JavaScript文件 JavaScript程 ... -
js的nextSibling
2010-01-13 11:28 2559nextSilbling 属性的作用是:直接返回一个节点之后的 ... -
Javascript去掉字符串前后空格
2010-01-07 10:20 1414给string类型添加方法 String.prototype ... -
javascript中的location.reload() 和 location.replace()的区别和应用
2010-01-06 17:42 2461首先介绍两个方法的语法: reload 方法,该方法强迫浏览 ... -
javascript中substring()方法与substr()方法的区别
2010-01-06 16:45 21501 这两个方法都是String对象的方法 2 substr( ... -
关于IE和火狐下JS加载循序的问题
2009-12-16 10:42 1235FF是按照循序加载的,而IE却不是的,也就是说FF是同步加载, ... -
当嵌套iframe时,提供了一个统一的访问超时退出的UI界面
2009-12-16 09:04 3951Js代码:(来自Javaeye中的一段代码) functio ... -
异步加载组织结构树以及操作
2009-11-25 11:53 3339//============================= ... -
js中 break和 continue区别
2009-11-25 11:46 3947例子: <html> <body&g ...
相关推荐
通常,推荐使用局部变量和实例/类变量来代替全局变量。 ```ruby $global_var = "Greetings, Global!" puts $global_var # 输出 "Greetings, Global!" ``` 三、实例变量 实例变量以`@`开头,它们是对象的私有属性...
为了减少错误和提高代码的可维护性,应该尽量减少全局变量的使用,并考虑使用局部变量或函数参数来代替。 关于全局变量的生命周期,它始于程序启动的时刻,持续到程序终止。这意味着,即使某些函数已经执行完毕,...
在深入探讨全局变量的作用...在设计和维护大型程序时,应当有意识地限制全局变量的使用,并尽可能采用局部变量和参数传递来代替全局变量,这样可以更好地控制变量的生命周期和作用域,从而提升整个程序的质量和稳定性。
- 尽量减少全局变量的使用,使用局部变量或参数传递来代替。 - 如果必须使用全局变量,应使用const关键字限制其值不被修改。 - 使用头文件来声明全局变量,以保证所有使用全局变量的函数能够统一访问。 编程实践中...
在使用变量时,应该遵循一些最佳实践,比如变量名应该具有描述性,变量的声明应该靠近其首次使用的点,使用局部变量代替全局变量以减少潜在的错误等。 10. 代码提交的提示 在项目开发中,应该坚持定期提交代码到...
因此,设计时应当考虑是否真的需要全局变量,或者是否可以用其他方式如函数参数、返回值或者利用对象的成员变量来代替。 在学习和实践编程时,理解并能够正确使用全局变量的作用域和生命周期对于编写结构清晰、易于...
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. 减少函数调用 频繁的函数调用会增加程序的开销,包括参数传递、保存现场等操作。因此,对于简单的操作,应尽量减少函数调用次数,可以...
#### 五、用局部变量代替全局变量 定义局部变量比全局变量更为高效。这是因为编译器将局部变量存储在内部存储区中,而全局变量则存储在外部存储区,后者访问速度较慢。此外,过度依赖全局变量可能会导致程序维护...
- **使用本地数据保护全局数据**:如果需要使用全局数据,可重入函数应该使用局部变量来复制这些数据,或者通过信号量等方式来保护全局数据,确保数据的一致性和完整性。 - **避免调用不可重入函数**:可重入函数不...
24. 定义但未使用的局部变量:即使未在函数中使用,定义局部变量也会降低性能,因为 PHP 会检查是否有同名的全局变量。 25. 方法调用的影响:方法调用的性能与类中方法的数量关系不大,但与具体的调用方式有关。 ...