0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<h2>Транскрипт урока</h2>
1
<h2>Транскрипт урока</h2>
2
<p>В одном из прошлых уроков мы говорили об ошибках и как с ними справляться. Есть несколько видов ошибок, и я хочу напомнить об одном конкретном виде. Вот небольшой фрагмент того урока:</p>
2
<p>В одном из прошлых уроков мы говорили об ошибках и как с ними справляться. Есть несколько видов ошибок, и я хочу напомнить об одном конкретном виде. Вот небольшой фрагмент того урока:</p>
3
<p>Взгляните на этот код:</p>
3
<p>Взгляните на этот код:</p>
4
<p>Сначала мы создали константу. Помните, что это как давать чему-то название: в нашем случае - числу 12 даётся название length. В следующей строке мы вызываем функцию length и передаём ей аргумент - число 54. Но подождите! length - это не функция! Это всего лишь число. Числа - это не функции, не ящики, которые производят какие-то действия. И JavaScript пожалуется именно на это:</p>
4
<p>Сначала мы создали константу. Помните, что это как давать чему-то название: в нашем случае - числу 12 даётся название length. В следующей строке мы вызываем функцию length и передаём ей аргумент - число 54. Но подождите! length - это не функция! Это всего лишь число. Числа - это не функции, не ящики, которые производят какие-то действия. И JavaScript пожалуется именно на это:</p>
5
<p>Это<strong>Ошибка типизации</strong>: тип объекта, который вы использовали, неверный. Интерпретатор JavaScript не скажет<strong>чем что-то является</strong>, но точно скажет<strong>чем оно не является</strong>. length - это не функция.</p>
5
<p>Это<strong>Ошибка типизации</strong>: тип объекта, который вы использовали, неверный. Интерпретатор JavaScript не скажет<strong>чем что-то является</strong>, но точно скажет<strong>чем оно не является</strong>. length - это не функция.</p>
6
<blockquote><p>Ошибка типизации - это как просить кошку постирать бельё. Возможно, вы хотели попросить об этом вашего друга.</p>
6
<blockquote><p>Ошибка типизации - это как просить кошку постирать бельё. Возможно, вы хотели попросить об этом вашего друга.</p>
7
</blockquote><p>В программировании "типизация" - это классификация информации. Это общий термин и разные языки программирования справляются с типизацией по-разному. Как вы уже знаете, JavaScript умеет отличать типы. Функция - это один тип, Число - другой, и вы не можете просто использовать число как функцию.</p>
7
</blockquote><p>В программировании "типизация" - это классификация информации. Это общий термин и разные языки программирования справляются с типизацией по-разному. Как вы уже знаете, JavaScript умеет отличать типы. Функция - это один тип, Число - другой, и вы не можете просто использовать число как функцию.</p>
8
<p>typeof - это специальный оператор, который возвращает строку, в которой написан тип.</p>
8
<p>typeof - это специальный оператор, который возвращает строку, в которой написан тип.</p>
9
<p>42 и 3.14, очевидно, числа, несколько комбинаций букв в кавычках - строка, а true и false - булево значение. Всё это - типы в JavaScript - число, строка и булево значение.</p>
9
<p>42 и 3.14, очевидно, числа, несколько комбинаций букв в кавычках - строка, а true и false - булево значение. Всё это - типы в JavaScript - число, строка и булево значение.</p>
10
<p>NaN означает - "не число", но тип NaN - это "число". Да, я знаю. Еще одна странность JavaScript. Такие правила в этом языке.</p>
10
<p>NaN означает - "не число", но тип NaN - это "число". Да, я знаю. Еще одна странность JavaScript. Такие правила в этом языке.</p>
11
<p>Типизация полезна. Когда мы попытаемся запустить число, как будто это функция, JavaScript начнёт жаловаться и мы увидим ошибку и починим её. Если бы никакого обозначения типов в JavaScript не было, мы бы сталкивались либо с каким-нибудь аномальным поведением, либо с мистической ошибкой. Вместо чёткого "length - это не функция", мы бы видели что-то вроде "I'm sorry Dave, I'm afraid I can't do that".</p>
11
<p>Типизация полезна. Когда мы попытаемся запустить число, как будто это функция, JavaScript начнёт жаловаться и мы увидим ошибку и починим её. Если бы никакого обозначения типов в JavaScript не было, мы бы сталкивались либо с каким-нибудь аномальным поведением, либо с мистической ошибкой. Вместо чёткого "length - это не функция", мы бы видели что-то вроде "I'm sorry Dave, I'm afraid I can't do that".</p>
12
<p>А что, если создать переменную, но не задать ей никакого значения? Какой в этом случае будет тип? Это ни число, ни строка, ничто... Потому что нет значения, правильно?</p>
12
<p>А что, если создать переменную, но не задать ей никакого значения? Какой в этом случае будет тип? Это ни число, ни строка, ничто... Потому что нет значения, правильно?</p>
13
<p>JavaScript в этом случае кое-что делает в тайне от вас. Переменная без значения на самом деле имеет специальное значение - "undefined". И тип такой переменной называется "undefined".</p>
13
<p>JavaScript в этом случае кое-что делает в тайне от вас. Переменная без значения на самом деле имеет специальное значение - "undefined". И тип такой переменной называется "undefined".</p>
14
<p>Например, тип number имеет множество потенциальных значений: 1, 2, -10, 69000 и другие числа. А тип undefined только одно - undefined.</p>
14
<p>Например, тип number имеет множество потенциальных значений: 1, 2, -10, 69000 и другие числа. А тип undefined только одно - undefined.</p>
15
<p>Когда дело касается типизации в программировании, важно различать две концепции: динамическая против статической и слабая против сильной.</p>
15
<p>Когда дело касается типизации в программировании, важно различать две концепции: динамическая против статической и слабая против сильной.</p>
16
<p>Чтобы понимать разницу между динамической и статической типизацией, нам сначала нужно посмотреть как написанные программы становятся запущенными программами.</p>
16
<p>Чтобы понимать разницу между динамической и статической типизацией, нам сначала нужно посмотреть как написанные программы становятся запущенными программами.</p>
17
<p>Код, который вы пишете, обычно конвертируется в понятную для запуска компьютером форму. Этот процесс называется компиляцией, а промежуток времени, за который это происходит - "стадией компиляции" или compile time.</p>
17
<p>Код, который вы пишете, обычно конвертируется в понятную для запуска компьютером форму. Этот процесс называется компиляцией, а промежуток времени, за который это происходит - "стадией компиляции" или compile time.</p>
18
<p>После того, как компиляция закончена и программа запущена, начинается отсчёт времени, который называется "стадией исполнения" или run time.</p>
18
<p>После того, как компиляция закончена и программа запущена, начинается отсчёт времени, который называется "стадией исполнения" или run time.</p>
19
<p>Некоторые языки проверяют типы и ищут ошибки типизации на стадии компиляции. У них статическая типизация.</p>
19
<p>Некоторые языки проверяют типы и ищут ошибки типизации на стадии компиляции. У них статическая типизация.</p>
20
<p>Другие языки проверяют типы и ищут ошибки типизации на стадии исполнения. Такая типизация - динамическая.</p>
20
<p>Другие языки проверяют типы и ищут ошибки типизации на стадии исполнения. Такая типизация - динамическая.</p>
21
<p>Иными словами: статическая типизация означает проверку типов перед запуском программы, динамическая - проверку типов, когда программа запущена.</p>
21
<p>Иными словами: статическая типизация означает проверку типов перед запуском программы, динамическая - проверку типов, когда программа запущена.</p>
22
<p>C#, C++, Java, Go - статически типизированные языки. Если в одном из этих языков вы создадите число и попытаетесь проводить с ним операции, как с функцией, вы получите ошибку во время компиляции, а программа не станет запускаться - она даже не дойдёт до этой стадии, потому что ошибка типизации будет обнаружена перед исполнением, в период компиляции.</p>
22
<p>C#, C++, Java, Go - статически типизированные языки. Если в одном из этих языков вы создадите число и попытаетесь проводить с ним операции, как с функцией, вы получите ошибку во время компиляции, а программа не станет запускаться - она даже не дойдёт до этой стадии, потому что ошибка типизации будет обнаружена перед исполнением, в период компиляции.</p>
23
<p>JavaScript, Ruby, PHP - динамически типизированные языки. Как вы видели раньше, если использовать неверную типизацию, ваша программа запустится, а ошибка обнаружится только когда будет исполняться конкретная строчка кода. Здесь типы проверяются в период исполнения.</p>
23
<p>JavaScript, Ruby, PHP - динамически типизированные языки. Как вы видели раньше, если использовать неверную типизацию, ваша программа запустится, а ошибка обнаружится только когда будет исполняться конкретная строчка кода. Здесь типы проверяются в период исполнения.</p>
24
<p>Вообще-то, в JavaScript<em>обычно</em>нет никакой компиляции, но это тема другого урока.</p>
24
<p>Вообще-то, в JavaScript<em>обычно</em>нет никакой компиляции, но это тема другого урока.</p>
25
<p>Динамическая типизация не хуже и не лучше статической. Оба способа имеют свои преимущества и недостатки. Динамически типизированные языки обычно проще изучать и писать на них программы, но, как вы можете представить, это потенциально увеличивает ошибки.</p>
25
<p>Динамическая типизация не хуже и не лучше статической. Оба способа имеют свои преимущества и недостатки. Динамически типизированные языки обычно проще изучать и писать на них программы, но, как вы можете представить, это потенциально увеличивает ошибки.</p>
26
<p>Теперь давайте поговорим о слабой и сильной типизации. Посмотрите на этот JavaScript код:</p>
26
<p>Теперь давайте поговорим о слабой и сильной типизации. Посмотрите на этот JavaScript код:</p>
27
<p>М-да… Это… Ок, что тут происходит? Сложение числа 4 со строкой "7" даёт нам строку "47". JavaScript конвертирует число 4 в строку "4" и конкатенирует две строки - склеивает их друг с другом. JavaScript просто берёт на себя ответственность предположить, что это то, что мы хотели. Глупо обвинять его - чего мы действительно хотели? Складывать число со строкой не имеет никакого смысла. Какой-нибудь другой язык, вроде Ruby или Python просто бы пожаловался и ничего не сделал.</p>
27
<p>М-да… Это… Ок, что тут происходит? Сложение числа 4 со строкой "7" даёт нам строку "47". JavaScript конвертирует число 4 в строку "4" и конкатенирует две строки - склеивает их друг с другом. JavaScript просто берёт на себя ответственность предположить, что это то, что мы хотели. Глупо обвинять его - чего мы действительно хотели? Складывать число со строкой не имеет никакого смысла. Какой-нибудь другой язык, вроде Ruby или Python просто бы пожаловался и ничего не сделал.</p>
28
<p>Произведение числа 4 со строкой "7", это, как видите, 28, по мнению JavaScript. В этом случае он сконвертировал строку "7" в число 7 и произвёл обычное умножение.</p>
28
<p>Произведение числа 4 со строкой "7", это, как видите, 28, по мнению JavaScript. В этом случае он сконвертировал строку "7" в число 7 и произвёл обычное умножение.</p>
29
<p>JavaScript постоянно так делает. Он знает о типах разных значений, но когда типы не соответствуют, он пытается предположить и сконвертировать один тип в другой, не предупреждая вас. Иногда это полезно, иногда мозгодробяще. Такое происходит потому что JavaScript - язык со слабой типизацией. У него есть представление о типах, но он типа "это всего лишь игра, чего ты злишься?"</p>
29
<p>JavaScript постоянно так делает. Он знает о типах разных значений, но когда типы не соответствуют, он пытается предположить и сконвертировать один тип в другой, не предупреждая вас. Иногда это полезно, иногда мозгодробяще. Такое происходит потому что JavaScript - язык со слабой типизацией. У него есть представление о типах, но он типа "это всего лишь игра, чего ты злишься?"</p>
30
<p>У этой концепции нет ничего общего с динамической и статической типизацией, смысл которых - КОГДА проверять типы. Сильная против слабой - это НАСКОЛЬКО СЕРЬЁЗНО проверять типы.</p>
30
<p>У этой концепции нет ничего общего с динамической и статической типизацией, смысл которых - КОГДА проверять типы. Сильная против слабой - это НАСКОЛЬКО СЕРЬЁЗНО проверять типы.</p>
31
<p>Вы можете считать, что слабая - это нестрогая типизация, а сильная - это требовательная.</p>
31
<p>Вы можете считать, что слабая - это нестрогая типизация, а сильная - это требовательная.</p>
32
<p>В отличие от динамичности-статичности, сила типизации это спектр. У PHP типизация немного сильнее. У Python ещё сильнее. И все они динамически типизированные языки.</p>
32
<p>В отличие от динамичности-статичности, сила типизации это спектр. У PHP типизация немного сильнее. У Python ещё сильнее. И все они динамически типизированные языки.</p>
33
<p>JavaScript делает множество неявных конвертаций, но он так же даёт нам инструменты, чтобы мы могли делать явные конвертации сами. Мы можем конвертировать строки в числа, числа в строки, булевы значения в строки и так далее:</p>
33
<p>JavaScript делает множество неявных конвертаций, но он так же даёт нам инструменты, чтобы мы могли делать явные конвертации сами. Мы можем конвертировать строки в числа, числа в строки, булевы значения в строки и так далее:</p>
34
<p>Можно предположить, что неявная конверсия из типа в тип - не самая лучшая идея. Неявный, значит скрытый, а скрытый - значит трудно понимаемый и предрасположенный к ошибкам. Поведение программы становится менее очевидным. Вы пишете меньше кода, да, но код более хрупкий и менее понятный.</p>
34
<p>Можно предположить, что неявная конверсия из типа в тип - не самая лучшая идея. Неявный, значит скрытый, а скрытый - значит трудно понимаемый и предрасположенный к ошибкам. Поведение программы становится менее очевидным. Вы пишете меньше кода, да, но код более хрупкий и менее понятный.</p>
35
<h2>Дополнение к уроку</h2>
35
<h2>Дополнение к уроку</h2>
36
<h3>null</h3>
36
<h3>null</h3>
37
<p>В JavaScript кроме undefined существует null. Оно означает, что "значение отсутствует". Например, если создать переменную, но не задавать ей значения, то у нее будет значение undefined:</p>
37
<p>В JavaScript кроме undefined существует null. Оно означает, что "значение отсутствует". Например, если создать переменную, но не задавать ей значения, то у нее будет значение undefined:</p>
38
<p>Тут значения не оказалось ненамеренно. Видимо, просто еще не пришло время дать этой переменной значение.</p>
38
<p>Тут значения не оказалось ненамеренно. Видимо, просто еще не пришло время дать этой переменной значение.</p>
39
<p>null нужен для явного, намеренного указания, что значения нет. Можно сказать let a = null;. Например, вы попросили пользователя ввести информацию, но он ничего не ввел. В таком случае уместно записать в результат null.</p>
39
<p>null нужен для явного, намеренного указания, что значения нет. Можно сказать let a = null;. Например, вы попросили пользователя ввести информацию, но он ничего не ввел. В таком случае уместно записать в результат null.</p>
40
<p>null, в отличие от undefined, можно задавать вручную, передавать как аргумент в функцию и в целом использовать как любое другое явное значение.</p>
40
<p>null, в отличие от undefined, можно задавать вручную, передавать как аргумент в функцию и в целом использовать как любое другое явное значение.</p>
41
<p>(undefined тоже можно задавать вручную, но никогда не нужно этого делать: это значение семантически создано только для того, чтобы его генерировал компьютер, а не программист).</p>
41
<p>(undefined тоже можно задавать вручную, но никогда не нужно этого делать: это значение семантически создано только для того, чтобы его генерировал компьютер, а не программист).</p>
42
<p>При сравнении null и undefined нужно быть осторожным:</p>
42
<p>При сравнении null и undefined нужно быть осторожным:</p>
43
<h3>Сравнение</h3>
43
<h3>Сравнение</h3>
44
<p>В этом курсе мы сравниваем данные, используя три знака равенства:</p>
44
<p>В этом курсе мы сравниваем данные, используя три знака равенства:</p>
45
<p>Это сравнение прямое: являются ли эти данные абсолютно идентичными?</p>
45
<p>Это сравнение прямое: являются ли эти данные абсолютно идентичными?</p>
46
<p>В JavaScript есть расслабленное сравнение, с двумя знаками равенства. Оно показывает, что происходит внутри JavaScript, при сравнении значений разных типов:</p>
46
<p>В JavaScript есть расслабленное сравнение, с двумя знаками равенства. Оно показывает, что происходит внутри JavaScript, при сравнении значений разных типов:</p>
47
<h2>Выводы</h2>
47
<h2>Выводы</h2>
48
<h3>Типизация в JavaScript</h3>
48
<h3>Типизация в JavaScript</h3>
49
<p>JavaScript имеет представление о типах: числах, строках, функциях, логических значениях и так далее. typeof возвращает строку, в которой записан тип:</p>
49
<p>JavaScript имеет представление о типах: числах, строках, функциях, логических значениях и так далее. typeof возвращает строку, в которой записан тип:</p>
50
<p>NaN означает "не число", но тип этого значения - number.</p>
50
<p>NaN означает "не число", но тип этого значения - number.</p>
51
<p>Переменная без значения имеет специальное значение undefined. Тип такой переменной - undefined:</p>
51
<p>Переменная без значения имеет специальное значение undefined. Тип такой переменной - undefined:</p>
52
<h3>Динамическая и статическая типизация</h3>
52
<h3>Динамическая и статическая типизация</h3>
53
<p>Код конвертируется в другую форму, которую компьютер может запустить. Этот процесс называется компиляцией, а период времени, за который этот процесс происходит -<strong>стадией компиляции</strong>(compile time).</p>
53
<p>Код конвертируется в другую форму, которую компьютер может запустить. Этот процесс называется компиляцией, а период времени, за который этот процесс происходит -<strong>стадией компиляции</strong>(compile time).</p>
54
<p>После того, как компиляция закончена, запускается программа и период, пока она запущена, называется<strong>стадией исполнения</strong>(run time).</p>
54
<p>После того, как компиляция закончена, запускается программа и период, пока она запущена, называется<strong>стадией исполнения</strong>(run time).</p>
55
<p><strong>Статически типизированные</strong>языки проверяют типы и ищут ошибки типизации на стадии компиляции.</p>
55
<p><strong>Статически типизированные</strong>языки проверяют типы и ищут ошибки типизации на стадии компиляции.</p>
56
<p><strong>Динамически типизированные</strong>языки проверяют типы и ищут ошибки типизации на стадии исполнения.</p>
56
<p><strong>Динамически типизированные</strong>языки проверяют типы и ищут ошибки типизации на стадии исполнения.</p>
57
<p>Иными словами: статическое типизирование означает проверку типов перед запуском программы; динамическое - проверку типов пока программа запущена.</p>
57
<p>Иными словами: статическое типизирование означает проверку типов перед запуском программы; динамическое - проверку типов пока программа запущена.</p>
58
<h3>Слабая и сильная типизация</h3>
58
<h3>Слабая и сильная типизация</h3>
59
<p>JavaScript часто конвертирует типы автоматически:</p>
59
<p>JavaScript часто конвертирует типы автоматически:</p>
60
<p>JavaScript - это язык со слабой типизацией. У него есть представление о типах, но он расслаблено к ним относится и может оперировать значениями, можно сказать, произвольно. Чем сильнее система типизации, тем строже правила.</p>
60
<p>JavaScript - это язык со слабой типизацией. У него есть представление о типах, но он расслаблено к ним относится и может оперировать значениями, можно сказать, произвольно. Чем сильнее система типизации, тем строже правила.</p>
61
<h3>Явные конверсии в JavaScript</h3>
61
<h3>Явные конверсии в JavaScript</h3>
62
62