专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »Javascript教程 » javascript变量:在JavaScript中 为什么要尽可能使用局部变量? »正文

javascript变量:在JavaScript中 为什么要尽可能使用局部变量?

来源: 发布时间:星期六, 2009年2月14日 浏览:0次 评论:0
="t18">在JavaScript中我们应该尽可能用局部变量来代替全局变量这句话所有人都知道可是这句话是谁先说?为什么要这么做?有什么根据么?不这么做对性能到底能带来多大损失?本文就来探讨这些问题答案从根本上了解变量读写性能都和哪些原因有关

【原文】JavaScript variable performance
【作者】Nicholas C. Zakas
【译文】在JavaScript中为什么要尽可能使用局部变量?
【译者】明达

以下是对原文翻译:

在如何提高JavaScript性能这个问题上大家最常听到建议应该就是尽量使用局部变量(local variables)来代替全局变量(global variables)在我从事Web开发工作 9年时间里这条建议始终萦绕在我耳边并且从来没有质疑过而这条建议基础则来自于 JavaScript处理作用域(scoping)和标识符解析(identier resolution)思路方法

首先我们要明确在JavaScript中具体表现为对象创建过程其实也就是创建个对象过程每个对象都有个叫做 [[Scope]]内部属性这个内部属性包含创建作用域信息实际上[[Scope]]属性对应个对象(Variable Objects)列表列表中对象是可以从内部访问比如说我们建立个全局A那么A[[Scope]]内部属性中只包含个全局对象(Global Object)而如果我们在A中创建个新B那么B[[Scope]]属性中就包含两个对象AActivation Object对象在前面全局对象(Global Object)排在后面

被执行时候会自动创建个可以执行对象(Execution Object)并同时绑定个作用域链(Scope Chain)作用域链会通过下面两个步骤来建立用于进行标识符解析

1. 首先将对象[[Scope]]内部属性中对象按顺序复制到作用域链中
2. 其次执行时会创建个新Activation Object对象这个对象中包含了this、参数(arguments)、局部变量(包括命名参数)定义这个Activation Object对象会被置于作用域链最前面

在执行JavaScript代码过程中当遇到个标识符就会根据标识符名称在执行上下文(Execution Context)作用域链中进行搜索从作用域链个对象(该Activation Object对象)开始如果没有找到就搜索作用域链中个对象如此往复直到找到了标识符定义如果在搜索完作用域中最后个对象也就是全局对象(Global Object)以后也没有找到则会抛出提示用户该变量未定义(und)这是在ECMA-262标准中描述执行模型和标识符解析(Identier Resolution)过程事实证明大部分JavaScript引擎确实也是这样实现需要注意ECMA-262并没有强制要求采用这种结构只是对这部分功能加以描述而已

了解标识符解析(Identier Resolution)过程以后我们就能明白为什么局部变量解析速度要比其他作用域变量快主要是由于搜索过程被大幅缩短了但是具体会快多少呢?为了回答这个问题我模拟了系列测试来测试区别作用域深度中变量性能

个测试是向个变量中写入个最简单值(这里使用字面量数值1)结果如下图显示很有趣:



从结果中不难看出当标识符解析过程需要进行深度搜索时会伴随性能损失而且性能损失程度会随着标识符深度增加而递增意料的中Internet Explorer表现是最差(但公平IE 8还是有些改善)值得注意这里有些例外情况Google Chrome和最新WebKit午夜版在访问变量时间保持得很稳定不会随着作用域深度递增而增长当然这应该归功于它们所使用代 JavaScript引擎V8和SquirrelFish这些引擎在执行代码时进行了优化而且很明显这些优化使访问变量速度比以往更快 Opera表现也很不错比IE、Firefox和当前版本Safari要快但比基于V8和Squirrelfish浏览器要慢 Firefox 3.1 Beta 2表现有点出人意料对于局部变量执行效率非常高但随着作用域层数增加效率便大打折扣需要注意我这里使用都是默认设置也就是说 Firefox是没有开启Trace功能

上面结果是通过对变量执行写操作而得出其实我很好奇读取变量时情况会不会有什么区别于是接着做了下面测试结果发现速度要比写速度快但是性能变化趋势是



和上个测试Internet Explorer和Firefox还是最慢Opera表现了非常抢眼性能而同样Chrome和最新版本Webkit午夜版显示了和作用域深度无关性能趋势同样需要注意Firefox 3.1 Beta 2变量访问时间还是会伴随着深度出现个奇怪跳跃

在测试过程中我发现个有趣现象就是Chrome在访问全局变量时候会有额外性能损失访问全局变量时间和作用域层数没有关系但是会比访问同样层数局部变量时间多出50%

这两个测试可以给我们带来什么启示呢?首先是验证了那个古老观点就是要尽可能使用局部变量在所有浏览器下访问局部变量都比访问跨作用域变量要快当然也包括全局变量下面这几点应该是通过这个测试得出经验吧:

* 仔细检查中所有使用变量如果有个变量不是当前作用域定义而且使用了不止那么我们就应该把这个变量保存在局部变量中而使用这个局部变量来进行读写操作这样可以帮助我们将作用域外变量搜索深度减少到1.这对全局变量尤为重要全局变量总是被放到作用域链最后位置来搜索
* 避免使用with语句它会修改执行上下文(Execution Context)作用域链在最前面添加个对象(Variable Object)这就意味着在执行with过程中实际上局部变量都被移到作用域链上第 2个位置这会带来性能上损失
* 如果你确定段代码肯定会抛出异常那么就要避免使用try-catchcatch分支在作用域链上处理思路方法和with是但try分支代码是没有性能损失所以还是建议用try-catch来捕获那些不可预知

如果你想围绕这个话题展开更多讨论我在上个月Mountain View JavaScript Meetup中曾经发表了个小演讲可以在SlideShare上下载幻灯片或者观看聚会完整视频演讲大概从11分钟左右时开始

译者笔记

大家如果在阅读本文过程中有什么疑惑建议延伸阅读以下两篇文章:
* Richie写JavaScript对象模型-执行模型
* ECMA-262第 3版主要看看第十章就是执行上下文(Execution Context)那张本文提到名词在那里都有详细解释

在最后时候Nicholas提到个Mountain View JavaScript MeetupMeetup那个网站WebSite其实就是个各种现实世界活动组织网站WebSite需要翻墙才能访问住在Calornia真幸福有那么多好活动可以参加呵呵

0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: