Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #31 (permalink)  
Старый 04.09.2012, 02:18
Аватар для Kivi
Интересующийся
Отправить личное сообщение для Kivi Посмотреть профиль Найти все сообщения от Kivi
 
Регистрация: 30.08.2012
Сообщений: 15

Опять хрень!!! Только, кажется, уже все - разобрался и опять...
Здесь (на 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.


Моё объяснение (по методу прогиба подреальность):
скрипт прошел - все ссылки определились, и не смотря, что в сценарии вывод идет параллельно циклу, на самом деле все не так - вывод в консоль идет в конце.
Вопрос:
Где почитать когда события по коду идут "одновременно" а когда "по-особенному"?
Ответить с цитированием
  #32 (permalink)  
Старый 04.09.2012, 02:22
Аватар для Kivi
Интересующийся
Отправить личное сообщение для Kivi Посмотреть профиль Найти все сообщения от Kivi
 
Регистрация: 30.08.2012
Сообщений: 15

Nerv
Чувствую, что нужно переходить на ru-board.com - там движение побольше, а не один ты будешь за всех отдуваться.
Ответить с цитированием
  #33 (permalink)  
Старый 04.09.2012, 02:46
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,587

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 не скажите, жабаскрипетров нам не так много, а компетентных и подавно.)
__________________
29375, 35

Последний раз редактировалось Aetae, 04.09.2012 в 02:56.
Ответить с цитированием
  #34 (permalink)  
Старый 04.09.2012, 13:22
Аватар для Kivi
Интересующийся
Отправить личное сообщение для Kivi Посмотреть профиль Найти все сообщения от Kivi
 
Регистрация: 30.08.2012
Сообщений: 15

А почему так с кодом
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);
поледовательно ?
Ответить с цитированием
  #35 (permalink)  
Старый 04.09.2012, 13:54
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Kivi, потому, что значение i нигде не фиксируется. Это можно прочитать как: вывести значение переменной i через n миллисекунд. А через n миллисекунд оно будет равно чему?

Сообщение от Kivi
Чувствую, что нужно переходить на ru-board.com - там движение побольше, а не один ты будешь за всех отдуваться.
не то, чтобы я отдувался Отвечаю тогда, когда мне удобно. Не хочу, не отвечаю.
Переходить или нет, решать тебе. Могу только отметить, что здесь js мозги очень даже неплохие (это я не о себе).
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #36 (permalink)  
Старый 04.09.2012, 16:23
Аватар для Kivi
Интересующийся
Отправить личное сообщение для Kivi Посмотреть профиль Найти все сообщения от Kivi
 
Регистрация: 30.08.2012
Сообщений: 15

Так вот я и хочу узнать механизм.
Внес некоторые изменения в код:
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 нужно поставить чтоб заработало?
Ответить с цитированием
  #37 (permalink)  
Старый 04.09.2012, 17:30
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,587

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>


Сообщение от Kivi Посмотреть сообщение
Или какое k<XXXXXXX нужно поставить чтоб заработало?
Я так понимаю в хотите подобрать такое k, чтобы на момент прошествия 1000мс цикл всё ещё продолжал исполнение и соответственно значение k было взято из текущей итерации?
Так вот - это не возможно, т.к. асинхронность в js виртуальна и всё исполняется в одном потоке. Вызов же функции по событию или по таймеру, в случае если другой код ещё выполняется, ставит эту функцию в очередь выполнения сразу после окончания текущего непрерывного блока кода. Циклы же относятся как раз тем блокам, что нельзя прерывать.
Соответственно сколько бы не итерировался цикл, функция по таймеру не будет вызвана пока оный не закончится. По этому в описании setTimeout всегда пишут не: "вызывает функцию через n", а "вызывает функцию не раньше чем через n", или типа того.

Сообщение от Kivi Посмотреть сообщение
ведь (из моего примера) он в теле цикла в {}.
Нет не в теле. В описание setTimeout написано.(покрайней мере должно быть), что он исполняете передаваемую функцию в глобальной области видимости. А внутреннюю переменную i она видит только потому, что сама передаваемая функция была создана в внутри другой и замкнула на себя ссылки на внутренние переменные. И на момент исполнения i уже давно равна 10.

Также возможно вас смущает сам синтаксис for? Чтоб было понятнее:
function top(){
    for(var i = 0; i < 10; i++) {
        //...
    }
}
это то же самое что:
function top(){
    var i = 0;
    while(i < 10) {
        i++;
        //...
    }
}
Т.е. i в цикле не имеет никаких особых свойств, это такая же обычная переменная.
__________________
29375, 35

Последний раз редактировалось Aetae, 04.09.2012 в 18:18.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Почему то работает, то нет? gyunduz Общие вопросы Javascript 0 22.01.2011 16:08
Некорректно работает функция для создания элементов exec Общие вопросы Javascript 4 13.07.2010 11:15
jQuery не так работает на сервере dial jQuery 2 19.11.2009 15:19
Функция не возвращает false, почему? Vitaly jQuery 3 05.07.2009 16:05
почему не работает <body onload=test()> Ichigeki Общие вопросы Javascript 11 29.10.2008 13:49