Опять хрень!!! Только, кажется, уже все - разобрался и опять...
Здесь (на http://learn.javascript.ru Использование замыканий есть пример: function makeArmy() { var shooters = []; for(var i=0; i<10; i++) { var shooter = function() { // функция-стрелок alert(i); // выводит свой номер }; shooters.push(shooter); } return shooters; } var army = makeArmy(); army[0](); // стрелок выводит 10, а должен 0 army[5](); // стрелок выводит 10... // .. все стрелки выводят 10 вместо 0,1,2...9ну и объяснение К моменту вызова army[0](), функция makeArmy уже закончила работу. Цикл завершился, последнее значение было i=10. Все понятно. А вот чуть ниже чем тут. Еще пример: for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 1000); }и тоже объясняется: Данный код не будет выводить числа с 0 до 9, вместо этого число 10 будет выведено десять раз. Анонимная функция сохраняет ссылку на i и когда будет вызвана функция console.log, цикл for уже закончит свою работу, а в i будет содержаться 10. Моё объяснение (по методу прогиба подреальность): скрипт прошел - все ссылки определились, и не смотря, что в сценарии вывод идет параллельно циклу, на самом деле все не так - вывод в консоль идет в конце. Вопрос: Где почитать когда события по коду идут "одновременно" а когда "по-особенному"? |
Nerv-у
Чувствую, что нужно переходить на ru-board.com - там движение побольше, а не один ты будешь за всех отдуваться. |
function top(){ for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 1000); } } Тут всё просто, присмотритесь внимательнее: function() { console.log(i); }console.log(i) выводит не конкретное число, а внутреннюю переменную i из области видимости функции top(или глобальной если цикл находится вне функции). А поскольку это происходит через 1000мс(1с), когда функция top уже отработала, то обращаясь к i функция получает значение внутренней переменной i, которое та приобрела к концу работы функции top, т.е. - 10. Разложить это можно ещё так: for(var i = 0; i < 10; i++) {} //спустя 1000мс console.log(i); console.log(i); console.log(i); console.log(i); console.log(i); console.log(i); console.log(i); console.log(i); console.log(i); console.log(i); По поводу ru-board.com не скажите, жабаскрипетров нам не так много, а компетентных и подавно.) |
А почему так с кодом
for(var i = 0; i < 10; i++) {} //спустя 1000мс console.log(i); console.log(i); console.log(i); console.log(i);ведь (из моего примера) он в теле цикла в {}. Разве не должно быть так: for i=1 console.log(1); for i=2 console.log(2); ... for i=10 console.log(10); поледовательно ? |
Kivi, потому, что значение i нигде не фиксируется. Это можно прочитать как: вывести значение переменной i через n миллисекунд. А через n миллисекунд оно будет равно чему?
Цитата:
Переходить или нет, решать тебе. Могу только отметить, что здесь js мозги очень даже неплохие (это я не о себе). |
Так вот я и хочу узнать механизм.
Внес некоторые изменения в код: for ( var k = 0; k < 10999; k++ ) { document.write( k ) document.write( "<br>" ); setTimeout(function() { document.write( k ); }, 2000 ); }чтоб цикл не успел закончиться, а например document.write(1) должен бы уже напечататься. А все равно ничего. ведь setTimeout идет как тело цикла и пока оно не выполнится не k не должно меняться. Или какое k<XXXXXXX нужно поставить чтоб заработало? |
document.write нельзя использовать в функциях исполняемых не сразу, а по событию или таймеру.
document.write - это особый способ вывода, который выводит код по мере загрузки страницы напрямую в тело(т.е. ещё не живой DOM, а просто в обрабатываемый на ходу код), и после того как страница сформирована и документ закрыт его использовать нельзя. Т.е. document.write можно использовать даже так: <script> document.write('<in'); document.write('pu'); document.write('t'); document.write(' valu'); document.write('e="t'); document.write('ext'); document.write('">'); </script>в отличие от innerHTML который работает уже на живую, а потому каждая выводимая часть обрабатывается сразу как полноценная: <script> function appendHTML( html, node ){ var d = document, fragment = d.createDocumentFragment(), container = d.createElement('div'); container.innerHTML = html; while( container.hasChildNodes() ) fragment.appendChild( container.firstChild ); (node || d.body || d.documentElement).appendChild( fragment ); return node } appendHTML('<in'); appendHTML('pu'); appendHTML('t'); appendHTML(' valu'); appendHTML('e="t'); appendHTML('ext'); appendHTML('">'); </script> Цитата:
Так вот - это не возможно, т.к. асинхронность в js виртуальна и всё исполняется в одном потоке. Вызов же функции по событию или по таймеру, в случае если другой код ещё выполняется, ставит эту функцию в очередь выполнения сразу после окончания текущего непрерывного блока кода. Циклы же относятся как раз тем блокам, что нельзя прерывать. Соответственно сколько бы не итерировался цикл, функция по таймеру не будет вызвана пока оный не закончится. По этому в описании setTimeout всегда пишут не: "вызывает функцию через n", а "вызывает функцию не раньше чем через n", или типа того. Цитата:
Также возможно вас смущает сам синтаксис for? Чтоб было понятнее: function top(){ for(var i = 0; i < 10; i++) { //... } }это то же самое что: function top(){ var i = 0; while(i < 10) { i++; //... } }Т.е. i в цикле не имеет никаких особых свойств, это такая же обычная переменная. |
Часовой пояс GMT +3, время: 00:38. |