Контекст функции при вызове по таймеру
Здравствуйте. При изучении учебника по Javascript возник вопрос. В теме про таймеры есть упражнение "Вывод чисел каждые 100мс". Код решения:
function printNumbersInterval20_100() { var i = 1; var timerId = setInterval(function() { console.log(i); if (i == 20) clearInterval(timerId); i++; }, 100); } // вызов printNumbersInterval20_100(); Не понял расклад по контексту (видимости переменных) в случае вызова setInternal() из функции (не из глобального контекста), в нашем случае printNumbersInterval20_100. Из текста статьи, цитирую: "Вызов через setTimeout не передаёт контекст this. В частности, вызов метода объекта через setTimeout сработает в глобальном контексте". Так вот если наша анонимная функция сработает через указанное время в глобальном контексте, то откуда она будет знать про переменную i, которая определена локально во внешней функции? Как я понимаю, setInternal не блокирует выполнение скрипта, в данном случае не останавливает выполнение функции printNumbersInterval20_100. Т.е.создав таймер "в отдельном потоке", функция продолжает выполнятся и в конце концов заканчивается. Тогда откуда берется сохраненное значение i? |
Цитата:
|
Разве передано? function(), т.е. параметры не передаются. А тело функции, имхо, будет получать значения исходя из контекста, исходя из окружения в момент выполнения, который случиться позже, когда внешняя функция printNumbersInterval20_100() уже завершиться. Да и контекст анонимной функции, согласно статье, глобальный. Где я ошибаюсь?
|
Цитата:
Цитата:
Цитата:
|
Bombus, почитай коментарии к этой статье до конца...
|
Ok, а как же (цитата из учебника):
"Вызов через setTimeout не передаёт контекст this. В частности, вызов метода объекта через setTimeout сработает в глобальном контексте". Т.е. переменные из внешней функции передаются, а контекст нет? |
Цитата:
|
ksa, предложу немного измененный вариант исходного кода:
function printNumbersInterval20_100() { var i = 1, point = 'start'; var timerId = setInterval(function() { console.log(i + ' ' + point); if (i == 20) clearInterval(timerId); i++; }, 100); point = 'finish'; } В логах пишется: 1 finish 2 finish ......... 20 finish Кажется механизм передачи переменных следующий: 1. При выполнении функции printNumbersInterval20_100() создается анонимная функция, которая привязывается к таймеру. Также ей передается ссылка на VariableEnviroment (а может и на LexicalEnvironment) от вызывающей функции, но все-же это не передача параметров функции. 2. printNumbersInterval20_100() уже может выполнится полностью, когда таймер сработает первый раз, но завершение функции будет означать лишь остановку действий внешней функции, а VariableEnviroment останется висеть в памяти. Примерно как это происходит с замыканиями - внешняя функция вроде завершена, но список переменных из памяти не выгружается пока на них будут ссылаться другие функции. 3. Анонимная функция при срабатывания таймера берет значения из переданного объекта VariableEnviroment. Т.е. ей не передается снимок переменных в момент создания анонимной функции из printNumbersInterval20_100(), а именно переменные в функцию попадают по ссылке в момент сработки таймера. Еще один вывод: если таймеров создается много, то необходимо их после выполнения(!) чистить "ручками", а не оставлять на без присмотра, иначе будет копиться мусор и могут появиться тормоза. Где-то на форуме видел рекомендации про чистку при создании тысяч таймеров в обязательном порядке, иначе система может тормозить. Если я не прав, прошу поправить. |
Bombus,
У вас 6я строка отрабатывает каждые 0.1 секунды, а 8я еще ДО того момента, когда закончится первый интервал. Может так понятнее будет: function printNumbersInterval20_100() { var i = 1, point = 'start'; var timerId = setInterval(function() { console.log(i + ' ' + point); if (i == 20) clearInterval(timerId); i++; point = (point =='finish') ? 'start' : 'finish'; }, 100); } printNumbersInterval20_100(); |
BETEPAH,
Что-то не понял, что вы хотели сказать. Т.е. подтверждаете тот механизм передачи значения переменных через VariablrEnviroment? Мне показалось что в вашем коде пропущена строка point = 'finish';в конце функции printNumbersInterval20_100, т.к. в логах занчения point чередуются между 'start' и 'finish'. |
Часовой пояс GMT +3, время: 12:35. |