数据访问之改变作用域链
来源:互联网 发布:mac鼠标右键功能 编辑:程序博客网 时间:2024/06/06 15:37
function initUI(){
with (document){ //avoid!
var bd = body,
links = getElementsByTagName_r("a"),
i = 0,
len = links.length;
while(i < len){
update(links[i++]);
}
getElementById("go-btn").onclick = function(){
start();
};
bd.className = "active";
}
}
此重写的initUI()版本使用了一个with 表达式,避免多次书写“document”。这看起来似乎更有效率,而实际上却产生了一个性能问题。当代码流执行到一个with 表达式时,运行期上下文的作用域链被临时改变了。一个新的可变对象将被创建,它包含指定对象的所有属性。此对象被插入到作用域链的前端,意味着现在函数的所有局部变量都被推入第二个作用域链对象中,所以访问代价更高了。
通过将document 对象传递给with 表达式,一个新的可变对象容纳了document 对象的所有属性,被插入到作用域链的前端。这使得访问document 的属性非常快,但是访问局部变量的速度却变慢了,例如bd 变量。正因为这个原因,最好不要使用with 表达式。正如前面提到的,只要简单地将document 存储在一个局部变量中,就可以获得性能上的提升。
在JavaScript 中不只是with 表达式人为地改变运行期上下文的作用域链,try-catch 表达式的catch 子句具有相同效果。当try 块发生错误时,程序流程自动转入catch 块,并将异常对象推入作用域链前端的一个可变对象中。在catch 块中,函数的所有局部变量现在被放在第二个作用域链对象中。例如:
try {
methodThatMightCauseAnError();
} catch (ex){
alert(ex.message); //scope chain is augmented here
}
请注意,只要catch 子句执行完毕,作用域链就会返回到原来的状态。如果使用得当,try-catch 表达式是非常有用的语句,所以不建议完全避免。如果你计划使用一个try-catch语句,请确保你了解可能发生的错误。一个try-catch 语句不应该作为JavaScript 错误的解决办法。如果你知道一个错误会经常发生,那说明应当修正代码本身的问题。你可以通过精缩代码的办法最小化catch 子句对性能的影响。一个很好的模式是将错误交给一个专用函数来处理。例子如下:
try {
methodThatMightCauseAnError();
} catch (ex){
handleError(ex); //delegate to handler method
}
handleError()函数是catch 子句中运行的唯一代码。此函数以适当方法自由地处理错误,并接收由错误产生的异常对象。由于只有一条语句,没有局部变量访问,作用域链临时改变就不会影响代码的性能。Dynamic Scopes 动态作用域无论是with 表达式还是try-catch 表达式的catch 子句,以及包含()的函数,都被认为是动态作用域。一个动态作用域只因代码运行而存在,因此无法通过静态分析(察看代码结构)来确定(是否存在动态作用域)。例如:
function execute(code) {
(code);
function subroutine(){
return window;
}
var w = subroutine();
//what value is w?
};
execute()函数看上去像一个动态作用域,因为它使用了()。w 变量的值与code 有关。大多数情况下,w将等价于全局的window 对象,但是请考虑如下情况:execute("var window = {};")这种情况下,()在execute()函数中创建了一个局部window 变量。所以w 将等价于这个局部window 变量而不是全局的那个。所以说,不运行这段代码是没有办法了解具体情况的,标识符window 的确切含义不能预先确定。
优化的JavaScript 引擎,例如Safari 的Nitro 引擎,企图通过分析代码来确定哪些变量应该在任意时刻被访问,来加快标识符识别过程。这些引擎企图避开传统作用域链查找,取代以标识符索引的方式进行快速查找。当涉及一个动态作用域后,此优化方法就不起作用了。引擎需要切回慢速的基于哈希表的标识符识别方法,更像传统的作用域链搜索。正因为这个原因,只在绝对必要时才推荐使用动态作用域。
- 数据访问之改变作用域链
- 访问变量-作用域链 访问属性-原型链
- JS - 关于改变Javascript的作用域链
- 哪种方式能改变作用域链
- SpringBoot之数据访问
- 数据访问之文件系统数据
- apply()、call()、bind()改变作用域
- JS基础--with改变作用域
- 微软改变数据访问策略 OLE DB再次转向ODBC
- javascript之作用域链
- 通用数据访问之我见
- 数据访问速度之差别
- Spring 数据访问之事务管理
- Spring 之数据访问 JdbcTemplate
- 微信小程序之数据访问
- SpringBoot之数据访问操作
- JavaScript高级之词法作用域和作用域链
- 进击JavaScript之词法作用域与作用域链
- 哈工大 《.NET程序设计》 实验1:开发Windows窗体应用程序
- poj 3308
- PHP 代码规范
- Oracle学习笔记--第一章
- NSDate计算天数。
- 数据访问之改变作用域链
- 在gentoo上安装 mips64el-st-linux-gnu-交叉编译工具链
- C/C++ programming in Emacs
- 利用JS弹出层实现简单的动态提示“正在加载中,请稍等...”
- jquery如何获得页面元素的坐标值
- 第一个程序IDL
- Git 中文教程
- 如何缩小undo表空间的大小
- android线程 Handler Message Queue AsyncTask线程模型 线程交互 + 修改Button样式 示例 最终easy整合版