JavaScript

Можно ли это замыкание переписать по-другому?

Есть такой код:
function foo() {
for (x = 1; x < 10; x += 1) {
setTimeout(function () {
console.log(x);
}, 10);
}
}
foo();

Он работает некорректно. Чтобы работал корректно, нужно написать так:
function foo_2() {
var f = function (x) {
setTimeout(function () {
console.log(x);
}, 0);
};
for (x = 1; x < 10; x += 1) {
f(x);
}
}
foo_2();

У меня вопрос. А можно ли еще как-нибудь написать, чтобы он работал корректно? Я слышал, что Javascript такой гибкий, что один и тот же код можно написать сотнями разных способов. Я хочу в этом убедиться.
Xavi Hernandes
Xavi Hernandes
54
'Можно' - не значит 'нужно' )
___________

Ну наприимер любой цикл for можно переписать в while:

for( let i = 0; i < 10; i++ ) { ...}



let i = 0;
while( i < 10 ){
  // код...
  i++
}

for в принципе и не нужен, но классно, что он есть)
_________________

Например это тоже будет выводить числа от 0 до 9:

new Array(10).fill(0).map( (e,i) => setTimeout( () => console.log(i), 10 ) );

Но так никто не делает, потому что нефиг писать неочевидный код. Чем легче читать код - тем лучше. А легкочитаемых вариантов решения как правило очень мало (а чаще - один).

P.s. для циклов принято использовать переменную i ...от слова "итерация". Если она занята, j или k.

x - y как правило используют для обозначения координат)
Aлександр Oбуховский
Aлександр Oбуховский
62 360
Лучший ответ
Да, можно. Достаточно добавить в первый вариант твоего кода всего одно слово:

function foo() {
for (let x = 1; x < 10; ++x) {
setTimeout(function () {
console.log(x);
}, 10);
}
}

Подробности: https://learn.javascript.ru/let-const (пункт 3).

P.S. НИКОГДА не используй глобальные переменные в качестве параметров циклов. А твоё for (x = 1; x < 10; x += 1) - это именно использование ГЛОБАЛЬНОЙ переменной x.

P.P.S. JS - это не гибкость а полное отсутствие контроля на поле, густо усеянном граблями.
А какую задачу решает этот код, для чего ты так насилуешь очередь коллбэков?
Решение ведь именно от задачи зависит (нормальные люди не пишут код только для того чтобы написать код... обычно, кодом хотят сделать что-то осмысленное).
Владимир Пудов
Владимир Пудов
58 203
как вариант без let или когда значение нужно после цикла

function foo() {
let x;
for (x = 1; x < 10; x ++) { ((i) => { setTimeout(() => { console.log(i); }, 10); }).call(null, x); }
}

это ваш второй пример но компактный (мы не храним и сразу вызываем после создания)

вся соль в том что мы создаем второе замыкание в котором есть переменная-аргумент которую и юзает таймер (это если очень общо), а при передаче аргументов значения в них КОПИРУЮТСЯ если это не объект