Если оператор «with» в Javascript создает новую область видимости, почему это закрытие не содержит новый «x» в новой области видимости каждый раз? - PullRequest
3 голосов
/ 30 апреля 2010

Если оператор with в Javascript создает новую область видимости, не следует ли щелкнуть по ссылкам, чтобы показать разные 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>

1 Ответ

27 голосов
/ 30 апреля 2010

Оператор with не создает полностью новую лексическую область, он просто вводит объект перед цепочкой областей действия, например, если вы захватите переменную i, он будет работать :

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 новый объект ({x:20}) вводится в цепочку областей действия с помощью оператора with, теперь цепочка областей действия выглядит примерно так:

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

На шаге 3 выполняется еще один оператор var, но он не действует, потому что, как я уже говорил, только функции создают полную лексическую область действия.

Оператор var не имеет эффекта, но назначение имеет значение, поэтому, когда переменная x разрешена, достигается первый объект в цепочке областей действия, который мы ввели с помощью with.

Идентификатор y также разрешен, но он не найден в первом объекте в цепочке, поэтому поиск продолжается и находит его в последнем объекте, цепочке областей после назначений выглядит так:

   ________              ________
  | x = 10 | <--------- | <b>x = 30</b> |
  | <b>y = 30</b> |             ¯¯¯¯¯¯¯¯¯
   ¯¯¯¯¯¯¯¯ 

Когда оператор with заканчивается, цепочка областей действия наконец восстанавливается:

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

Edit: Позвольте мне немного расширить и поговорить о функциях.

При создании функции ее текущая родительская область привязывается, например:

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, и функций, объявленных с помощью оператора 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

На шаге 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 = <b>30</b> |
  | y = 10 |            | y = <b>30</b> | 
   ¯¯¯¯¯¯¯¯              ¯¯¯¯¯¯¯¯ 

И, наконец, на шаге 5 функция заканчивается, и цепочка областей действия возвращается в исходное состояние.

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

Рекомендуемые лекции:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...