如果“带”, Javascript中的语句创建了一个新的范围,为什么这个闭包不包含新的“x”。在每个新的范围? [英] If the "with" statement in Javascript creates a new scope, why does this closure doesn't contain the new "x" in new scope each time?

查看:138
本文介绍了如果“带”, 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);返回false; }
}

}

< / script>


解决方案

with 语句不会创建一个全新的词法范围,它只是在范围链前引入一个对象,例如,如果你捕获 i 变量,它将工作

  for(var i = 1; i< = 5; i ++){
with({x:i}){
document.getElementById('link'+ i).onclick = function (){
alert(x);
返回false;
};
}
}

让我尝试用另一个例子更好地解释它:

  var x = 10,y = 10; //步骤1 

with({x:20}){// Step 2

var x = 30,y = 30; //步骤3

alert(x); // 30
alert(y); // 30
}

alert(x); // 10
alert(y); // 30

在第1步中, x y 变量被声明,它们是作用域链中第一个对象的一部分,即全局对象。



在第2步中,新对象( {x:20} )由引入范围链中,带声明,现在范围链看起来像这样:

 
________ ________
| x = 10 | < --------- | x = 20 |
| y = 10 | ¯¯¯¯¯¯¯¯¯¯¯
¯¯¯¯¯¯¯¯

在第3步中,另一个 var 语句已执行,但它没有效果,因为正如我之前所说,只有函数创建一个完整的词法范围。



var 语句无效,但分配有,因此当解析 x 变量时,范围链上的第一个对象,我们使用引入的对象。



y 标识符也已解析,但在链中的第一个对象上找不到,因此查找继续,并在最后一个对象上找到它,分配后的作用域链如下所示:

 
________ ________
| x = 10 | < --------- | x = 30 |
| y = 30 | ¯¯¯¯¯¯¯¯¯¯¯
¯¯¯¯¯¯¯¯

语句结束后,范围链最终恢复:

 
________
| x = 10 |
| y = 30 | $ b $b¯¯¯¯¯¯¯¯¯b

编辑:
让我展开一点点,谈谈功能。



函数已创建其当前父作用域已绑定,例如:

  var fn; 
//扩充范围链
with({foo:bar}){
fn = function(){// create function
return foo;
};
}
//恢复范围链
fn(); //bar,foo仍可在fn
内访问

创建一个新的词法范围并添加到函数执行时的范围链。



基本上所有函数参数的标识符(名称),用 var 和使用函数语句声明的函数被绑定为在幕后创建的新对象的属性,就在函数本身执行之前(当控件进入此新执行上下文)。



此对象无法通过代码访问,称为变量对象,例如:

  var x = 10,y = 10; //步骤1 

(function(){//步骤2
var x,y;

x = 30; //步骤4
y = 30;

alert(x); // 30
alert(y); // 30
})(); //步骤3

alert(x); // 10 //步骤5
alert(y); // 10

在步骤1中,再次在我的第一个例子中, x y 变量,它们是作用域链中第一个对象的一部分,即全局对象。



在步骤2中,创建一个新的函数对象,此时父作用域存储到该函数的[[Scope]]中,现在包含 x y



在步骤3中,调用该函数,启动变量实例化过程,它在作用域链中创建一个新对象,包含在这个新函数中声明的本地作用域 x y 变量,此时的作用域链如下所示:

 
父范围变量对象
________ _______________
| x = 10 | < --------- | x =未定义|
| y = 10 | | y =未定义|
~~~~~在步骤4中, x y 的分配已完成,但由于已创建新的词法范围,它不会影响外部值。

 
父范围变量对象
________ ________
| x = 10 | < --------- | x = 30 |
| y = 10 | | y = 30 |
~~~~~~~~~~~~~~~~~~函数结束,范围链恢复到原始状态。

 
________
| x = 10 |
| y = 10 | $ b $b¯¯¯¯¯¯¯¯¯

推荐讲座:




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>

解决方案

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 the i variable, it will work:

for (var i = 1; i <= 5; i++) {
  with({x:i}) {
    document.getElementById('link' + i).onclick = function() {
      alert(x);
      return false;
    };
  }
}

Let me try to explain it better with another example:

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

In the Step 1, the x and y 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 the with statement, now the scope chain looks something like this:

   ________              ________
  | x = 10 | <--------- | x = 20 |
  | y = 10 |             ¯¯¯¯¯¯¯¯¯
   ¯¯¯¯¯¯¯¯ 

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 the x variable is resolved, is reached on the first object on the scope chain, the one we introduced using with.

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:

   ________              ________
  | x = 10 | <--------- | x = 30 |
  | y = 30 |             ¯¯¯¯¯¯¯¯¯
   ¯¯¯¯¯¯¯¯ 

When the with statement ends, the scope chain is finally restored:

   ________ 
  | x = 10 |
  | y = 30 |
   ¯¯¯¯¯¯¯¯ 

Edit: Let me expand a little bit and talk about functions.

When a function is created its current parent scope is bound, for example:

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

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 the function 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:

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

In the Step 1, again as in my first example, the x and y 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 and y.

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 and y variables declared inside this new function, the scope chain at this moment looks like this:

  parent scope           Variable Object
   ________              _______________
  | x = 10 | <--------- | x = undefined |
  | y = 10 |            | y = undefined | 
   ¯¯¯¯¯¯¯¯              ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 

Then in the Step 4, the assignment of x and y is done, but since the new lexical scope has been created, it doesn't affect the outer values.

  parent scope           Variable Object
   ________              ________
  | x = 10 | <--------- | x = 30 |
  | y = 10 |            | y = 30 | 
   ¯¯¯¯¯¯¯¯              ¯¯¯¯¯¯¯¯ 

And finally, in the Step 5, the function ends and the scope chain is restored to its original state.

   ________ 
  | x = 10 |
  | y = 10 |
   ¯¯¯¯¯¯¯¯ 

Recommended lectures:

这篇关于如果“带”, Javascript中的语句创建了一个新的范围,为什么这个闭包不包含新的“x”。在每个新的范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆