nop*_*ole 3 javascript closures scope
如果withJavascript中的语句创建了一个新范围,那么不应该点击链接显示x不同范围内的不同内容吗?它没有.
<a href="#" id="link1">ha link 1</a>
<a href="#" id="link2">ha link 2</a>
<a href="#" id="link3">ha link 3</a>
<a href="#" id="link4">ha link 4</a>
<a href="#" id="link5">ha link 5</a>
<script type="text/javascript">
for (i = 1; i <= 5; i++) {
with({foo:"bar"}) {
var x = i;
document.getElementById('link' + i).onclick = function() { alert(x); return false; }
}
}
</script>
Run Code Online (Sandbox Code Playgroud)
CMS*_*CMS 27
该with语句不会创建一个全新的词法范围,它只是在范围链的前面引入一个对象,例如,如果捕获i变量,它将起作用:
for (var i = 1; i <= 5; i++) {
with({x:i}) {
document.getElementById('link' + i).onclick = function() {
alert(x);
return false;
};
}
}
Run Code Online (Sandbox Code Playgroud)
让我试着用另一个例子更好地解释它:
var x = 10, y = 10; // Step 1
with ({x: 20}) { // Step 2
var x = 30, y = 30; // Step 3
alert(x); // 30
alert(y); // 30
}
alert(x); // 10
alert(y); // 30
Run Code Online (Sandbox Code Playgroud)
在步骤1中,声明了x和y变量,它们是作用域链中第一个对象(全局对象)的一部分.
在第2步中,语句{x:20}将一个新的object()引入作用域链with,现在作用域链如下所示:
________ ________ | x = 10 | <--------- | x = 20 | | y = 10 | ¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯
在步骤3中,var执行另一个语句,但它没有任何效果,因为正如我之前所说,只有函数创建一个完整的词法范围.
该var语句没有任何效果,但是赋值具有,因此当x解析变量时,会在作用域链上的第一个对象上找到,即我们引入的对象with.
该y标识符也解决了,但它不是链的第一个对象上找到,所以继续查找了,发现它的最后一个对象上,在分配后,作用域链是这样的:
________ ________ | x = 10 | <--------- | x = 30 | | y = 30 | ¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯
当with语句结束,范围链终于恢复:
________ | x = 10 | | y = 30 | ¯¯¯¯¯¯¯¯
编辑: 让我扩展一下,谈谈功能.
当创建函数其当前父范围约束,例如:
var fn;
// augment scope chain
with ({foo: "bar"}) {
fn = function () { // create function
return foo;
};
}??
// restored scope chain
fn(); // "bar", foo is still accessible inside fn
Run Code Online (Sandbox Code Playgroud)
在执行函数时,会创建一个新的词法范围并将其添加到范围链中.
基本上所有函数参数的标识符(名称),声明的变量var和用function语句声明的函数都被绑定为在幕后创建的新对象的属性,就在函数本身执行之前(当控件进入这个新的执行上下文时).
此对象无法通过代码访问,称为变量对象,例如:
var x = 10, y = 10; // Step 1
(function () { // Step 2
var x, y;
x = 30; // Step 4
y = 30;
alert(x); // 30
alert(y); // 30
})(); // Step 3
alert(x); // 10 // Step 5
alert(y); // 10
Run Code Online (Sandbox Code Playgroud)
在第1步中,再次在我的第一个示例中,声明了x和y变量,它们是作用域链中第一个对象(全局对象)的一部分.
在步骤2中,创建一个新的函数对象,此时将父作用域存储到该函数的[[Scope]]中,包含now x和y.
在步骤3中,调用该函数,启动变量实例化过程,该过程在作用域链中创建一个新对象,包含在此新函数内声明的本地作用域x和y变量,此时作用域链如下所示:
parent scope Variable Object ________ _______________ | x = 10 | <--------- | x = undefined | | y = 10 | | y = undefined | ¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
然后在步骤4中,分配x和y完成,但由于新的词法范围已创建,因此它不会影响外部值.
parent scope Variable Object ________ ________ | x = 10 | <--------- | x = 30 | | y = 10 | | y = 30 | ¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯
最后,在步骤5中,函数结束,范围链恢复到其原始状态.
________ | x = 10 | | y = 10 | ¯¯¯¯¯¯¯¯
推荐讲座: