HTML Diff
1 added 1 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Вспомним несколько важных понятий из прошлого курса:</p>
1 <p>Вспомним несколько важных понятий из прошлого курса:</p>
2 <p>Выражение - код, выполнение которого возвращает значение. Инструкция - код, представляющий собой команду.</p>
2 <p>Выражение - код, выполнение которого возвращает значение. Инструкция - код, представляющий собой команду.</p>
3 <ul><li>Выражения - вычисляются.</li>
3 <ul><li>Выражения - вычисляются.</li>
4 <li>Инструкции - исполняются.</li>
4 <li>Инструкции - исполняются.</li>
5 </ul><p>К выражениям относятся:</p>
5 </ul><p>К выражениям относятся:</p>
6 <ul><li>Вызов функции</li>
6 <ul><li>Вызов функции</li>
7 <li>Арифметические и логические операции</li>
7 <li>Арифметические и логические операции</li>
8 <li>Тернарный оператор</li>
8 <li>Тернарный оператор</li>
9 <li>и другие</li>
9 <li>и другие</li>
10 </ul><p>К инструкциям относятся:</p>
10 </ul><p>К инструкциям относятся:</p>
11 <ul><li>for</li>
11 <ul><li>for</li>
12 <li>while</li>
12 <li>while</li>
13 <li>break</li>
13 <li>break</li>
14 <li>return</li>
14 <li>return</li>
15 <li>if</li>
15 <li>if</li>
16 <li>и другие</li>
16 <li>и другие</li>
17 </ul><p>Список выражений и инструкций на этом не заканчивается, с полным перечнем можно ознакомиться в документации (см. дополнительные материалы к уроку).</p>
17 </ul><p>Список выражений и инструкций на этом не заканчивается, с полным перечнем можно ознакомиться в документации (см. дополнительные материалы к уроку).</p>
18 <p>Для лучшего понимания, как могут взаимодействовать друг с другом различные конструкции языка, необходимо знать разницу между ними.</p>
18 <p>Для лучшего понимания, как могут взаимодействовать друг с другом различные конструкции языка, необходимо знать разницу между ними.</p>
19 - <p>Возьмем условный оператор if. В некоторых языках он представлен инструкцией, в неоторых - выражением. Посмотрите на код ниже и подумайте, возможно ли такое в JavaScript и почему:</p>
19 + <p>Возьмем условный оператор if. В некоторых языках он представлен инструкцией, в некоторых - выражением. Посмотрите на код ниже и подумайте, возможно ли такое в JavaScript и почему:</p>
20 <p>Такой код в JavaScript невозможен только по одной простой причине: if -<strong>это инструкция, а не выражение</strong>.</p>
20 <p>Такой код в JavaScript невозможен только по одной простой причине: if -<strong>это инструкция, а не выражение</strong>.</p>
21 <p>Но такой код возможен и часто используется в языках вроде Ruby или Python. Зачем же нужен if, если есть тернарный оператор, который как раз и является выражением?</p>
21 <p>Но такой код возможен и часто используется в языках вроде Ruby или Python. Зачем же нужен if, если есть тернарный оператор, который как раз и является выражением?</p>
22 <p>Дело вот в чем. Если бы if был выражением, то тернарный оператор стал бы попросту не нужен, несмотря на то, что он является более лаконичной заменой if. Но и тернарный оператор бывает неудобен в тех ситуациях, когда вычисление слишком большое и не помещается в одну строку, а его результат должен быть записан в одну и ту же константу или переменную в каждой из веток. В такой ситуации как раз пригодился бы if как выражение.</p>
22 <p>Дело вот в чем. Если бы if был выражением, то тернарный оператор стал бы попросту не нужен, несмотря на то, что он является более лаконичной заменой if. Но и тернарный оператор бывает неудобен в тех ситуациях, когда вычисление слишком большое и не помещается в одну строку, а его результат должен быть записан в одну и ту же константу или переменную в каждой из веток. В такой ситуации как раз пригодился бы if как выражение.</p>
23 <p>Этот пример ярко иллюстрирует тот факт, что конструкции языка, представленные выражением, делают язык гибче, а решения с их использованием делают код лаконичнее. Другими словами, язык становится<em>выразительнее</em>. Кроме описанного выше, у выражений есть еще одно огромное преимущество: они могут комбинироваться друг с другом и вкладываться друг в друга.</p>
23 <p>Этот пример ярко иллюстрирует тот факт, что конструкции языка, представленные выражением, делают язык гибче, а решения с их использованием делают код лаконичнее. Другими словами, язык становится<em>выразительнее</em>. Кроме описанного выше, у выражений есть еще одно огромное преимущество: они могут комбинироваться друг с другом и вкладываться друг в друга.</p>
24 <p>Ниже рассмотрим варианты комбинирования выражений, но с акцентом на функции:</p>
24 <p>Ниже рассмотрим варианты комбинирования выражений, но с акцентом на функции:</p>
25 <h2>Арифметические операции</h2>
25 <h2>Арифметические операции</h2>
26 <p>На последней строке может возникнуть вопрос: насколько допустимо складывать результаты функций? Вызов функции - это выражение, возвращающее результат, так что этот код допустим на 100%. Если функция вернет значение, неподходящее для сложения, то может возникнуть ошибка, но это будет логическая ошибка, а не синтаксическая.</p>
26 <p>На последней строке может возникнуть вопрос: насколько допустимо складывать результаты функций? Вызов функции - это выражение, возвращающее результат, так что этот код допустим на 100%. Если функция вернет значение, неподходящее для сложения, то может возникнуть ошибка, но это будет логическая ошибка, а не синтаксическая.</p>
27 <p><em>Примечание: предполагается, что используемые в примерах этого урока функции и константы (например, f2 или isEditing) ранее где-то были определены. Их определение мы убрали из примеров, чтобы не отвлекать от главного.</em></p>
27 <p><em>Примечание: предполагается, что используемые в примерах этого урока функции и константы (например, f2 или isEditing) ранее где-то были определены. Их определение мы убрали из примеров, чтобы не отвлекать от главного.</em></p>
28 <h2>Логические операции</h2>
28 <h2>Логические операции</h2>
29 <p>Все то же самое можно делать и с логическими выражениями:</p>
29 <p>Все то же самое можно делать и с логическими выражениями:</p>
30 <p>Из-за слабой типизации подобный код работать будет вообще всегда, даже если функции возвращают не true или false, но пользоваться этим не стоит. (Типизация рассматривалась в<a>уроке предыдущего курса</a>).</p>
30 <p>Из-за слабой типизации подобный код работать будет вообще всегда, даже если функции возвращают не true или false, но пользоваться этим не стоит. (Типизация рассматривалась в<a>уроке предыдущего курса</a>).</p>
31 <h2>Аргументы</h2>
31 <h2>Аргументы</h2>
32 <p>А теперь чуть более сложный пример. Когда мы вызываем функцию, то в аргументах ожидается выражение: func(&lt;expression&gt;, &lt;expression&gt;, ...). А из этого следует, что мы можем сделать так:</p>
32 <p>А теперь чуть более сложный пример. Когда мы вызываем функцию, то в аргументах ожидается выражение: func(&lt;expression&gt;, &lt;expression&gt;, ...). А из этого следует, что мы можем сделать так:</p>
33 <p>Если последний вызов вам кажется сложным, то вспомните вот что. Когда мы изучали русский язык в школе, то постоянно делали грамматический разбор предложения, в котором выделяли существительное, подлежащее, сказуемое, различные обороты и многое другое. Здесь нужно сделать то же самое. Очень важно уметь разбивать в уме сложное выражение на составные.</p>
33 <p>Если последний вызов вам кажется сложным, то вспомните вот что. Когда мы изучали русский язык в школе, то постоянно делали грамматический разбор предложения, в котором выделяли существительное, подлежащее, сказуемое, различные обороты и многое другое. Здесь нужно сделать то же самое. Очень важно уметь разбивать в уме сложное выражение на составные.</p>
34 <p>Пройдемся по примеру выше. f(f1(f2(n3, f3(n1, n2))), f4()) содержит в аргументах два выражения:</p>
34 <p>Пройдемся по примеру выше. f(f1(f2(n3, f3(n1, n2))), f4()) содержит в аргументах два выражения:</p>
35 <ol><li>f4()</li>
35 <ol><li>f4()</li>
36 <li>f1(f2(n3, f3(n1, n2))) - этот вызов содержит один аргумент - вызов функции: f2(n3, f3(n1, n2)), - который в свою очередь содержит два аргумента: n3 и вызов функции f3(n1, n2).</li>
36 <li>f1(f2(n3, f3(n1, n2))) - этот вызов содержит один аргумент - вызов функции: f2(n3, f3(n1, n2)), - который в свою очередь содержит два аргумента: n3 и вызов функции f3(n1, n2).</li>
37 </ol><h2>Порядок выполнения</h2>
37 </ol><h2>Порядок выполнения</h2>
38 <p>Осталось понять, в какой последовательности происходят эти вызовы. JavaScript считается энергичным языком, то есть языком с аппликативным порядком вычисления, а это значит, что аргументы вычисляются до того, как попадают внутрь функций.</p>
38 <p>Осталось понять, в какой последовательности происходят эти вызовы. JavaScript считается энергичным языком, то есть языком с аппликативным порядком вычисления, а это значит, что аргументы вычисляются до того, как попадают внутрь функций.</p>
39 <p>Как видно, вычисление идет с самого глубокого уровня слева направо. Каждая функция попадает в стек вызовов, где работает принцип "первым вошел - последним вышел". Поскольку каждый аргумент - тоже функция, то они также добавляются за ней следом. Те функции, которые возвращают результат, сразу вычисляются. Так получается, что стек наполняется и очищается до тех пор, пока не выполнится f1.</p>
39 <p>Как видно, вычисление идет с самого глубокого уровня слева направо. Каждая функция попадает в стек вызовов, где работает принцип "первым вошел - последним вышел". Поскольку каждый аргумент - тоже функция, то они также добавляются за ней следом. Те функции, которые возвращают результат, сразу вычисляются. Так получается, что стек наполняется и очищается до тех пор, пока не выполнится f1.</p>