Подтвердить что ты не робот

Может ли кто-нибудь объяснить эту функцию автозапуска JavaScript?

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

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

4b9b3361

Ответ 1

Ваш код:

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 теперь является "личными данными" закрытия. Довольно аккуратный ха?

Ответ 2

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

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

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

Способ вызова:

foo();

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

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

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

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

Ответ 3

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

(function() { ... })

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

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

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

function(){return x++;}

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

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

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

Ваш код немедленно вызывает внешнюю функцию и присваивает результат (закрытие) 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