Переменная локальной области видимости JavaScript доступна в событии после возврата из функции хоста.Зачем? - PullRequest
2 голосов
/ 23 мая 2019

Итак ... Я из C ++, и я мало что понимаю в JS. Например:

function a()
{
   var x = 0; // Local variable

   $(document).on('mousedown', function(){console.log('down: ', x++);});
   $(document).on('mouseup', function(){console.log('up: ', x++);});
   setInterval(function(){console.log('interval: ', x++);}, 1000);

   //W3schools: 'Local variables are deleted when the function is completed.'
}
a();

Почему вывод консоли выглядит следующим образом? (при случайном нажатии)


interval:  0
down:  1
up:  2
interval:  3
down:  4
up:  5
interval:  6
down:  7
interval:  8
up:  9
interval:  10
down:  11
interval:  12
up:  13
interval:  14
down:  15
up:  16
interval:  17
interval:  18

Я ожидал, что это будет 'undefined's', NaN или null, так как x должен быть удален в конце области, но кажется, что все три обратного вызова ссылаются на него просто отлично навсегда ... почему? Это новое поведение или оно работает так со старых версий JS? Я не могу найти ответ.

Ответы [ 2 ]

1 голос
/ 23 мая 2019

Комментарий W3schools неполный. В большинстве случаев переменные очищаются после завершения функции (не обязательно мгновенно, но при следующем запуске сборки мусора). Но это только потому, что в большинстве случаев больше нет ссылок на эти переменные.

Однако, поскольку javascript поддерживает функции как объекты первого класса, он также поддерживает замыкания. Когда у вас есть такая строка:

$(document).on('mousedown', function(){console.log('down: ', x++);});

... вы создаете замыкание. Это замыкание является новой функцией плюс лексическая среда, в которой она была определена. У него есть ссылка на x, и поэтому, даже когда a завершит свое разрешение, x не будет собирать мусор. Позже, когда функция вызывается, она все равно может получить доступ к переменным замыкания.

x потенциально может по-прежнему быть сборщиком мусора, но только если все затворы, ссылающиеся на него, также собирают мусор. В этом случае вы добьетесь этого, отменив регистрацию событий mouseup и mousedown и отменив интервал.

0 голосов
/ 23 мая 2019

Функции могут обращаться к x, потому что вы дали им эту переменную в области, где она была доступна. Он подсчитывает, потому что в javascript вы указываете не фактическое значение, а просто ссылку на него, поэтому все ваши обратные вызовы все еще ссылаются на x внутри функции a (). И поскольку на него все еще ссылаются, сборщик мусора javascript не удалит его, потому что он думает, что он все еще «используется», что и есть (потому что ваши функции обратного вызова используют его для увеличения при каждом вызове).

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