В чем разница в этих примерах замыканий? - PullRequest
4 голосов
/ 25 июня 2011

У меня две ситуации в каждом тесте. Я хочу понять разницу и больше понять замыкания.

тест 1:

somefunction(someobj);

и

somefunction(function(){ return someobj; });

тест 2

for(;;){
  someoperations;
}

и

for(;;)(function(iterator){
  someoperations;
})(iterator);

тест 3:

var x = (function() {
  return {};
})();

и

(function() {
  //this = window
  var x = function() {
    //this = instance of x
    this.something = somethingelse;
  }
  //making it global OR making it available outside closure.
  return (this.x=x);
})();

Мне нужно объяснение того, в чем преимущество использования его вторым способом в каждом тестовом примере.

Ответы [ 2 ]

3 голосов
/ 25 июня 2011

В javascript единственный способ создать новую переменную область видимости - это функция.

Необходимость новой области будет полностью зависеть от обстоятельств.Таким образом, общие примеры, которые вы представили, не дают однозначного ответа.


Чтобы дать что-то более конкретное, давайте возьмем ваш тест 2 и применим этот очень распространенный сценарий.где someoperations - это асинхронный вызов, такой как setTimeout:

for( var i=1; i<4; i++ ) setTimeout( function() { alert( i ); }, 1000 * i);

Проблема в том, что каждая функция, созданная в цикле (и переданная в setTimeout), ссылаетсята же самая переменная i, и поскольку она является setTimeout, которая не является блокирующей, цикл завершается полностью, прежде чем какая-либо из функций, созданных в цикле, когда-либо будет вызвана.

В результате получаетсячто каждая функция будет предупреждать 4, поскольку именно там после цикла оставалось значение i.

Пример: http://jsfiddle.net/Ng3rr/


С другой стороны, если вы вызываете функцию внутри цикла , которая устанавливает setTimeout, передавая значение i этой функции, тогда переменная, на которую ссылается каждая функция, отправляется на setTimeoutбудет местный inner_i, который ссылается на Value, который был передан во внешний вызов.

(я назвал его inner_i, чтобы различать два, но вы также можете назвать внутреннюю переменную i.Это называется изменением теней.)

for( var i=1; i<4; i++ )(function( inner_i ){
  setTimeout( function() { alert( inner_i ); }, 500 * inner_i);
})( i );

Теперь каждое предупреждение отображает значение, которое было получено во время каждой итерации.

Итак, как вы можете видеть, оно полностью зависит отситуация.

Пример: http://jsfiddle.net/Ng3rr/1/


Чтобы добавить некоторый контраст к приведенным выше примерам, если мы не выполняли какой-либо асинхронный код в цикле,внешняя функция была бы ненужной.

Это:

for( var i=1; i<4; i++ ) alert( i );

Пример: http://jsfiddle.net/Ng3rr/2/

... и это:

for( var i=1; i<4; i++ )(function( inner_i ){
    alert( inner_i );
})( i );

Пример: http://jsfiddle.net/Ng3rr/3/

... будет иметь идентичное поведение, делая внешнюю функцию ненужной.


Таким образом, вызывая внешнюю функциюФункция создает новую переменную области видимости.В этой новой области видимости переменные будут сохраняться любыми дополнительными вложенными функциями, созданными в этой области.

Кроме того, хотя переменные, созданные в этой области, доступны в функциях, вложенных в эту область, они недоступен за пределами этой области.Это предотвращает загрязнение окружающей области с помощью дополнительных имен переменных.

0 голосов
/ 25 июня 2011

Позвольте ответить, не ограничиваясь JavaScript.

Существует несколько способов использования функции в качестве переменной / параметра, один из которых вложен в другую функцию, называемую «замыканием».

Вы можете проверить полное описание «замыкания» здесь:

http://en.wikipedia.org/wiki/Closure_%28computer_science%29

Я предлагаю использовать отдельные функции (случай 1) для очень длинного расширенного кода и вложенную функцию (случай2) для краткого кода.

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