- 浏览: 176417 次
- 性别:
- 来自: 福建
最新评论
-
卡殿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 642LABjs 的核心是 LAB(Loadin ... -
正则表达式
2011-03-26 09:00 787正则表达式可以: •测试字符串的某个模式。例如,可以对一个输入 ... -
offsetParent,parentNode,parentElement区别
2011-03-22 15:09 1287offsetParent 指与位置有关的上级元素 pare ... -
js中的preventDefault和stopPropagation
2011-01-07 13:57 967首先讲解一下js中preventDefault和stopP ... -
javascrip编码(escape(), encodeURL(), encodeURIComponent())
2010-10-27 10:04 1002escape() 方法: 采用ISO-Latin字符集对指定 ... -
splice() 方法
2010-03-15 10:56 935splice() 方法用于插入、删除或替换数组的元素。 语法 ... -
ajax的原理和运行机制
2010-03-12 17:36 850关于ajax,是最近炒得非常火的一种技术,并且时下它也是非常流 ... -
HTML文档中小meta的大作用
2010-01-25 10:37 682meta 是用来在HTML文档中 ... -
JavaScript的陷阱
2010-01-22 13:38 727区分大小写 变量名和 ... -
连续字符自动换行的解决方案
2010-01-21 11:58 837http://dancewithnet.com/2008/12 ... -
JS判断脚本是否加载完成
2010-01-21 11:29 16631.function include_js(file) { 2 ... -
JavaScript程序编码规范
2010-01-20 15:27 789JavaScript文件 JavaScript程 ... -
js的nextSibling
2010-01-13 11:28 2465nextSilbling 属性的作用是:直接返回一个节点之后的 ... -
Javascript去掉字符串前后空格
2010-01-07 10:20 1364给string类型添加方法 String.prototype ... -
javascript中的location.reload() 和 location.replace()的区别和应用
2010-01-06 17:42 2419首先介绍两个方法的语法: reload 方法,该方法强迫浏览 ... -
javascript中substring()方法与substr()方法的区别
2010-01-06 16:45 21161 这两个方法都是String对象的方法 2 substr( ... -
关于IE和火狐下JS加载循序的问题
2009-12-16 10:42 1175FF是按照循序加载的,而IE却不是的,也就是说FF是同步加载, ... -
当嵌套iframe时,提供了一个统一的访问超时退出的UI界面
2009-12-16 09:04 3880Js代码:(来自Javaeye中的一段代码) functio ... -
异步加载组织结构树以及操作
2009-11-25 11:53 3244//============================= ... -
js中 break和 continue区别
2009-11-25 11:46 3896例子: <html> <body&g ...
相关推荐
全局变量、局部变量、静态全局变量、静态局部变量的区别
通过代码的运行,并理解代码,明白C中的局部变量与本地变量的区别
静态全局变量,静态局部变量,全局变量,局部变量静态全局变量,静态局部变量,全局变量,局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。 访问范围 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被...
C语言中局部变量、全局变量.pdf
1、局部变量能否和全局变量...来引用某个在头文件中声明的全局变理,假定你将那个编写错了,那么在编译期间会报错, 如果你用extern 方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连 接期间报错。
CC++中的静态全局变量,静态局部变量,全局变量,局部变量的区别
局部变量和全局变量总汇,希望对大家有帮助!
变量可以分为全局变量、静态全局变量、静态局部变量和局部变量 按存储区域分:全局变量、静态全局变量和静态局部变量都存放在内存的全局数据区,局部变量存放在内存的栈区 按作用域分:全局变量在整个工程文件内都...
c语言中详细解说局部变量和全局变量的关系和作用,让你明白!
比较局部变量、全局变量、堆、堆栈、静态和全局的区别和联系。
主要介绍了Vue全局变量局部变量,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
SQL中局部变量全局变量详解.doc
本文实例讲述了Python3.5局部变量与全局变量作用域。分享给大家供大家参考,具体如下: 1、局部变量与全局变量定义: 在子程序(函数)中定义的变量称为:局部变量;在程序顶级(一开始)定义的变量称为:全局变量。...
这个工程里面的描述很简单。就是陈列了一个全局变量和一个局部变量。适合人群:刚开始C语言单片机编程的开发人员。对函数之间数据交互不太清楚的人。
局部变量和全局变量1
在C语言编程中,全局变量和局部变量命名冲突的问题。 编程学习者的迷惑的地方!
详细的分析了全局变量,局部变量,static变量的区别 以及使用时用该注意的东西,很不错的。有兴趣的可以看看
block,局部变量,全部变量,static的静态变量关系
在JavaScript中,我们应该尽可能的用局部变量来代替全局变量,这句话所有人都知道,可是这句话是谁先说的?