Выражения и инструкции
Транскрипт урока
Взгляните на эту простую строчку кода:

const x = 5;
Вы точно знаете, что в ней происходит, верно? Создадим новую константу x, зададим ей значение 5. Ничего особенного тут нет.

Вот другая строчка кода:

const y = getAnswer();
Создадим новую константу y, зададим ей то значение, которое возвращает функция getAnswer. Теперь представьте, что getAnswer — это на самом деле невероятно сложная функция с миллионом строчек кода и потребуется 12 лет для её вычисления.

Насколько отличаются эти строчки? Оказывается, в информатике более важный и полезный вопрос: "насколько они схожи?".

И ответ, конечно — "всё относительно".

Если вы рассуждаете о том, что действительно, буквально, происходит — они вообще не похожи друг на друга. Одна устанавливает числовое значение, другая вызывает какую-то функцию. А мы уже хорошо понимаем, что это разные вещи. Мы знакомы с функциями, аргументами и всем, что связано с функциями.

Но иногда полезно оперировать другими понятиями, на другом уровне. Конечно, бегать и управлять самолётом — это очень разные виды активности, но на определённом уровне они подобны — и та и другая подразумевают передвижение из одной точки в другую.

Эти две строчки подобны, потому что справа от знака равно в обоих случаях находится выражение. Выражение — это фрагмент кода, который превращается в значение. Другими словами — становится значением. Да, знаю, 5 — это уже значение, но для интерпретатора JavaScript это выражение, которое превращается в значение 5. Другое выражение, которое превращается в значение 5 — это, например, 2 + 3.

Вызов функции getAnswer() — это тоже выражение, потому что функция что-то возвращает. Этот вызов будет заменён на значение, которое она возвращает. Другими словами, вызов функции превратится в значение, а поэтому он является выражением.

Не всё в коде становится значением. Так что не всё в коде — это выражение, хотя большая часть его — именно выражения.

JavaScript различает выражения и инструкции. Инструкция — это команда, действие. Помните условие с if, циклы с while и for — всё это — инструкции, потому что они только производят и контролируют действия, но не становятся значениями.

Это что, какие-то мутные технические термины из учебников? Может так показаться, но в реальности очень важно понимать и видеть разницу между выражениями и инструкциями.

Это помогает правильно понимать процесс вычисления и выполнения программы. Посмотрите на пример:

12 + square(7 + 5) + square(square(2));
Это выражение состоит из нескольких подвыражений.
Первое — 12 — выражается в 12. Следующее состоит из множества подвыражений:
  • 7 выражается в 7
  • 5 выражается в 5
  • 7 + 5 выражается в 12
  • square(12) выражается в 144
К этому моменту в процессе JavaScript видит такую картинку:

12 + 144 + square(square(2));
Это еще не конец, остались необработанные выражения. Это будет продолжаться пока всё выражение не превратится в единое значение.
square(square(2)) решается таким способом:

  • 2 выражается в 2
  • square(2) выражается в 4
  • square(4) выражается в 16
Давайте заглянем в мозг интерпретатора снова:

12 + 144 + 16;
Все внутренние выражения решены, так что теперь сложение происходит в два шага:

12 + 144 + 16;
156 + 16;
172;
Теперь решено всё выражение.

Кстати, оператор сложения имеет левую ассоциативность. Это значит, что в случае с составными сложениями процесс пойдёт слева направо, вот почему мы вначале видим 12 + 144, а потом 156 + 16.

Вы не можете ставить инструкции там, где должны быть выражения. Например, передача инструкции const как аргумента функции приведёт к ошибке. Как и попытка присвоить инструкцию if переменной. Подобное просто не имеет смысла в этом языке, потому что в таких случаях предполагаются только выражения:

console.log(const x);   // error!
let b = if (x > 10) { return 100; };    // error!
Зная такие вещи, вы скоро обретёте две важные суперспособности:
  1. Вы будете способны замечать, что большая часть кода, даже та функция из миллиона строк на двенадцать лет, это просто горсть безделушек, которые становятся значениями.
  2. Вы будете способны замечать, что иногда код просто не будет работать, потому что он не имеет смысла в контексте выражений и инструкций.
Выводы
Выражением (expression) является любой корректный блок кода, который возвращает значение.

Ниже 5 это expression, оно выражается в значение 5:

const x = 5;
Ниже getAnswer() — это вызов функции — другое выражение. Этот вызов возвращает значение, то есть этот вызов функции выразится в значение:

const y = getAnswer();
Ниже пример выражения, которое состоит из нескольких подвыражений, и пошаговый процесс превращения каждого выражения по порядку, пока целое выражение не превратится в одно значение:

12 + square(7 + 5) + square(square(2));

12 + square(12) + square(square(2));
12 + 144 + square(square(2));
12 + 144 + square(4);
12 + 144 + 16;
156 + 16;
172;
JavaScript различает выражения (expressions) и инструкции (statements). Инструкция — это (грубо говоря) команда, действие.

if, while, for, const — примеры инструкций. Они производят или контролируют действия, но не превращаются в значения.
Дополнительные материалы
Тесты
Пройти тест
Может ли программа содержать несколько функций? (доверьтесь своим инстинктам ;)
Верно!
Неверно
Дальше
Проверить
Завершить тест
Могут ли функции возвращать строки (тексты), или они могут возвращать исключительно числа?
Верно!
Неверно
Неверно
Дальше
Проверить
Завершить тест
Дан такой код:

const height = findHeight();

Какое значение будет "записано" в константу height после выполнения?

Верно!
Неверно
Неверно
Дальше
Проверить
Завершить тест
Дан такой код:

const someFunction = (x) => {
  return 10 * 42;
};


const y = someFunction(9281);

Что будет "сохранено" в константе y после выполнения?
Неверно
Верно!
Неверно
Дальше
Проверить
Завершить тест
Каким будет результат вызова функции?

 const firstNum = 10;
 const secondNum = 5;


 const sum = (z, g) => z + g;


 sum(firstNum, secondNum);
Верно!
Неверно! Попробуйте еще раз
Неверно! Попробуйте еще раз
Дальше
Проверить
Завершить тест
Дана такая функция:

const sum = (a, b, c) => {
  return a + b + c;
};

Можно ли в этой ситуации использовать сокращенный синтаксис записи функции?
Неверно
Верно!
Дальше
Проверить
Завершить тест
Пройти еще раз
Пройти еще раз
Пройти еще раз
Пройти еще раз
Упражнение
  • Реализуйте функцию square(), которая возвращает квадрат числа.
  • Реализуйте функцию sumOfSquares(), которая возвращает сумму квадратов двух чисел.
  • Реализуйте функцию squareSumOfSquares(), которая возвращает квадрат суммы квадратов двух чисел.
Примеры работы функций:

square(5); // 25
square(10); // 100
sumOfSquares(5, 10); // 125
sumOfSquares(10, -9); // 181
squareSumOfSquares(1, 1); // 4
squareSumOfSquares(2, 3); // 169
Подсказки
  • Функция square() может быть использована внутри sumOfSquares()
  • Функция sumOfSquares() может быть использована внутри squareSumOfSquares()