JavaScript Инкремент

246
16 февраля 2017, 00:26

Изучаю JavaScript. В учебнике сказано:

i++; // более короткая запись для i = i + 1

Более короткая запись, как я понимаю делается для следующего:

оптимизировать(сократить) код и сделать его понятнее; логично, что более короткая равна полной.

Но я столкнулся с простым примером(в будущем назовем его Пример№1):

i = 0; 
while (i++ < 5) { 
  alert(i); 
}

И решил записать его, в не сокращенном виде (ведь они равны). У меня не получилось:

i = 0; 
while ((i = i + 1) < 5) { 
  alert(i); 
}

Из-за скобок приоритет меняется (с пятеркой сравнение идет уже после +1) и последний алерт выдает четверку. Удивительно, что я не могу сделать полную запись, там где сделал сокращенную.

  • Я хочу получить результат, как в Пример№1, но при этом сделать запись не сокращенную, а полную (т.е.(i = i + 1))
  • Постфиксная форма и префиксная форма, мне о них известно, они здесь роли не играют на мой взгляд. Если это важно вам кажется используйте их в своем объяснении.
  • Такой вариант:

i = 0; 
 
while (i < 5) { 
  i = i + 1; 
  alert(i); 
}

меня также не устраивает, нужно чтобы полная запись была в скобках у while, как и сокращенная.

Мой вопрос:

Объясните мне как это работает. ! Нужно использовать цикл while как в моем примере, если записи равны, у вас не составит труда так записать. Ваше объяснение желательно пусть сводиться к следующему:

  1. i++; // более короткая запись для i = i + 1 Это неправда, записи не равны и ...
  2. i++; // более короткая запись для i = i + 1 Записи равны и ваш код(выше читаем какой результат я хочу получить) ...

PS Это не дубликат вопроса, пишу т.к. очередной пользователь ru.stackoverflow, пометил данный вопрос "как возможный дубликат". Данный вопрос хорошо оформлен и четко поставлен, были даны подробные ответы. Если в данном вопросе вы находите что-то знакомое и близкое, это не означает, что он становится дубликатом. Лучше прочитать вопрос еще раз, прочитать и комментарии к нему, а не писать ссылку на тему, которая уже здесь несколько раз поднималась. Данный вопрос отражает стремление разобраться, он понятен и несет пользу(автору уж точно).

Answer 1

В данном случае имеет место неверное интерпретирование того, что написано в учебнике.

i++; // более короткая запись для i = i + 1

Обрати внимание на ; в этой записи.

Действительно, строка

i++;

может быть безболезненно заменена на

i = i + 1;

Особенность постинкремента в том, что данный оператор возвращает значение до увеличения. И, так как в строке i++; это значение нигде не используется, указанные выше записи становятся эквивалентны.

Если же возвращаемое значение используется, как в случае в вопросе, то здесь подойдет ответ @good_web_master наглядно демонстрирующий эквивалентные выражения:

a=i++ => a=i
         i=i+1

Как видно, для полной эмуляции короткой записи, необходимо где-то сохранять значение перед увеличением, это может быть:

  1. сторонняя переменная

    var i = 0, 
      a; 
     
    while ((a = i, i = i + 1, a) < 5) { 
      console.log(i); 
    } 
     
      

    В данном случае помогает оператор Запятая (,) позволяя вернуть значение a для сравнения в условии.

  2. непосредственно создаваемые структуры:

    1. объект

      var i = 0; 
       
      while ({pred:i, curr: i = i + 1}.pred < 5) { 
        console.log(i); 
      }

    2. либо массив

      var i = 0; 
       
      while ([i, i = i + 1][0] < 5) { 
        console.log(i); 
      }

Answer 2

"они здесь роли не играют" - как раз играют:

i++ - возвращает значение до инкремента, a

i = i + 1 - после.

var i = 0; 
// здесь с единицей сравнивается значение i до инкремента - то есть 0 
if (i++ < 1) { 
  console.log("i - check " + i); 
} 
 
var j = 0; 
// здесь с единицей сравнивается значение j после инкремента - то есть 1 
if ((j = j + 1) < 1) { 
} else { 
  console.log("j - no check " + j); 
} 
 
// однако: 
var k = 0; 
// здесь с единицей сравнивается значение k после инкремента - то есть 1 
if (++k < 1) { 
} else { 
  console.log("k - no check " + k); 
}

печатание цикла while в свете приобретенных знаний оставлено автору вопроса в качестве упражения

Answer 3
var i = 2;
i++;      // более короткая запись для i = i + 1.
alert(i); // 3

Именно в такой форме, не в качестве выражения, это и есть более короткая запись, потому что делает ровным счётом то же самое - увеличивает значение переменной i на единицу.

В чём же разница?
В возвращаемом значении.
Выражение i++ возвращает значение переменной i до увеличения.
Выражение (i=i+1)(как и ++i) возвращает значение переменной i после увеличения.

Существует множество способов привести второе выражение к первому, например:

  • Сохранить первоначальное значение: (temp = i, i = i + 1, temp)
  • Рассчитать первоначальное значение: (i = i + 1) - 1

{ // Вариант с сохранением значения 
  let i = 0, temp; 
  while (temp = i, i = i + 1, temp < 5) console.log(i); 
} 
 
{ // Вариант с восстановлением значения 
  let i = 0; 
  while ((i = i + 1) - 1 < 5) console.log(i); 
} 
 
// Можно также произвести некоторые математические операции для упрощения 
{ // Увеличим обе части неравенства на 1 
  let i = 0; 
  while ((i = i + 1) < 6) console.log(i); 
} 
{ // За счёт нестрогого неравенства можно сохранить первоначальную константу 
  let i = 0; 
  while ((i = i + 1) <= 5) console.log(i); 
}

READ ALSO
JavaScript | Прототипирование, застрял немножко

JavaScript | Прототипирование, застрял немножко

Написал такую штуку: Вопросы собственно в коде

286
Как в React.js клонировать элемент?

Как в React.js клонировать элемент?

Как в Reactjs клонировать элемент? В голову приходит:

368
Node/ES6 import. Uncaught SyntaxError: Unexpected token import при запуске приложения

Node/ES6 import. Uncaught SyntaxError: Unexpected token import при запуске приложения

Решил использовать react-scrollbar для кастомизации скроллбаров на сайтеВ мануале по использованию, указывается нодовский импорт модуля

934
PHP-скрипт возвращает состояние rejected в fail()

PHP-скрипт возвращает состояние rejected в fail()

Отправляю ajax-запрос к php-файлу:

356