Jump to content
  • 0

Не срабатывает цикл for


denis_alekss
 Share

Question

Почему код срабатывает только тогда когда var i = 0; поменять на let i = 0;?
Если оставить код как есть вывод:

 

fib[6] = undefined


 

Сам код

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <script>
const fib = [1,2,3,5,8,13]
for(var i = 0; i < fib.length; i++){
    setTimeout(function() {
        console.log(`fib[${i}] = ${fib[i]}`)
    },1500)
}

    </script>
</body>
</html>

 

Вот такой код:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <script>
const fib = [1,2,3,5,8,13]
for(var i = 0; i < fib.length; i++){
    (function(j){
    setTimeout(function() {
        console.log(`fib[${i}] = ${fib[i]}`)
    },1500)
    })(i)
}

    </script>
</body>
</html>



 выдаст также
 

fib[6] = undefined


 

Edited by denis_alekss
Link to comment
Share on other sites

21 answers to this question

Recommended Posts

  • 0

В примере с замыканием на самом деле все правильно работает, ошибка тут:

// console.log(`fib[${i}] = ${fib[i]}`)
   console.log(`fib[${j}] = ${fib[j]}`)

У var область видимости функции или глобальная, у let и const – область видимости окружающего блока.

То есть пример можно переписать так, что будет равнозначно:

const fib = [1, 2, 3, 5, 8, 13];

var i = 0;

for(; i < fib.length; i++) {
  setTimeout(function() {
    console.log(`fib[${i}] = ${fib[i]}`)
  }, 1500)
}

Видно, что на каждой итерации увеличивается значение одной и той же внешней переменной. Но когда счетчик i++ доходит до 6 и условие (i < 6) не выполняется, цикл завершает свою работу, однако значение переменной i теперь уже 6, а не 5.

Функция обратного вызова, переданная в setTimeout, ставится в очередь на выполнение. И эта очередь подойдет, только когда завершится выполнение основного потока. А к этому моменту i == 6. Дальше отложенные коллбэки начинают вызываться один за другим, и они берут это глобальное значение. Ну а элемента с индексом 6 в массиве нет, вот и undefined.

С замыканием или let или const, понятно, что такой проблемы не будет.

  • Like 1
Link to comment
Share on other sites

  • 0

При var i = 0  при проверке условия цикла тело цикла вообще выполняется? Или 5 раз проверяется условие но тело не выполняется?

5 раз как проверяется условие выводы почему не происходят?

Edited by denis_alekss
Link to comment
Share on other sites

  • 0
51 минуту назад, denis_alekss сказал:

При var i = 0  при проверке условия цикла тело цикла вообще выполняется? Или 5 раз проверяется условие но тело не выполняется?

5 раз как проверяется условие выводы почему не происходят?

У вас JavaScript головного мозга. Даже ниндзи так не угарают ...

Гонять порожняк в порожняк по таймеру IIFE в консту. Мсье еще не знает об async и await. Ему бы это доставило.

 

	let fib = [ 1, 2, 3, 5, 8, 13 ];

	var xfib = [];

	let x = 0;

	for( i of fib ) {

		(( j ) => {

			void setTimeout(() => {

				xfib[ x++ ] = j;

			}, 1500);

		})( i );

	}

 

Во первых, const - это плохо так как он "зафризил" все данные. Его лучше не использовать вообще.

Во вторых, надо следить за контекстом.

 

Edited by Full-R
Link to comment
Share on other sites

  • 0

Вместо анонимной вы сделали запись короче стрелочной функцией.. for...of вы перебрали элементы массива fib.. и записали все в новый пустой массив xfib, а void в этом коде какую роль играет?

Вот так без void также работает:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <script>
let fib = [ 1, 2, 3, 5, 8, 13 ];

	var xfib = [];

	let x = 0;

	for( i of fib ) {

		(( s) => {
			setTimeout(() => {

			xfib[ x++ ] = s;
			console.log(xfib)	
  			}, 1500);

		})( i );

	}

    </script>
</body>
</html>

 

Edited by denis_alekss
Link to comment
Share on other sites

  • 0
11 часов назад, denis_alekss сказал:

Вместо анонимной вы сделали запись короче стрелочной функцией.. for...of вы перебрали элементы массива fib.. и записали все в новый пустой массив xfib, а void в этом коде какую роль играет?

Вот так без void также работает:

 

Void освобождает память сразу после срабатывания. Какая цель вашего кода?

Link to comment
Share on other sites

  • 0
11 часов назад, Full-R сказал:

Какая цель вашего кода?

тренировочная



 

let fib = [ 1, 2, 3, 5, 8, 13 ];

    var xfib = [];

    let x = 0;

    for( i of fib ) {

        (( j ) => {

            void setTimeout(() => {

                xfib[ x++ ] = j;

            }, 1500);

        })( i );

    }



Стрелочная функция здесь анонимная с параметром j в который попадает значение i за каждой итерацией?
Эта строка нужна чисто чтобы заполнить пустой массив, создав клон массива?

Edited by denis_alekss
Link to comment
Share on other sites

  • 0
12 часов назад, denis_alekss сказал:

тренировочная



 



let fib = [ 1, 2, 3, 5, 8, 13 ];

    var xfib = [];

    let x = 0;

    for( i of fib ) {

        (( j ) => {

            void setTimeout(() => {

                xfib[ x++ ] = j;

            }, 1500);

        })( i );

    }



Стрелочная функция здесь анонимная с параметром j в который попадает значение i за каждой итерацией?
Эта строка нужна чисто чтобы заполнить пустой массив, создав клон массива?

> Стрелочная функция здесь анонимная с параметром j в который попадает значение i за каждой итерацией?

Это так.

> Эта строка нужна чисто чтобы заполнить пустой массив, создав клон массива?

Да.

 Void очищает память после выполнения.

 

SetTimeout и SetInterval в браузере сделаны очень плохо(есть утечки памяти). Для этого добавлен void.

Вот модель этих futures в браузере на request animation frame.

 


RR = {
		// Modern TimeOut and Interval
		interval: ( c, d = 1000, o = null ) => {

			if( c ) {

				//let hash = RR.md5( c.toString() );

				let dn = Date.now, start = dn(), stop;

				//console.log('Interval '+ hash +' started');

				let cnt = 0;

				let interval = async () => {

					let n = dn() - start < d;

					if( !n && o ) {

						stop = 1;

						//console.log('Timeout '+ hash +' stoped');

					}

					n || ( start += d, c.call( /*hash*/ ) );

					stop || await void self.requestAnimationFrame( interval );

					cnt++;

				};

				void self.requestAnimationFrame( interval );

				return {

					stop: () => { 

						stop = 1;

						//o ? console.log('Timeout '+ hash +' stoped by task') : console.log('Interval '+ hash +' stoped by task');

					}

				};

			}
			else {

				console.log('Interval: Callback function not defined');

			}

		},
};

Даже в этом коде loop не завершается. Таймер продолжает тикать до бесконечности. 

 

console.log(`fib[${i}] = ${fib[i]}`)

 

Я просто не понял зачем вы это делаете?

 

Edited by Full-R
  • Like 1
Link to comment
Share on other sites

  • 0

Пруфа нет. Это мои личные исследования по теме. Можно немного пояснить на примере с SetInterval. Если сделать void то ссылка на него уничтожится после инициализации. То есть не возможно будет отследить этот таймер, что облегчит работу браузера на немного:

 

let i = void setInterval(() => {

	console.log('test');

}, 500);

В данном примере не работает clearInterval

clearInterval(i);

Если интервал нужно останавливать, то void стоит убрать.

Для setTimeout: она разрушается после выполнения первого тика, но оставляет шлак в памяти и продолжает тикать в процессоре:

let i = void setTimeout(() => {

	console.log('test');

}, 500);

После того как прошло пол секунды таймер перестанет вызывать console.log. Поскольку мы не знаем как это говнище сделано в браузере приходится применять методы борьбы с утечками памяти вручную(все до одного системные программисты говорят что там 2 ошибки есть и кроме этого таймер не завершается вообще).

Вот кстати, вариант получше с моделью таймера на requestAnimationFrame:

 

RR = {
  		// Modern TimeOut and Interval
		interval: ( c, d = 1000, o = null ) => {

			if( c ) {

				//let hash = RR.md5( c.toString() );

				let dn = Date.now, start = dn(), stop;

				//console.log('Interval '+ hash +' started');

				let cnt = 0;

				void requestAnimationFrame(

					async function interval() {

						let n = dn() - start < d;

						if( !n && o ) {

							stop = 1;

							// console.log('Timeout '+ hash +' stoped');

						}

						n || ( start += d, c.call( /*hash*/ ) );

						stop || await void requestAnimationFrame( interval );

						if( stop ) {

							interval = null;

						}

						cnt++;

					}

				);

				return {

					stop: () => { 

						stop = 1;

						// o ? console.log('Timeout '+ hash +' stoped by task') : console.log('Interval '+ hash +' stoped by task');

					}

				};

			}
			else {

				console.log('Interval: Callback function not defined');

			}

		},

 

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

Если функцию запустить с void она уничтожается после первого вызова и дальше к ней нет доступа. Это значит что и оперативная память, где дислоцировалась функция престаёт жрать электричество.

Edited by Full-R
Link to comment
Share on other sites

  • 0
14 часов назад, Full-R сказал:

Если сделать void то ссылка на него уничтожится после инициализации.

Если вы никуда не присваиваете ссылку на объект, то счетчик ссылок на него и так будет нулевым. Сборщик мусора уничтожит его и без void.

14 часов назад, Full-R сказал:

Для setTimeout: она разрушается после выполнения первого тика, но оставляет шлак в памяти и продолжает тикать в процессоре.

Пруф? Знакомые системные программисты, которые все как один подтверждают мои слова – это не аргумент.

14 часов назад, Full-R сказал:

Это мои личные исследования по теме.

Тогда в чем же заключается ваше исследование? Ну сделали вы предположение, что оно вот так вот работает (хотя тут же пишете, что понятия не имеете, как это говнище сделано в браузере). Предложили решение. Ok. Где подтверждение, что ваша проблема решена (причем проблема, которую вы даже не описали; все у вас опять к какой-то глупой конспирологии свелось).

В догонку, не понял, зачем вы объявляете асинхронной функцию, которая и так уже будет вызываться асинхронно, раз вы ее в raf передаете:

14 часов назад, Full-R сказал:

void requestAnimationFrame(
  async function interval() {
    // ...
  }
)
14 часов назад, Full-R сказал:

Это все было на тему энергоэффективного программирования.

Остапа понесло.

Link to comment
Share on other sites

  • 0
5 часов назад, Igor Schnaider сказал:

Если вы никуда не присваиваете ссылку на объект, то счетчик ссылок на него и так будет нулевым. Сборщик мусора уничтожит его и без void.

Пруф? Знакомые системные программисты, которые все как один подтверждают мои слова – это не аргумент.

Тогда в чем же заключается ваше исследование? Ну сделали вы предположение, что оно вот так вот работает (хотя тут же пишете, что понятия не имеете, как это говнище сделано в браузере). Предложили решение. Ok. Где подтверждение, что ваша проблема решена (причем проблема, которую вы даже не описали; все у вас опять к какой-то глупой конспирологии свелось).

В догонку, не понял, зачем вы объявляете асинхронной функцию, которая и так уже будет вызываться асинхронно, раз вы ее в raf передаете:

Остапа понесло.

Пойдите на хабр пожалуйста. Так надоели по всему интернету. Сядьте в свое гнездо и там п*зд*т*сь. Не надо вот этих приписок красными буквами.

С вами не о чем разговаривать. Ваши мозги дальше спеки не уходят. 

Link to comment
Share on other sites

  • 0
36 минут назад, Full-R сказал:

С вами не о чем разговаривать. Ваши мозги дальше спеки не уходят. 

Ахахх. Сказал местный сумасшедший))

p.s. Красненьким сарказм подчеркивают, если не знал.

 

upd

Блин, а вы ведь всерьез про энергоэффективное программирование написали. Я то подумал, что это это вы так жирно троллите. Скажите честно, вы Денис Попов?))

p.s. Прошу прощения у @denis_alekss за флуд в его теме.

Link to comment
Share on other sites

  • 0

Скажите, а целесообразно переписать мой код с использованием асинхронных функций? Сейчас начал изучать асинхронные функции читать, скоро создам следующий пост если что будет не ясно, пока не совсем понимаю смысл написания async function и можно ли ее применить к коду моему.

const fib = [1,2,3,5,8,13]
for(var i = 0; i < fib.length; i++){
	(function(j){
	setTimeout(function() {
		console.log(`fib[${j}] = ${fib[j]}`)
	},1500)
	})(i)
}

 

Link to comment
Share on other sites

  • 0
10 часов назад, denis_alekss сказал:

Скажите, а целесообразно переписать мой код с использованием асинхронных функций? Сейчас начал изучать асинхронные функции читать, скоро создам следующий пост если что будет не ясно, пока не совсем понимаю смысл написания async function и можно ли ее применить к коду моему.



const fib = [1,2,3,5,8,13]
for(var i = 0; i < fib.length; i++){
	(function(j){
	setTimeout(function() {
		console.log(`fib[${j}] = ${fib[j]}`)
	},1500)
	})(i)
}

 

Обычно это не требуется. На асинхронных функциях время от времени хорошо создавать promise чтобы избавиться от then функций и оптимизировать код.

Ахахх. Сказал местный сумасшедший))

Дебил.

Edited by Full-R
Link to comment
Share on other sites

  • 0

Как мы можем вызвать функцию r не объявляя ее?
Интересует вторая строка после конст.
 

const delay = function(ms) {
return new Promise(function (r) { setTimeout((function () { r() } ),ms) } )

Вначале создается анонимная функция с параметром r, а в теле этой анонимной функции вызывается функция r внутри функции setTimeout, , откуда взялся вызов функции r? Я ведь ее не объявлял, у меня только был параметр с именем r в анонимной, функции r нигде не объявлена как функция. Я про этот вызов r() в анонимной функции.   
 

<script>
const delay = function(ms) {
    return new Promise(function (r){ setTimeout((function () {r()}),ms)})
}
const url = 'https://jsonplaceholder.typicode.com/todos'

function fetchTodos(){
    console.log('Fetch todo started')
    return delay(2000).then(()=>{
    return fetch(url) }).then(response => response.json())
}

fetchTodos()
.then(data =>{
console.log('Data', data)})
.catch(e=>console.error(e))
</script>

 

Edited by denis_alekss
Link to comment
Share on other sites

  • 0
8 минут назад, denis_alekss сказал:

Как мы можем вызвать функцию r не объявляя ее?
Интересует вторая строка после конст.
 


const delay = function(ms) {
return new Promise(function (r) { setTimeout((function () { r() } ),ms) } )

Вначале создается анонимная функция с параметром r, а в теле этой анонимной функции вызывается функция r внутри функции setTimeout, , откуда взялся вызов функции r? Я ведь ее не объявлял, у меня только был параметр с именем r в анонимной, функции r нигде не объявлена как функция. Я про этот вызов r() в анонимной функции.   
 


<script>
const delay = function(ms) {
    return new Promise(function (r){ setTimeout((function () {r()}),ms)})
}
const url = 'https://jsonplaceholder.typicode.com/todos'

function fetchTodos(){
    console.log('Fetch todo started')
    return delay(2000).then(()=>{
    return fetch(url) }).then(response => response.json())
}

fetchTodos()
.then(data =>{
console.log('Data', data)})
.catch(e=>console.error(e))
</script>

 

Promise - JavaScript | MDN (mozilla.org)

Если не понимаете, то используйте async и await вместо promise и then.

Углубляемся в JavaScript: всё ли может async/await, или когда использовать Promise (tproger.ru)

Link to comment
Share on other sites

  • 0

Спасибо, хорошая ссылка с примерами.

 

Я читал что первый параметр resolve если успешно второй если не успешно rejected. Тут просто используется вроде объекты первого класса тема? Глянем на этот код:

function (r) { setTimeout((function () { r() } )

Я попробовал простой пример который не относится вообще к асинхронным функциям, вот ниже написал, просто этот подход используется в том коде.

((n)=>n)(console.log(5))

Здесь делается похожее. n изначально было просто параметром, а потом превратилось в функцию с именем n.
Перепишем обычным кодом:
 

(function (n) {return n})(console.log(5))

Вызывается сразу функция n которую я даже не объявлял, я объявил просто параметр n в анонимной функции.
Как кстати переписать эти 2 строчки чтобы вызвать отдельно а не сразу после объявления?

Понял, вот так можно через ссылку.

let d = (function (n) {return n})
console.log(d(5))

 

Или сокращенно:

let d = (n=>n)
console.log(d(5))

 

Вернемся к коду.

Не совсем понял вот эту строку:

    return fetch(url) }).then(response => response.json())

Что происходит здесь? fetch это встроенный метод Обещаний в который мы передаем в качестве параметра url а затем в обещание через тот же подход через функцию response вызываем метод json, он вытягивает эту ссылку или что?

 

Link to comment
Share on other sites

  • 0

Аргумент сам по себе не становится функцией. Он и есть функция 🙂

    return fetch(url) }).then(response => response.json())

Then работает для любых функций вообще. Не только для fetch.

Здесь результат fetch(url) превращается в response после ожидания, как аргумент функции, а дальше работает response.json(). 

 

Link to comment
Share on other sites

  • 0

fetch(url) возвращает объект промис, response это объект промис, который мы создаем в then и через него получаем доступ в json() чтобы вытащить этот url и в дальнейшем вывести ссылку https://jsonplaceholder.typicode.com/todos через консоль?

Link to comment
Share on other sites

  • 0
3 часа назад, denis_alekss сказал:

fetch(url) возвращает объект промис, response это объект промис, который мы создаем в then и через него получаем доступ в json() чтобы вытащить этот url и в дальнейшем вывести ссылку https://jsonplaceholder.typicode.com/todos через консоль?

Ни какого промиса ни что ни когда не возвращает, если оно не говнокод. У слабых программистов моцк то маленький, они бы все промисами писали и всю жизнь бы думали что это кто-то возвращает.

Вот  пример fetch без promise(также любой код можно разложить на async и await)

// Modern Fetch future
RR = {

	fetch: async ( u = null, m = 'get', d = 'text', e = null , f = null, preview = null ) => {

		// Configure

		let p = { credentials: 'same-origin', mode: 'same-origin', redirect: 'follow', referrer: 'client', cache: 'default', method: m };

		/*if( [ 'POST', 'PUT' ].includes(m.toUpperCase()) && f ) {

			p.body = (RR.formData) ? RR.formData : d;

		}
		*/

		// Perform

		(async (r, e, d, v, p, u) => {

			// Stage 1
			//RR.screenPosition(.2, 1, true);

			if( r.ok ) {

				let g;

				switch( d ) {

					case 'json':

						g = await r.json();

						break;

					case 'text':

					default:

						g = await r.text();

						break;

				}

				// Stage 2
				//RR.screenPosition(.4, 1, true);

				// Detach all events
				/*if( e ) {

					RR.detachEvents();

				}*/

				// Stage 3
				//RR.screenPosition(.6, 1, true);

				delete RR.formData;

				// Stage 4
				//RR.screenPosition(.8, 1, true);

				/*if( v ) {

					// Stage 5
					//RR.screenPosition(1, 1, true);

					RR.callback(g, v);

				}*/

			}

		})(await fetch( new Request(u, p) ), e, d, f, preview, u);

	},

}

 

Edited by Full-R
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy