如果“与”是Javascript 中的语句创建了一个新的作用域,为什么这个闭包不包含新的“x”?每次都在新的范围内?
如果 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>
If the with
statement in Javascript creates a new scope, shouldn't clicking on the links show a different x
which are in different scopes? It doesn't.
<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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
with
语句不会创建一个全新的词法作用域,它只是在作用域链前面引入一个对象,例如,如果您捕获i
变量,它会工作:让我尝试用另一个例子更好地解释它:
在步骤 1 中,
x< /code> 和
y
变量已声明,它们是作用域链中第一个对象(全局对象)的一部分。步骤 2 中,通过
with
语句将一个新对象 ({x:20}
) 引入到作用域链中,现在作用域链看起来像这样:在 第 3 步,执行另一个 var 语句,但它没有任何效果,因为正如我之前所说,只有函数才能创建完整的词法作用域。
var
语句没有效果,但赋值有效果,因此当x
变量被解析时,会到达作用域链上的第一个对象,即我们使用与
。y 标识符也被解析,但在链中的第一个对象上找不到它,因此继续查找,并在最后一个对象上找到它,赋值后的作用域链如下所示:
当
with
语句结束时,作用域链最终恢复:编辑:
我稍微展开一下,讲讲函数。
当函数被创建时,其当前父作用域被绑定,例如
:当函数执行时,新的词法作用域被创建并添加到作用域链中。
基本上,函数参数的所有标识符(名称)、用
var
声明的变量以及用function
语句声明的函数,都被绑定为在幕后创建的新对象的属性,只是在函数本身执行之前(当控件进入这个新的执行上下文时)。该对象无法通过代码访问,称为变量对象,例如:
在步骤 1 中,再次与我的第一个示例一样,
x
和y
变量被声明,它们是作用域链中第一个对象(全局对象)的一部分。在第2步中,创建了一个新的函数对象,父作用域此时存储在该函数的[[Scope]]中,现在包含
x
和y
。在步骤 3 中,调用该函数,启动变量实例化 process,它在作用域链中创建一个新对象,包含在这个新函数中声明的本地作用域的 x 和 y 变量,此时的作用域链如下所示:
然后在第4步中,完成了
x
和y
的赋值,但由于新的词法作用域已经创建,因此它不会影响外部值。最后,在第 5 步中,函数结束,作用域链恢复到原始状态。
推荐讲座:
The
with
statement doesn't creates a full new lexical scope, it just introduces an object in front of the scope chain, for example, if you capture thei
variable, it will work:Let me try to explain it better with another example:
In the Step 1, the
x
andy
variables are declared and they are part of the first object in the scope chain, the global object.In the Step 2, a new object (
{x:20}
) is introduced into the scope chain by thewith
statement, now the scope chain looks something like this:In the Step 3, another
var
statement is executed, but it has no effect because as I said before, only functions create a full lexical scope.The
var
statement has no effect, but the assignment has, so when thex
variable is resolved, is reached on the first object on the scope chain, the one we introduced usingwith
.The
y
identifier is resolved also, but it is not found on the first object in the chain, so the lookup continues up, and finds it on the last object, the scope chain after the assignments looks like this:When the
with
statement ends, the scope chain is finally restored:Edit:
Let me expand a little bit and talk about functions.
When a function is created its current parent scope is bound, for example:
A new lexical scope is created and added to the scope chain when the function is executed.
Basically all identifiers (names) of function arguments, variables declared with
var
and functions declared with thefunction
statement, are bound as properties of a new object created behind the scenes, just before the function itself executes (when controls enters this new execution context).This object is not accessible through code, is called the Variable Object, for example:
In the Step 1, again as in my first example, the
x
andy
variables are declared and they are part of the first object in the scope chain, the global object.In the Step 2, a new function object is created, the parent scope is stored in this moment, into the [[Scope]] of that function, containing now
x
andy
.In the Step 3, the function is invoked, starting the Variable Instantiation process, which creates a new object in the scope chain, containing the locally scoped
x
andy
variables declared inside this new function, the scope chain at this moment looks like this:Then in the Step 4, the assignment of
x
andy
is done, but since the new lexical scope has been created, it doesn't affect the outer values.And finally, in the Step 5, the function ends and the scope chain is restored to its original state.
Recommended lectures: