Порядок вычислений
В прошлом уроке мы написали функцию add и вызывали её по одному разу в строке. Но в одной строке может встретиться сразу несколько знаков действий и вызовов. Тогда важно знать, в каком порядке JavaScript их выполняет.
Вернёмся к кулинарной книге. Шаг «полейте рыбу соусом» нельзя выполнить сразу: повар открывает страницу соуса, готовит его и только потом возвращается к рыбе. Внешний шаг ждёт, пока закончится внутренний.
Давайте посмотрим на программу, где в каждой строке несколько действий:
function add(a, b) {
return a + b;
}
console.log(1 + 2 * 3); // 7
console.log((1 + 2) * 3); // 9
console.log(10 - 4 - 3); // 3
console.log(add(add(1, 2), 3)); // 6
console.log(add(2 * 3, 1)); // 7Первые три строки подчиняются правилам знаков действий, а последние две — правилу вызова: сначала вычисляются аргументы, потом сам вызов. Разберём оба правила.
Знаки действий
С числами работают знаки +, - и *. Порядок задают три правила:
- как в математике,
*выполняется раньше+и-; - знаки одного уровня, например
+и-, выполняются по очереди слева направо; - скобки меняют этот порядок.
По этим правилам JavaScript считает первые три строки примера так:
1 + 2 * 3: сначала2 * 3, и1 + 6даёт7.(1 + 2) * 3: скобки заставляют сначала сложить1 + 2, и3 * 3даёт9.10 - 4 - 3: вычитания идут слева направо, поэтому сначала10 - 4даёт6, а затем6 - 3даёт3.
Если сомневаетесь в порядке, поставьте скобки. Скобки вокруг того, что и так выполнилось бы первым, результат не меняют: 1 + (2 * 3) тоже даёт 7.
Вложенные вызовы
Вызов можно передать в другой вызов как аргумент. Такую запись называют вложенным вызовом: сначала выполняется внутренний вызов, и его результат становится аргументом внешнего. Как с соусом: внешний add не начнёт работу, пока внутренний не вернёт готовое число.
Нажмите «Следующий шаг» и следите, как выполнение уходит в add и возвращается с готовым числом. Обратите внимание: внутренний вызов заканчивается раньше внешнего.
1function add(a, b) {2 return a + b;3}4 5console.log(add(2, 3));6console.log(add(add(1, 2), 3));
Строки 1–3 только объявляют add, поэтому выполнение начинается с вызова add(2, 3).
Последние две строки первого примера выполняются так:
add(1, 2)возвращает3, затемadd(3, 3)возвращает6.- Аргумент тоже может быть вычислением: сначала вычисляется
2 * 3, то есть6, и функция получает числа6и1.
У картинки с соусом есть предел. Повар может сварить соус заранее, ещё утром. У JavaScript такого выбора нет: аргументы вычисляются по очереди, слева направо, прямо перед вызовом. Например, в add(add(1, 2), add(3, 4)) сначала add(1, 2) даёт 3, затем add(3, 4) даёт 7, и только потом внешний add(3, 7) возвращает 10.
На собеседовании новичкам часто показывают строку с вызовом внутри вызова и спрашивают, что она напечатает. Найдите самый внутренний вызов и считайте изнутри наружу.
Частая ошибка
Функция должна сложить два числа и удвоить сумму, но скобки забыли:
function doubleSum(a, b) {
return a + b * 2; // ✗
}
console.log(doubleSum(2, 3)); // 8Сообщения об ошибке нет, но вместо 10 программа печатает 8: * выполнилось раньше +, и удвоилось только b. Исправление — взять сумму в скобки: return (a + b) * 2;.
Главное
*выполняется раньше+и-, знаки одного уровня идут слева направо, а скобки меняют порядок.- Сначала вычисляются аргументы, потом выполняется сам вызов.
- Во вложенном вызове внутренний вызов заканчивается раньше внешнего, и его результат становится аргументом.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.