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(<expression>, <expression>, ...). А из этого следует, что мы можем сделать так:</p>
32
<p>А теперь чуть более сложный пример. Когда мы вызываем функцию, то в аргументах ожидается выражение: func(<expression>, <expression>, ...). А из этого следует, что мы можем сделать так:</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>