如果Javascript中的“with”语句创建了一个新范围,为什么每次关闭时此关闭都不包含新范围中的新“x”?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了如果Javascript中的“with”语句创建了一个新范围,为什么每次关闭时此关闭都不包含新范围中的新“x”?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3217字,纯文字阅读大概需要5分钟。
内容图文
![如果Javascript中的“with”语句创建了一个新范围,为什么每次关闭时此关闭都不包含新范围中的新“x”?](/upload/InfoBanner/zyjiaocheng/766/9e3d8faa9c80405bab51ad0b555cb029.jpg)
如果Javascript中的with语句创建了一个新范围,那么不应该单击链接显示不同范围内的不同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>
解决方法:
with语句不会创建一个全新的词法范围,它只是在范围链的前面引入了一个对象,例如,如果捕获i变量,它将为work:
for (var i = 1; i <= 5; i++) {
with({x:i}) {
document.getElementById('link' + i).onclick = function() {
alert(x);
return false;
};
}
}
让我试着用另一个例子更好地解释它:
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
在步骤1中,声明了x和y变量,它们是作用域链中第一个对象(全局对象)的一部分.
在步骤2中,通过with语句将新对象({x:20})引入作用域链中,现在作用域链如下所示:
________ ________ | x = 10 | <--------- | x = 20 | | y = 10 | ¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯
在步骤3中,执行另一个var语句,但它没有任何效果,因为正如我之前所说,只有函数创建一个完整的词法范围.
var语句没有效果,但是赋值有,所以当解析x变量时,会在作用域链上的第一个对象上找到,我们引入的那个使用了.
y标识符也被解析,但是在链中的第一个对象上找不到它,因此查找继续,并在最后一个对象上找到它,分配后的作用域链如下所示:
________ ________ | x = 10 | <--------- | x = 30 | | y = 30 | ¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯
当with语句结束时,最终会恢复作用域链:
________ | x = 10 | | y = 30 | ¯¯¯¯¯¯¯¯
编辑:
让我扩展一下,谈谈功能.
当function is created绑定其当前父作用域时,例如:
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
在执行函数时,会创建一个新的词法范围并将其添加到范围链中.
基本上所有函数参数的标识符(名称),用var声明的变量和用函数声明声明的函数都被绑定为在幕后创建的新对象的属性,就在函数本身执行之前(当控件进入这个新的execution context时).
此对象无法通过代码访问,称为变量对象,例如:
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
在第1步中,再次如在我的第一个示例中那样,声明了x和y变量,它们是作用域链中第一个对象(全局对象)的一部分.
在步骤2中,创建一个新的函数对象,此时将父作用域存储到该函数的[[Scope]]中,现在包含x和y.
在步骤3中,调用该函数,从Variable Instantiation进程开始,该进程在作用域链中创建一个新对象,包含在此新函数内声明的本地作用域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 | ¯¯¯¯¯¯¯¯
推荐讲座:
> ECMA-262-3 in detail. Chapter 4: Scope chain
> Scope Chain and Identifier Resolution
内容总结
以上是互联网集市为您收集整理的如果Javascript中的“with”语句创建了一个新范围,为什么每次关闭时此关闭都不包含新范围中的新“x”?全部内容,希望文章能够帮你解决如果Javascript中的“with”语句创建了一个新范围,为什么每次关闭时此关闭都不包含新范围中的新“x”?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。