aboutsummaryrefslogtreecommitdiff
path: root/files/ru/learn/javascript/first_steps/what_went_wrong/index.html
blob: 560f580d4ec31ee8c97e0355949f07bc1dfbfea8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
---
title: Что пошло не так? Устранение ошибок JavaScript
slug: Learn/JavaScript/First_steps/What_went_wrong
translation_of: Learn/JavaScript/First_steps/What_went_wrong
original_slug: Learn/JavaScript/Первые_шаги/Что_пошло_не_так
---
<div>{{LearnSidebar}}</div>

<div>{{PreviousMenuNext("Learn/JavaScript/Первые_шаги/A_first_splash", "Learn/JavaScript/Первые_шаги/Variables", "Learn/JavaScript/Первые_шаги")}}</div>

<p class="summary">Когда вы создали игру «Угадай номер» в предыдущей статье, вы, возможно, обнаружили, что она не работает. Не бойтесь — эта статья призвана избавить вас от разрыва волос над такими проблемами, предоставив вам несколько простых советов о том, как найти и исправить ошибки в программах JavaScript.</p>

<table class="learn-box standard-table">
 <tbody>
  <tr>
   <th scope="row">
    <p>Нужно:</p>
   </th>
   <td>базовая компьютерная грамотность, базовое понимание HTML и CSS, понимание того, что такое JavaScript.</td>
  </tr>
  <tr>
   <th scope="row">Цель</th>
   <td>получить способность и уверенность в том, чтобы приступить к исправлению простых проблем в вашем собственном коде.</td>
  </tr>
 </tbody>
</table>

<h2 id="Типы_ошибок">Типы ошибок</h2>

<p>Когда вы делаете что-то не так в коде, есть два основных типа ошибок, с которыми вы столкнётесь:</p>

<ul>
 <li>
  <p><strong>Синтаксические ошибки:</strong> Это орфографические ошибки в коде, которые фактически заставляют программу вообще не запускаться, или перестать работать на полпути — вам также будут предоставлены некоторые сообщения об ошибках. Обычно они подходят для исправления, если вы знакомы с правильными инструментами и знаете, что означают сообщения об ошибках!</p>
 </li>
 <li><strong>Логические ошибки:</strong> Это ошибки, когда синтаксис действительно правильный, но код не тот, каким вы его предполагали, что означает, что программа работает успешно, но даёт неверные результаты. Их часто сложнее находить, чем синтаксические ошибки, так как обычно не возникает сообщение об ошибке, которое направляет вас к источнику ошибки.</li>
</ul>

<p>Ладно, все <em>не так</em> просто — есть и другие отличия, которые вы поймёте, пока будете изучать язык JavaScript глубже. Однако вышеуказанной классификации достаточно на раннем этапе вашей карьеры. Мы рассмотрим оба эти типа в дальнейшем.</p>

<h2 id="Ошибочный_пример">Ошибочный пример</h2>

<p>Чтобы начать работу, давайте вернёмся к нашей игре с угадыванием чисел — за исключением того, что мы будем изучать версию с некоторыми преднамеренными ошибками. Перейдите в Github и сделайте себе локальную копию <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/troubleshooting/number-game-errors.html">number-game-errors.html</a> (см. здесь <a href="http://mdn.github.io/learning-area/javascript/introduction-to-js-1/troubleshooting/number-game-errors.html">как это работает</a>).</p>

<ol>
 <li>Чтобы начать работу, откройте локальную копию внутри вашего любимого текстового редактора и вашего браузера.</li>
 <li>Попробуйте сыграть в игру — вы заметите, что когда вы нажимаете кнопку «Submit guess», она не работает!</li>
</ol>

<div class="note">
<p><strong>Примечание:</strong> Возможно, у вас может быть собственная версия игрового примера, которая не работает, которую вы можете исправить! Мы по-прежнему хотели бы, чтобы вы работали над статьёй с нашей версией, чтобы вы могли изучать методы, которые мы здесь преподаём. Затем вы можете вернуться и попытаться исправить ваш пример.</p>
</div>

<p>На этом этапе давайте рассмотрим консоль разработчика, чтобы увидеть, можем ли мы видеть какие-либо синтаксические ошибки, а затем попытаемся их исправить. Вы узнаете, как это сделать, ниже.</p>

<h2 id="Исправление_синтаксических_ошибок">Исправление синтаксических ошибок</h2>

<p>Раньше в курсе мы заставили вас набрать некоторые простые команды JavaScript в <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">консоль разработчика JavaScript</a> (если вы не можете вспомнить, как открыть это в своём браузере, следуйте предыдущей ссылке, чтобы узнать, как это сделать). Что ещё более полезно, так это то, что консоль предоставляет вам сообщения об ошибках всякий раз, когда существует синтаксическая ошибка внутри JavaScript, которая подаётся в механизм JavaScript браузера. Теперь пойдём на охоту.</p>

<ol>
 <li>Перейдите на вкладку, в которой у вас есть number-game-errors.html, и откройте консоль JavaScript. Вы должны увидеть сообщение об ошибке в следующих строках: <img alt="" src="https://mdn.mozillademos.org/files/13496/not-a-function.png" style="display: block; margin: 0 auto;"></li>
 <li>Это довольно простая ошибка для отслеживания, и браузер даёт вам несколько полезных бит информации, которые помогут вам (скриншот выше от Firefox, но другие браузеры предоставляют аналогичную информацию). Слева направо, у нас есть:
  <ul>
   <li>Красный «x» означает, что это ошибка.</li>
   <li>Сообщение об ошибке, указывающее, что пошло не так: «TypeError: guessSubmit.addeventListener не является функцией»</li>
   <li>Ссылка «Узнать больше», которая ссылается на страницу MDN, которая объясняет, что эта ошибка означает в огромных количествах деталей.</li>
   <li>Имя файла JavaScript, который ссылается на вкладку «Отладчик» консоли разработчика. Если вы перейдёте по этой ссылке, вы увидите точную строку, где подсвечивается ошибка.</li>
   <li>Номер строки, в которой находится ошибка, и номер символа в этой строке, где первая ошибка. В этом случае у нас есть строка 86, символ номер 3.</li>
  </ul>
 </li>
 <li>Если мы посмотрим на строку 86 в нашем редакторе кода, мы найдём эту строку:
  <pre class="brush: js"><font><font>guessSubmit.addeventListener('click', checkGuess);</font></font></pre>
 </li>
 <li>В сообщении об ошибке говорится, что «guessSubmit.addeventListener не является функцией», поэтому мы, вероятно, где-то ошиблись. Если вы не уверены в правильности написания синтаксиса, часто бывает полезно найти функцию на MDN. Лучший способ сделать это в настоящее время — поиск «mdn <em>имя-функции</em>» в вашей любимой поисковой системе. Вот ссылка, которая поможет сократить вам некоторое время в данном случае: <code><a href="/en-US/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code>.</li>
 <li>Итак, глядя на эту страницу, кажется, что ошибка в том, что мы неправильно назвали имя функции! Помните, что JavaScript чувствителен к регистру, поэтому любые незначительные отличия в орфографии или регистре текста могут вызвать ошибку. Изменение этого параметра в addEventListener должно быть исправлено. Сделайте это сейчас.</li>
</ol>

<div class="note">
<p><strong>Примечание: </strong>См. наш <a href="/en-US/docs/Web/JavaScript/Reference/Errors/Not_a_function">TypeError: «x»</a> не является справочной страницей функций для получения дополнительной информации об этой ошибке.</p>
</div>

<h3 id="Синтаксические_ошибки_второй_раунд">Синтаксические ошибки: второй раунд</h3>

<div class="note">
<p><strong>Примечание</strong>: <code><a href="/en-US/docs/Web/API/Console/log">console.log()</a></code> это часто используемая функция отладки, которая выводит значение в консоль. Поэтому она будет выводить значение <code>lowOrHi</code> в консоли, как только мы попытаемся установить его в строке 48.</p>
</div>

<ol>
 <li>Сохраните и обновите страницу, и вы увидите, что ошибка исчезла.</li>
 <li>Теперь, если вы попробуете ввести значение и нажать кнопку "Submit guess", вы увидите ... другую ошибку!  <img alt="" src="https://mdn.mozillademos.org/files/13498/variable-is-null.png" style="display: block; margin: 0 auto;"></li>
 <li>На этот раз сообщается об ошибке: "TypeError: lowOrHi is null", в строке 78.
  <div class="note"><strong>Примечание</strong>: <code><a href="/en-US/docs/Glossary/Null">Null</a></code> — это специальное значение, которое означает "ничего" или "не значение". Поэтому <code>lowOrHi</code> был объявлен и инициализирован без значения — у него нет типа или значения.</div>

  <div class="note"><strong>Примечание</strong>: Эта ошибка не появилась, как только страница была загружена, потому что эта ошибка произошла внутри функции (внутри <code>checkGuess() { ... }</code> block). Об этом вы узнаете более подробно в нашей более поздней статье о функциях, код внутри функций выполняется в отдельной области для кода внешних функций. В этом случае код не был запущен, и ошибка не была брошена до тех пор, пока функция <code>checkGuess()</code> не была запущена строкой 86.</div>
 </li>
 <li>Посмотрите на строку 78, и вы увидите следующий код:
  <pre class="brush: js"><font><font>lowOrHi.textContent = «Последнее предположение было слишком высоко!»;</font></font></pre>
 </li>
 <li>Эта строка пытается установить свойство <code>textContent</code> переменной <code>lowOrHi</code> как текстовую строку, но это не работает, поскольку <code>lowOrHi</code> не содержит того, что должна. Давайте посмотрим, почему так происходит — попробуйте найти другие экземпляры <code>lowOrHi</code> в коде. Самый ранний экземпляр, который вы найдёте в JavaScript, находится в строке 48:
  <pre class="brush: js"><font><font>const lowOrHi = document.querySelector('lowOrHi');</font></font></pre>
 </li>
 <li>На этом этапе мы пытаемся заставить переменную содержать ссылку на элемент документа HTML. Давайте проверим, является ли значение  <code>null</code> после выполнения этой строки. Добавьте следующий код в строку 49:
  <pre class="brush: js">console.log(lowOrHi);
</pre>
 </li>
 <li>Сохраните и обновите, и вы должны увидеть результат работы <code>console.log()</code> в консоли браузера. <img alt="" src="https://mdn.mozillademos.org/files/13494/console-log-output.png" style="display: block; margin: 0 auto;"> Разумеется, значение <code>lowOrHi</code> на данный момент равно <code>null</code>, поэтому определённо существует проблема в строке 48.</li>
 <li>Давайте подумаем о том, что может быть проблемой. Строка 48 использует метод <code><a href="/en-US/docs/Web/API/Document/querySelector">document.querySelector()</a></code> для получения ссылки на элемент, выбирая его с помощью селектора CSS. Посмотрев далее наш файл, мы можем найти обсуждаемый элемент <code>&lt;p&gt;</code>:
  <pre class="brush: js">&lt;p class="lowOrHi"&gt;&lt;/p&gt;
</pre>
 </li>
 <li>Поэтому нам нужен селектор классов, который начинается с точки (.), но селектор, передаваемый в метод <code>querySelector()</code> в строке 48, не имеет точки. Возможно, это и есть проблема! Попробуйте изменить <code>lowOrHi</code> на <code>.lowOrHi</code> в строке 48.</li>
 <li>Повторите попытку сохранения и обновления, и ваш вызов <code>console.log()</code> должен вернуть элемент <code>&lt;p&gt;</code>, который мы хотим. Уф! Ещё одна ошибка исправлена! Вы можете удалить строку с  <code>console.log()</code> сейчас, или оставить для дальнейшего применения — выбирайте сами.</li>
</ol>

<div class="note">
<p><strong>Примечание</strong>: Загляните на справочную страницу <a href="/en-US/docs/Web/JavaScript/Reference/Errors/Unexpected_type">TypeError: "x" is (not) "y"</a>, чтобы узнать больше об этой ошибке.</p>
</div>

<h3 id="Синтаксические_ошибки_третий_раунд">Синтаксические ошибки: третий раунд</h3>

<ol>
 <li>Теперь, если вы снова попробуете сыграть в игру, вы должны добиться большего успеха — игра должна играть абсолютно нормально, пока вы не закончите игру, либо угадав нужное число, либо потеряв жизни.</li>
 <li>На данном этапе игра снова слетает, и выводится такая же ошибка, как и в начале — "TypeError: resetButton.addeventListener is not a function"! Однако, теперь она происходит из-за строки 94.</li>
 <li>Посмотрев на строку 94, легко видеть, что здесь сделана такая же ошибка. Нам просто нужно изменить <code>addeventListener</code> на <code>addEventListener</code>.</li>
</ol>

<h2 id="Логическая_ошибка">Логическая ошибка</h2>

<p>На этом этапе игра должна проходить отлично, однако, поиграв несколько раз, вы, несомненно заметите, что случайное число, которое вы должны угадать, всегда 0 или 1. Определённо не совсем так, как мы хотим, чтобы игра была разыграна!</p>

<p>Безусловно, где-то в игре есть логическая ошибка — игра не возвращает ошибку, она просто работает неправильно.</p>

<ol>
 <li>Найдём переменную <code>randomNumber</code> , и строку где в первый раз устанавливали случайное число. Пример, в котором мы храним случайное число, которое должны угадать, на строке 44:

  <pre class="brush: js">let randomNumber = Math.floor(Math.random()) + 1;
</pre>
  И на строке 113, где мы генерируем случайное число, каждый раз после окончания игры:

  <pre class="brush: js">randomNumber = Math.floor(Math.random()) + 1;
</pre>
 </li>
 <li>Чтобы проверить, действительно ли проблема в этом, давайте обратимся к нашему другу <code>console.log()</code> снова — вставьте её ниже строк с ошибками:
  <pre class="brush: js">console.log(randomNumber);
</pre>
 </li>
 <li>Сохраните и обновите, а дальше попробуйте пару раз сыграть — в консоли вы увидите что <code>randomNumber</code> равна 1 в каждой точке, где вы её записали после строк с ошибками.</li>
</ol>

<h3 id="Работаем_через_логику">Работаем через логику</h3>

<p>Чтобы исправить это, давайте рассмотрим как работает строка. Первое, мы вызываем <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random">Math.random()</a></code>, который генерирует случайное десятичное число, между 0 и 1, например 0.5675493843.</p>

<pre class="brush: js"><font><font>Math.random()</font></font></pre>

<p>Дальше, мы передаём результат вызова <code>Math.random()</code> через <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor">Math.floor()</a></code>, который округляет число вниз, до ближайшего целого числа. Затем мы добавляем 1 к данному результату:</p>

<pre><font><font>Math.floor(Math.random()) + 1;</font></font></pre>

<p>Округление случайного десятичного числа к меньшему, всегда будет возвращать 0, так что добавление к нему единицы будет возвращать всегда 1.  Нам нужно умножить случайное число на 100, прежде чем мы округлим его к меньшему. Следующая строка вернёт нам случайное число между 0 и 99:</p>

<pre class="brush: js"><font><font>Math.floor(Math.random() * 100);</font></font></pre>

<p>поэтому нам нужно добавить 1, чтоб нам возвращалось случайное число между 1 и 100:</p>

<pre class="brush: js"><font><font>Math.floor(Math.random() * 100) + 1;</font></font></pre>

<p>А теперь, исправьте обе строки с ошибками, затем сохраните и обновите, игра должна работать так, как мы и планировали!</p>

<h2 id="Другие_распространённые_ошибки">Другие распространённые ошибки</h2>

<p>Существуют и другие распространённые ошибки, которые вы обнаружите в своём коде. В этом разделе показано большинство из них.</p>

<h3 id="SyntaxError_отсутствует_перед_постановкой"><font><font>SyntaxError: отсутствует ; </font><font>перед постановкой</font></font></h3>

<p>Эта ошибка обычно означает что вы упустили точку с запятой в конце одной из ваших строк кода, но иногда ошибка может быть более загадочной. Например, если мы изменим эту строку внутри функции <code>checkGuess()</code> :</p>

<pre class="brush: js"><font><font>var userGuess = Number(guessField.value);</font></font></pre>

<p>на эту</p>

<pre class="brush: js"><font><font>var userGuess === Number(guessField.value);</font></font></pre>

<p>Это вызовет данную ошибку, потому что браузер подумает, что вы пытались сделать что-то другое. Вы должны быть уверены, что вы не перепутали оператор присваивания (<code>=</code>), который присваивает значение переменной — с оператором сравнения (<code>===</code>), который строго сравнивает операнды, и возвращает <code>true</code>/<code>false</code> .</p>

<div class="note">
<p><strong>Примечание</strong>: Загляните на справочную страницу <a href="/ru/docs/Web/JavaScript/Reference/Errors/Missing_semicolon_before_statement">Синтаксическая ошибка: пропущен символ ; до объявления инструкции</a> для получения дополнительной информации об этой ошибке.</p>
</div>

<h3 id="В_программе_всегда_говорится_что_вы_выиграли_независимо_от_того_что_вы_ввели">В программе всегда говорится, что вы выиграли, независимо от того, что вы ввели</h3>

<p>Причиной этому является все то же перепутывание оператора присваивания (<code>=</code>) со строгим сравнением (<code>===</code>). Например, если мы изменим внутри <code>checkGuess()</code> эту строку кода:</p>

<pre class="brush: js"><font><font>if (userGuess === randomNumber) {</font></font></pre>

<p>на эту</p>

<pre class="brush: js"><font><font>if (userGuess = randomNumber) {</font></font></pre>

<p>мы всегда будем получать <code>true</code>, заставляя программу сообщать, что игра была выиграна. Будьте осторожны!</p>

<h3 id="SyntaxError_отсутствует_после_списка_аргументов"><font><font>SyntaxError: отсутствует ) после списка аргументов</font></font></h3>

<p>Эта ошибка проста — обычно она означает, что вы пропустили закрывающую скобку с конца вызова функции / метода.</p>

<div class="note">
<p><strong>Примечание</strong>: Загляните на справочную страницу  <a href="/en-US/docs/Web/JavaScript/Reference/Errors/Missing_parenthesis_after_argument_list">SyntaxError: missing ) after argument list</a> для получения дополнительной информации об этой ошибке.</p>
</div>

<h3 id="SyntaxError_missing_after_property_id">SyntaxError: missing : after property id</h3>

<p dir="ltr">Эта ошибка обычно связана с неправильно сформированным объектом JavaScript, но в этом случае нам удалось получить её, изменив</p>

<pre class="brush: js"><font><font>function checkGuess() {</font></font></pre>

<p>на</p>

<pre class="brush: js"><font><font>function checkGuess( {
</font></font></pre>

<p dir="ltr" id="tw-target-text">Это заставило браузер думать, что мы пытаемся передать содержимое функции в функцию в качестве аргумента. Будьте осторожны с этими скобками!</p>

<h3 id="SyntaxError_missing_after_function_body">SyntaxError: missing } after function body</h3>

<p>Это легко — обычно это означает, что вы пропустили одну из ваших фигурных скобок из функции или условной структуры. Мы получили эту ошибку, удалив одну из закрывающих фигурных скобок возле нижней части функции  <code>checkGuess()</code>.</p>

<h3 id="SyntaxError_expected_expression_got_string_or_SyntaxError_unterminated_string_literal">SyntaxError: expected expression, got '<em>string</em>' or SyntaxError: unterminated string literal</h3>

<p><font><font>Эти ошибки обычно означает, что вы пропустили открывающую или закрывающую кавычку для строковых значений. </font><font>В первой ошибки выше,  </font></font><em><font><font>строка</font></font></em><font><font>  будет заменена на неожиданный персонаж (ей) , </font><font>что браузер нашёл вместо кавычек в начале строки. </font><font>Вторая ошибка означает , </font><font>что строка не закончилась кавычки.</font></font></p>

<p>При всех этих ошибках действуйте так, как в наших  примерах, которые мы рассмотрели в пошаговом руководстве. Когда возникает ошибка, посмотрите полученный номер строки, перейдите к этой строке и посмотрите, можете ли вы определить, что случилось. Имейте в виду, что ошибка не обязательно будет на этой строке, а также, что ошибка может быть вызвана не такой же проблемой, которую мы привели выше!</p>

<div class="note">
<p><strong><font><font>Примечание</font></font></strong><font><font> : Смотрите наш </font></font><a href="/en-US/docs/Web/JavaScript/Reference/Errors/Unexpected_token"><font><font>SyntaxError: Неожиданный токен</font></font></a><font><font> и </font></font><a href="/en-US/docs/Web/JavaScript/Reference/Errors/Unterminated_string_literal"><font><font>SyntaxError: незавершённая строка</font></font></a><font><font> эталонных страниц для получения </font><font>более подробной информации об этих ошибках.</font></font></p>
</div>

<h2 id="Резюме"><font><font>Резюме</font></font></h2>

<p>Итак, мы научились основам  выяснения ошибок в простых программах JavaScript. Не всегда так просто разобраться, что не так в вашем коде, но, по крайней мере, это сэкономит вам несколько часов сна и позволит вам продвигаться немного быстрее, когда что-либо заработает не так, как ожидалось, в вашем учебном путешествии.</p>

<h2 id="Смотрите_также"><font><font>Смотрите также</font></font></h2>

<div>
<ul>
 <li><font><font>Есть много других типов ошибок, которые не перечислены здесь; </font><font>мы составляем ссылку , </font><font>которая объясняет , </font><font>что они означают подробно - см. </font></font><a href="/en-US/docs/Web/JavaScript/Reference/Errors"><font><font>ссылку ошибки JavaScript</font></font></a><font><font> .</font></font></li>
 <li><font><font>Если вы столкнётесь с любыми ошибками в коде, </font><font>которые вы не знаете , </font><font>как исправить после прочтения этой статьи, вы можете получить помощь! </font><font>Спросите на </font></font><a class="external external-icon" href="https://discourse.mozilla-community.org/t/learning-web-development-marking-guides-and-questions/16294"><font><font>нить обучения Область дискурсе</font></font></a><font><font> , или в </font></font><a href="irc://irc.mozilla.org/mdn"><font><font>#mdn</font></font></a><font><font> IRC канал на </font></font><a class="external external-icon" href="https://wiki.mozilla.org/IRC"><font><font>Mozilla IRC</font></font></a><font><font>. </font><font>Расскажите нам, какая</font><font> у вас ошибка, и мы постараемся вам помочь. </font><font>Приложите пример своего кода для большей ясности проблемы.</font></font></li>
</ul>
</div>

<p>{{PreviousMenuNext("Learn/JavaScript/Первые_шаги/A_first_splash", "Learn/JavaScript/Первые_шаги/Variables", "Learn/JavaScript/Первые_шаги")}}</p>