Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 17.11.2022, 23:31
Интересующийся
Отправить личное сообщение для logicaface Посмотреть профиль Найти все сообщения от logicaface
 
Регистрация: 17.11.2022
Сообщений: 11

Трагедия новичка: вынос переменных за циклы изменяет работу программы.
Всем привет. Я решил научиться в JS и стал проходить уроки по книге с этого сайта. Никаких проблем у меня не было и все шло хорошо до тех пор пока я не дошел до урока о выводе простых чисел из 88 страницы Современного учебника. Сам я совершенно не допетрил до того как по простому сделать эту штуку и посмотрел принцип решения. Решил сделать это не на циклах for а на циклах while. Итог: засел я на 2 часа и в конце концов впал в пучину отчаяния.

Однако, как мудрый и терпеливый воин, я не стал сразу забрасывать это дело, но начал по всякому пытаться понять - почему у меня не получается. Я насиловал себя и бедный JS: вставлял alert'ы для проверки переменных в начало и конец внешнего цикла, вставлял и во внутренний цикл вместо конструкции из if и continue. Это я делал для того, чтобы проверить тот факт, что первая переменная (i) всегда опережает внутреннюю (j) после первой интерации и цикл работает в таком темпе до самого конца.

Эта битва шла долго, но ничего не работало как надо. В конце концов я решил вынести переменные из примера учебника за циклы и обнаружил что тогда все тоже перестает работать. Я был поражен. Я перестал понимать почему так происходит. Я... Отчаялся... Но друзья, объясните мне пожалуйста почему так происходит и что мне нужно почитать и выучить чтобы хорошенько это понять и осознать. Я не хочу оставаться тупым, поверженным долу и втоптанным в землю воином сим элементарным книжным примером.

Прошу вас сенъёры фронт-энда: помогите. Объясните доходчиво чем отличается правильная работа скрипта и как ведут себя в нем переменные от того, что сделал я. И можно ли мой вариант через while привести к рабочему виду. Примеры кода ниже:

Рабочий пример из учебника:
let n = 10;
nextPrime: for (let i = 2; i <= n; i++) {
for (let j = 2; j < i; j++) {
if (i % j == 0) continue nextPrime;
}
alert(i);
}


Вот что сделал я (переменные ++i и ++j я тоже пытался размещать в разных местах):
let i = 2;
let j = 2;
butthurt: while (i <= 10) {
while (j < i) {
if (i % j == 0) continue butthurt;
++j;
}
alert(i);
++i;
}


Как я изменил пример из учебника, после чего он тоже перестал работать.
let n = 10;
let i = 2;
let j = 2
nextPrime: for (; i <= n; i++) {
for (; j < i; j++) {
if (i % j == 0) continue nextPrime;
}
alert(i);
}
Ответить с цитированием
  #2 (permalink)  
Старый 17.11.2022, 23:39
Интересующийся
Отправить личное сообщение для logicaface Посмотреть профиль Найти все сообщения от logicaface
 
Регистрация: 17.11.2022
Сообщений: 11

И еще забыл написать: мне кажется, что неправильный цикл работает не так как правильный в том смысле, что внутренний цикл почему-то увеличивается попеременно со внешним и не прогоняется весь от 2 до 7 например когда значение i = 7 (то есть на 7 интерации внешнего цикла внутренний сразу начинает от 6 или 7 а не от 2-х). Но я не понимаю почему так происходит.

Последний раз редактировалось logicaface, 17.11.2022 в 23:42.
Ответить с цитированием
  #3 (permalink)  
Старый 18.11.2022, 00:55
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,068

logicaface,
j никогда не уменьшается!!! а значит второй цикл не работает, как нужно.
Ответить с цитированием
  #4 (permalink)  
Старый 18.11.2022, 04:46
Аватар для Белый шум
Профессор
Отправить личное сообщение для Белый шум Посмотреть профиль Найти все сообщения от Белый шум
 
Регистрация: 19.01.2012
Сообщений: 498

Сообщение от рони Посмотреть сообщение
logicaface,
j никогда не уменьшается!!! а значит второй цикл не работает, как нужно.
И ещё i не увеличивается в случае, когда во внутреннем цикле происходит переход в начало по continue, что приводит к бесконечному циклу:

var i = 2;
butthurt: while (i <= 10) {
*!*
    var j = 2;
*/!*
    while (j < i) {
        if (i % j == 0) {
*!*
            ++i;
*/!*
            continue butthurt;
        }
        ++j;
    }
alert(i);
++i;
}

Последний раз редактировалось Белый шум, 19.11.2022 в 13:01.
Ответить с цитированием
  #5 (permalink)  
Старый 18.11.2022, 07:51
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,701

Сообщение от logicaface
Я насиловал себя и бедный JS: вставлял alert'ы для проверки переменных
Не понимаю, почему на всяких курсах насилуют учащихся алертами, вместо того, что бы в первую очередь научить пользоваться средствами разработчика вообще и отладчиком в частности, которые есть в любом браузере.
Ответить с цитированием
  #6 (permalink)  
Старый 18.11.2022, 10:07
Интересующийся
Отправить личное сообщение для logicaface Посмотреть профиль Найти все сообщения от logicaface
 
Регистрация: 17.11.2022
Сообщений: 11

Спасибо вам большое за помощь. А можете еще, если не трудно объяснить почему пример из учебника перестал работать когда я вынес объявления переменных за циклы? В чем принципиальная разница между этим:
let n = 10;
nextPrime: for (let i = 2; i <= n; i++) {
for (let j = 2; j < i; j++) {
if (i % j == 0) continue nextPrime;
}
alert(i);
}

И между этим. И почему первое работает а второе нет.
let n = 10;
let i = 2;
let j = 2;
nextPrime: for (; i <= n; i++) {
for (; j < i; j++) {
if (i % j == 0) continue nextPrime;
}
alert(i);
}
Ответить с цитированием
  #7 (permalink)  
Старый 18.11.2022, 10:30
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,701

Сообщение от logicaface
почему пример из учебника перестал работать когда я вынес объявления переменных за циклы
continue nextPrime передает управление на увеличение i. на i++. Но к началу работы второго цикла не присваивается j = 2;

ЗЫ А зачем их выносить надо было.
Цикл for в js не так прост. Его совсем непросто проимитировать другими средствами в общем случае.
Ответить с цитированием
  #8 (permalink)  
Старый 18.11.2022, 10:37
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,121

logicaface, я х/з чего ты мутишь...
Но в первом варианте j всегда "начинается" с 2... А в твоем варианте она не "сбрасывается", всегда увеличивается на +1.

Аналог правильного будет
let n = 10;
let i = 2;
nextPrime: for (; i <= n; i++) {
	console.log('i', i)
	let j = 2;
	for (; j < i; j++) {
		console.log('j', j)
		if (i % j == 0) continue nextPrime;
	}
	console.log('end', i);
}


P.S.
Всегда удивлялся как могут намутить кода некоторые товарищи...
Ответить с цитированием
  #9 (permalink)  
Старый 18.11.2022, 10:46
Интересующийся
Отправить личное сообщение для logicaface Посмотреть профиль Найти все сообщения от logicaface
 
Регистрация: 17.11.2022
Сообщений: 11

ksa, а i в первом варианте (рабочем) не всегда начинается с 2 с каждым новым включением continue? Там же тоже (внутри первого for стоит i = 2), значит когда continue скидывает интерацию из внутреннего цикла на внешний, то i тоже должно сбрасываться, или нет?) Я, походу, просто совсем не правильно понял как работают циклы...)))
Ответить с цитированием
  #10 (permalink)  
Старый 18.11.2022, 10:50
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,701

continue передает управление на изменение переменной, а не на сброс.

Если бы в js был оператор goto, то цикл
for (i=0; i<n; i++) {
 /*тело*/
 }

можно было бы расписать так
i = 0;
 goto LC;
 LI: 
	i++;
 LC: 
	if (i<n) goto LB;
	goto LE;
 
 LB: 
 {
 //тело
 }
 goto LI;
 
 LE:

Последний раз редактировалось voraa, 18.11.2022 в 11:00.
Ответить с цитированием
Ответ



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

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