Может кто-нибудь объяснить эту функцию автоматического выполнения JavaScript? - PullRequest
12 голосов
/ 02 декабря 2010
var foo = (function(){
  var x = 0;
  return function(){return x++;};
})()

Почему выражение var x = 0 запускается только один раз - мое самое большое недоразумение по этому поводу.

Ответы [ 6 ]

16 голосов
/ 02 декабря 2010

Ваш код:

var foo = (function(){
  var x = 0;
  return function(){return x++;};
})()

эквивалентен этому коду:

function f(){
  var x = 0;
  return function(){return x++;};
}
var foo = f();

Легко видеть, когда вы разбиваете его вот так, что функция f()звонил только один раз.Он определяет x, а затем возвращает новую функцию, которая определена внутри локальной области действия f.Эта новая функция часто называется «анонимной функцией» (что означает, что она не имеет имени) или «закрытием».По правде говоря, все функции в javascript являются «замыканиями» - независимо от того, названы они или нет.Термин «закрытие» просто означает, что функция сохраняет доступ к переменным, которые были определены в области действия родительской функции - даже после выхода из родительской функции.

Итак, теперь foo содержит новую функцию (закрытие), который был возвращен из f.Вы можете звонить foo() столько раз, сколько захотите - и каждый раз, когда вы это делаете, x будет возвращаться и увеличиваться.Поскольку x существует в родительской области замыкания, его значение будет сохраняться при нескольких вызовах замыкания.

Более того ... ни один другой код теперь не имеет доступа к x после выхода f() - это в основном означает, что x теперь является "частными данными" замыкания.Довольно аккуратно, да?

6 голосов
/ 02 декабря 2010

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

Объявляет переменную с именем x, инициализированную в 0.Возвращает функцию , которая при вызове будет увеличивать значение x.

Так что в этот момент foo ссылается на функцию .

Вы можете вызвать это следующим образом:

foo();

При первом вызове возвращается значение 0, затем 1, 2 ...

Ну, , подождите минуту ... , не должно ли это быть 1, 2, 3 ...?

Вы находитесь на правильном пути, но причина, по которой в данном случае это не является истинным, заключается в разнице между с предварительным увеличением и после увеличения ,(++var против var++).Разница в том, что результатом предварительного увеличения является значение переменной после увеличения, в то время как результатом последующего увеличения является значение переменной до увеличения .

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

3 голосов
/ 02 декабря 2010

Давайте разберемся ... Сначала мы определим анонимную функцию:

(function() { ... })

Затем мы немедленно выполняем его:

(function() { ... })()

Результатом этого выполнения является другая функция:

function(){return x++;}

И x = 0 захватывается замыканием, когда мы создали вышеуказанную функцию. Затем мы присваиваем эту результирующую функцию для foo:

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

Со значением х, захваченным замыканием. Всякий раз, когда выполняется foo, x увеличивается.

1 голос
/ 02 декабря 2010

Анонимная функция вызывается сразу после (), который следует за ней (без указания параметров). Эта функция при выполнении возвращает другую функцию, которая имеет собственную переменную x, которая увеличивается при запуске.

Таким образом, foo() будет 0 первым запуском, 1 вторым и т. Д., Так как этот x, с которого он был создан, продолжает увеличиваться.

0 голосов
/ 02 декабря 2010

Это то, что называется замыканием . Здесь определены две функции - внутренняя (которая является замыканием) и внешняя, которая создает и возвращает замыкание.

Ваш коднемедленно вызывает внешнюю функцию и присваивает результат (закрытие) foo.

Обратите внимание, что код внутри замыкания не включает оператор var x = 0;, поэтому при вызове foo() он выполняет только код внутри замыкания (return x++;)

x, упомянутый здесь, является экземпляром в вызове.Что делает замыкания интересными, так это то, что это x отличается между вызовами внешней функции - рассмотрим пример ниже.foo и bar будут увеличиваться независимо друг от друга, потому что они ссылаются на различных x s

function makeClosure(){
  var x = 0;
  return function(){return x++;};
}

var foo = makeClosure();
var bar = makeClosure();

foo(); //returns 0
foo(); //returns 1
bar(); //returns 0
foo(); //returns 2
0 голосов
/ 02 декабря 2010

На самом деле в этом случае x является локальной переменной в блоке / замыкании, назначенной объекту foo.Тот, который увеличивается при вызове foo().

Проверьте это в действии - http://jsfiddle.net/3X283/

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