diff options
Diffstat (limited to 'files/ru/web/javascript/guide')
25 files changed, 9978 insertions, 0 deletions
diff --git a/files/ru/web/javascript/guide/about/index.html b/files/ru/web/javascript/guide/about/index.html new file mode 100644 index 0000000000..0f9c90fcc8 --- /dev/null +++ b/files/ru/web/javascript/guide/about/index.html @@ -0,0 +1,158 @@ +--- +title: Об этом учебнике +slug: Web/JavaScript/Guide/About +translation_of: Web/JavaScript/Guide/Introduction +--- +<p>JavaScript это кросс-платформенный, объектно-ориентированный интерпретируемый язык программирования. В этом учебнике описано все, что вам нужно знать для того, чтобы начать ипользовать JavaScript.</p> + +<h2 id="Особенности_разных_версий_JavaScript">Особенности разных версий JavaScript</h2> + +<p> </p> + +<ul> + <li><a class="new" href="/ru/docs/Web/JavaScript/New_in_JavaScript/1.2" rel="nofollow">/ru/docs/Web/JavaScript/New_in_JavaScript/1.2</a></li> + <li><a class="new" href="/ru/docs/Web/JavaScript/New_in_JavaScript/1.3" rel="nofollow">/ru/docs/Web/JavaScript/New_in_JavaScript/1.3</a></li> + <li><a class="new" href="/ru/docs/Web/JavaScript/New_in_JavaScript/1.4" rel="nofollow">/ru/docs/Web/JavaScript/New_in_JavaScript/1.4</a></li> + <li><a href="/ru/docs/Web/JavaScript/New_in_JavaScript/1.5">Новое в JavaScript 1.5</a></li> + <li><a href="/ru/docs/Web/JavaScript/New_in_JavaScript/1.6">Новое в JavaScript 1.6</a></li> + <li><a href="/ru/docs/Web/JavaScript/New_in_JavaScript/1.7">Новое в JavaScript 1.7</a></li> + <li><a href="/ru/docs/Web/JavaScript/New_in_JavaScript/1.8">New in JavaScript 1.8</a></li> + <li><a href="/ru/docs/Web/JavaScript/New_in_JavaScript/1.8.1">Новое в JavaScript 1.8.1</a></li> + <li><a href="/ru/docs/Web/JavaScript/New_in_JavaScript/1.8.5">Новое в JavaScript 1.8.5</a></li> +</ul> + +<p> </p> + +<h2 id="Что_вы_уже_должны_знать">Что вы уже должны знать</h2> + +<p>Этот учебник предполагает, что у вас уже имеются некоторые знания и опыт:</p> + +<p>Общее понимание, что такое Интернет и всемирная сеть WWW. Знание языка разметки гипертекста (<a href="/en/HTML" title="en/HTML">HTML</a>) также привествуется.</p> + +<p>Некоторый опыт программирования на C или Visual Basic будет полезен, но не является обязательным.</p> + +<h2 id="Версии_JavaScript">Версии JavaScript</h2> + +<table class="standard-table"> + <caption>Таблица 1. Версии JavaScript и Navigator</caption> + <thead> + <tr> + <th scope="col">Версия JavaScript</th> + <th scope="col">Версия Navigator</th> + </tr> + </thead> + <tbody> + <tr> + <td>JavaScript 1.0</td> + <td>Navigator 2.0</td> + </tr> + <tr> + <td>JavaScript 1.1</td> + <td>Navigator 3.0</td> + </tr> + <tr> + <td>JavaScript 1.2</td> + <td>Navigator 4.0-4.05</td> + </tr> + <tr> + <td>JavaScript 1.3</td> + <td>Navigator 4.06-4.7x</td> + </tr> + <tr> + <td>JavaScript 1.4</td> + <td> </td> + </tr> + <tr> + <td>JavaScript 1.5</td> + <td>Navigator 6.0<br> + Mozilla (браузер с открытым исходным кодом)</td> + </tr> + <tr> + <td>JavaScript 1.6</td> + <td><a href="/en/Firefox_1.5_for_developers" title="en/Firefox_1.5_for_developers">Firefox 1.5</a>, другие, основанные на Mozilla 1.8 продукты</td> + </tr> + <tr> + <td>JavaScript 1.7</td> + <td><a href="/en/Firefox_2_for_developers" title="en/Firefox_2_for_developers">Firefox 2</a>, другие, основанные на Mozilla 1.8.1 продукты</td> + </tr> + <tr> + <td>JavaScript 1.8</td> + <td><a href="/en/Firefox_3_for_developers" title="en/Firefox_3_for_developers">Firefox 3</a>, другие, основанные на Mozilla 1.9 продукты</td> + </tr> + </tbody> +</table> + +<p>Каждая версия Netscape Enterprise Server также поддерживает разные версии JavaScript. Чтобы помочь вам писать скрипты совместимые с разными версиями Enterprise Server, это руководство пользуется аббревиатурой, которая однозначно идентифицирует версию сервера, в которой реализована каждая функциональность.</p> + +<p><br> + <strong style="font-style: inherit; font-weight: 700; line-height: 1.5;"> Таблица 2. Аббревиатуры версий Netscape Enterprise Server</strong></p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Abbreviation</th> + <th scope="col">Enterprise Server version</th> + </tr> + </thead> + <tbody> + <tr> + <td>NES 2.0</td> + <td>Netscape Enterprise Server 2.0</td> + </tr> + <tr> + <td>NES 3.0</td> + <td>Netscape Enterprise Server 3.0</td> + </tr> + </tbody> +</table> + +<h2 id="Где_найти_информацию_по_JavaScript">Где найти информацию по JavaScript</h2> + +<p>Документация JavaScript включает в себя следующие материалы:</p> + +<ul> + <li><a href="/ru/JavaScript/Guide" title="en/Core_JavaScript_1.5_Guide">Учебник JavaScript</a> (тот учебник, который вы сейчас читаете) содержит информацию о языке JavaScript и его объектах.</li> + <li><a href="/en/JavaScript/Reference" title="en/JavaScript/Reference">JavaScript Reference</a> содержит справочный материал по языку JavaScript.</li> +</ul> + +<p>Если вы новичок в JavaScript, то начните с <a href="/en/JavaScript/Guide" title="en/Core_JavaScript_1.5_Guide">Учебника </a><a href="/en/JavaScript/Guide" title="en/Core_JavaScript_1.5_Guide">JavaScript</a>. Как только вы усвоили фундаментальные основы, вы можете начать пользоваться <a href="/en/JavaScript/Reference" title="en/JavaScript/Reference">Справочником JavaScript</a>, чтобы получить больше информации об определенных объектах, выражениях и операторах.</p> + +<h2 id="Советы_изучающим_JavaScript">Советы изучающим JavaScript</h2> + +<p>Начать изучать JavaScript очень легко: все что вам нужно - это современный веб браузер. Этот учебник включает описание некоторых особенностей JavaScript, которые доступны только в самых последних версиях Firefox (и других браузерах основанных на движке Gecko), так что лучше всего воспользоваться самой последней версией Firefox.</p> + +<h3 id="Интерактивный_интерпретатор.">Интерактивный интерпретатор.</h3> + +<p>Интерактивная строка ввода JavaScript окажет бесценную услугу в изучении языка, так как позволит пробовать все вещи сразу же, вам не потребуется сохранять изменения в файле и обновлять страницу каждый раз. Консоль ошибок Firefox, доступна через меню Инструменты, предлагает простой способ попробовать выполнить JavaScript выражения: просто введите строку с кодом и нажмите кнопку "Evaluate".</p> + +<p><img alt="Image:ErrorConsole.png" class="internal" src="/@api/deki/files/192/=ErrorConsole.png"></p> + +<h3 id="Firebug">Firebug</h3> + +<p>Более продвинутое средство доступно в <a class="external" href="http://www.getfirebug.com/">Firebug</a>. Firebug это расширение Firefox. Хотя в последних версиях Firefox средства отладки становятся более совершенными и такой нужды Firebug уже нет. Выражения которые вы вводите интерпретируются как объекты и связываются c другими частями в Firebug. Например, вы можете сложить 5 плюс 5, заменить буквы в строке со строчных на прописные, получить кликабельную ссылку на документ, или получить ссылку на элемент в документе:</p> + +<p><img alt="" class="internal" src="/@api/deki/files/5188/=FirebugCommandLine.PNG" style="height: 281px; width: 728px;"></p> + +<p>Нажав на кнопке со стрелкой в нижнем правом углу вы можете открыть многострочный редактор скриптов.</p> + +<p>Firebug также имеет в составе продвинутый инспектор DOM, дебаггер JavaScript, инструменты профилирования и многие другие полезные утилиты. JavaScript код выполняемый на веб странице может вызвать функцию <code>console.log()</code>, которая выведет свой аргумент на консоль Firebug.</p> + +<p>Множество примеров в этом учебнике используют функцию <code>alert()</code>, чтобы вывести сообщение во время выполнения скрипта.</p> + +<h2 id="Принятые_соглашения_в_документе">Принятые соглашения в документе</h2> + +<p>JavaScript приложения выполняются на разных операционных системах; информация в этом учебнике актуальна в любом случае. Пути к директориям или файлам даны в формате Windows (обратный слеш как разделитель). Для версии Юникс, пути точно такие же, за исключением того, что используеся обычный слеш вместо обратного, а также соотвественно корневая директория начинается с '/' а не 'c:/' как это в Windows.</p> + +<p>Этот учебник использует единый локатор ресурсов (URL-ы) следующей формы:</p> + +<p><code>http://<em>server</em>.<em>domain</em>/<em>path</em>/<em>file</em>.html</code></p> + +<p>В этих URL-ах, <em>server</em> - это имя сервера на котором запущено ваше приложение, например <code>research1</code> или <code>www</code>; <em>domain</em> - это имя Internet домена, например <code>netscape.com</code> или <code>uiuc.edu</code>; <em>path</em> - структура директорий на сервере; и <em>file</em><code>.html</code> - имя файла, который расположен на вашем сервере. В общем, элементы выделенные курсивом в URL-ах это метки-заполнители, а элементы выделенные нормальным моноширинным шрифтом точные неизменные значения (например, конфиругацию сервера вы можете изменить, как и сменить доменное имя, структура каталогов может поменяться, а вот протокол всегда один, и расширение файла для вебстраниц тоже постоянно). Если ваш вебсервер поддерживает Secure Sockets Layer (SSL), то вы можете пользоваться <code>https</code> вместо <code>http</code> в URL.</p> + +<p>Этот учебник пользуется следующим соглашением об использовании шрифтов:</p> + +<ul> + <li><code>Моноширинный шрифт </code>используется для примеров кода и их вывода, API и элементов языка (например, имена методов или имена свойств), имена файлов, имена директорий, путей, тегов HTML, и любого другого текста, который должен быть выведен на экран. (<code><em>Моноширинный курсивный шрифт</em></code> использован для меток-заменителей встроенных в код.)</li> + <li><em>Курсивное начертание </em>использовано для оглавлений, особого выделения, переменных и меток-заменителей, и слов использованых в буквальном смысле.</li> + <li><strong>Жирное начертание </strong>использовано для терминов из глоссария.</li> +</ul> diff --git a/files/ru/web/javascript/guide/control_flow_and_error_handling/index.html b/files/ru/web/javascript/guide/control_flow_and_error_handling/index.html new file mode 100644 index 0000000000..a7b952b323 --- /dev/null +++ b/files/ru/web/javascript/guide/control_flow_and_error_handling/index.html @@ -0,0 +1,371 @@ +--- +title: Порядок выполнения и обработка ошибок +slug: Web/JavaScript/Guide/Control_flow_and_error_handling +tags: + - Guide + - JavaScript +translation_of: Web/JavaScript/Guide/Control_flow_and_error_handling +--- +<p>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Grammar_and_types", "Web/JavaScript/Guide/Loops_and_iteration")}}</p> + +<div class="summary"> +<p>JavaScript поддерживает компактный набор инструкций, особенно управляющих инструкций, которые вы можете использовать, чтобы реализовать интерактивность в вашем приложении. В данной главе дается обзор этих инструкций.</p> +</div> + +<p>Более подробная информация об инструкциях, рассмотренных в данной главе, содержится в <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements">справочнике по JavaScript</a>. Точка с запятой ( <code>;</code> ) используется для разделения инструкций в коде.</p> + +<p>Любое выражение (expression) в JavaScript является также инструкцией (statement). Чтобы получить более подробную информацию о выражениях, прочитайте <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Expressions_and_Operators">Выражения и операторы</a>.</p> + +<h2 id="Инструкция_block">Инструкция block</h2> + +<p>Инструкция block является фундаментальной и используется для группировки других инструкций. Блок ограничивается фигурными скобками:</p> + +<pre style="font-size: 14px; white-space: normal;">{ statement_1; statement_2; ... statement_n; }</pre> + +<p>Блок обычно используется с управляющими инструкциями (например, <code>if</code>, <code>for</code>, <code>while</code>).</p> + +<pre class="brush: js language-js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">while</span> <span class="punctuation token" style="color: #999999;">(</span>x <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;"><</span> <span class="number token" style="color: #990055;">10</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{ </span>x<span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">++</span><span class="punctuation token" style="color: #999999;">;</span><span class="punctuation token"> </span><span class="punctuation token" style="color: #999999;">}</span></code></pre> + +<p>В вышеприведенном примере <code>{ x++; }</code> является блоком.</p> + +<p><strong>Обратите внимание:</strong> в JavaScript <strong>отсутствует</strong> область видимости блока до ECMAScript2015. Переменные, объявленные внутри блока, имеют область видимости функции (или скрипта), в которой находится данный блок, вследствие чего они сохранят свои значения при выходе за пределы блока. Другими словами, блок не создает новую область видимости. "Автономные" (standalone) блоки в JavaScript могут продуцировать полностью отличающийся результат, от результата в языках C или Java. Например:</p> + +<pre class="brush: js language-js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> x <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="number token" style="color: #990055;">1</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">{ + </span><span class="keyword token" style="color: #0077aa;">var</span> x <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="number token" style="color: #990055;">2</span><span class="punctuation token" style="color: #999999;">; +</span><span class="punctuation token" style="color: #999999;">}</span> +console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>x<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // выведет 2</span></code></pre> + +<p>В вышеприведенном примере инструкция <code>var x</code> внутри блока находится в той же области видимости, что и инструкция <code>var x</code> перед блоком. В C или Java эквивалентный код выведет значение 1.</p> + +<p>Начиная с ECMAScript 6, оператор <code>let</code> позволяет объявить переменную в области видимости блока. Чтобы получить более подробную информацию, прочитайте {{jsxref("Statements/let", "let")}}.</p> + +<h2 id="Условные_инструкции">Условные инструкции</h2> + +<p>Условная инструкция — это набор команд, которые выполняются, если указанное условие является истинным. JavaScript поддерживает две условные инструкции: <code style="font-style: normal;">if...else</code> и <code style="font-style: normal;">switch</code>.</p> + +<h3 id="Инструкция_if...else">Инструкция if...else</h3> + +<p>Используйте оператор <code>if</code> для выполнения инструкции, если логическое условия истинно. Используйте опциональный <code>else</code>, для выполнения инструкции, если условие ложно. Оператор if выглядит так:</p> + +<pre class="brush: js notranslate">if (condition) { + statement_1; +} else { + statement_2; +}</pre> + +<p> Здесь <code>condition</code> может быть любым выражением, вычисляемым как истинное (true) или ложное (false). Чтобы получить более подробную информацию о значениях <code>true </code>и <code>false</code>, прочитайте <a href="/ru/docs/Web/JavaScript/Reference/Global_Objects/Boolean#Description">Boolean</a>. Если условие оценивается как<code> true</code>, то выполняется <code>statement_1</code>, в противном случае -<code> statement_2</code>. Блоки <code>statement_1 </code>и<code> statement_2</code> могут быть любыми блоками, включая также вложенные инструкции <code>if</code>.</p> + +<p>Также вы можете объединить несколько инструкций, пользуясь <code>else if</code> для получения последовательности проверок условий:</p> + +<pre class="syntaxbox notranslate">if (condition_1) { statement_1;} else if (condition_2) { statement_2;} else if (condition_n) { statement_n; } else { statement_last;}</pre> + +<p>В случае нескольких условий только первое логическое условие, которое вычислится истинным (true), будет выполнено. Используйте блок ( <code>{ ... }</code> ) для группировки нескольких инструкций. Применение блоков является хорошей практикой, особенно когда используются вложенные инструкции <code>if</code>:</p> + +<pre style="font-size: 14px; white-space: normal;">if (condition) { + statement_1_runs_if_condition_is_true; + statement_2_runs_if_condition_is_true; +} else { + statement_3_runs_if_condition_is_false; + statement_4_runs_if_condition_is_false; +}</pre> + +<p>Нежелательно использовать простые присваивания в условном выражении, т.к. присваивание может быть спутано с равенством при быстром просмотре кода. Например, не используйте следующий код:</p> + +<pre class="brush: js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal; background-color: rgb(255, 255, 255);"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">if</span> <span class="punctuation token" style="color: #999999;">(</span>x <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> y<span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span><span class="punctuation token"> </span><span class="comment token" style="color: #708090;">/* ... */</span><span class="comment token"> </span><span class="punctuation token" style="color: #999999;">}</span> +</code></pre> + +<p>Если вам нужно использовать присваивание в условном выражении, то распространенной практикой является заключение операции присваивания в дополнительные скобки. Например:</p> + +<pre class="brush: js language-js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">if</span> <span class="punctuation token" style="color: #999999;">( </span><span class="punctuation token" style="color: #999999;">(</span>x <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> y<span class="punctuation token" style="color: #999999;">) </span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span><span class="punctuation token"> </span><span class="comment token" style="color: #708090;">/* ... */</span><span class="comment token"> </span><span class="punctuation token" style="color: #999999;">}</span></code></pre> + +<h4 id="Ложные_значения">Ложные значения</h4> + +<p>Следующие значения являются {{Glossary("Falsy", "ложными")}}:</p> + +<ul> + <li><code>false</code></li> + <li><code>undefined</code></li> + <li><code>null</code></li> + <li><code>0</code></li> + <li><code>NaN</code></li> + <li>пустая строка ( <code>""</code> )</li> +</ul> + +<p>Все остальные значения, включая все объекты, будут восприняты как истина при передаче в условное выражение.</p> + +<p>Не путайте примитивные логические значения <code>true</code> и <code>false</code> со значениями true и false объекта {{jsxref("Boolean")}}. Например:</p> + +<pre class="brush: js notranslate">var b = new Boolean(false); +if (b) // это условие true +if (b == true) // это условие false +</pre> + +<p>В следующем примере функция <code>checkData</code> возвращает <code>true</code>, если число символов в объекте <code>Text</code> равно трем; в противном случае функция отображает окно alert и возвращает <code>false</code>.</p> + +<pre class="brush: js language-js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">function</span> <span class="function token" style="color: #dd4a68;">checkData<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">if</span> <span class="punctuation token" style="color: #999999;">(</span>document<span class="punctuation token" style="color: #999999;">.</span>form1<span class="punctuation token" style="color: #999999;">.</span>threeChar<span class="punctuation token" style="color: #999999;">.</span>value<span class="punctuation token" style="color: #999999;">.</span>length <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">==</span> <span class="number token" style="color: #990055;">3</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">return</span> <span class="keyword token" style="color: #0077aa;">true</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="punctuation token" style="color: #999999;">}</span> <span class="keyword token" style="color: #0077aa;">else</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="function token" style="color: #dd4a68;">alert<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">"Enter exactly three characters. "</span> <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> + document<span class="punctuation token" style="color: #999999;">.</span>form1<span class="punctuation token" style="color: #999999;">.</span>threeChar<span class="punctuation token" style="color: #999999;">.</span>value <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> <span class="string token" style="color: #669900;">" is not valid."</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">return</span> <span class="keyword token" style="color: #0077aa;">false</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="punctuation token" style="color: #999999;">}</span> +<span class="punctuation token" style="color: #999999;">}</span></code></pre> + +<h3 id="Инструкция_switch">Инструкция switch</h3> + +<p>Инструкция <code>switch</code> позволяет сравнить значение выражения с различными вариантами и при совпадении выполнить соответствующий код. Инструкция имеет следующий вид:</p> + +<pre class="notranslate">switch (expression) { + case label_1: + statements_1 + [break;] + case label_2: + statements_2 + [break;] + ... + default: + statements_default + [break;] +} +</pre> + +<p>Сначала производится поиск ветви <code>case</code> с меткой <code>label</code>, совпадающей со значением выражения <code>expression</code>. Если совпадение найдено, то соответствующий данной ветви код выполняется до оператора <code>break</code>, который прекращает выполнение <code>switch</code> и передает управление дальше. В противном случае управление передается необязательной ветви <code>default</code> и выполняется соответствующий ей код. Если ветвь <code>default</code> не найдена, то программа продолжит выполняться со строчки, следующей за инструкцией <code>switch</code>. По соглашению ветвь <code>default</code> является последней ветвью, но следовать этому соглашению необязательно.</p> + +<p>Если оператор <code>break</code> отсутствует, то после выполнения кода, который соответствует выбранной ветви, начнется выполнение кода, который следует за ней.</p> + +<p>В следующем примере если <code>fruittype</code> имеет значение <code>"Bananas"</code>, то будет выведено сообщение<code> "Bananas are $0.48 a pound."</code> и оператор <code>break</code> прекратит выполнение <code>switch</code>. Если бы оператор <code>break</code> отсутствовал, то был бы также выполнен код, соответствующий ветви <code>"Cherries"</code>, т.е. выведено сообщение <code>"Cherries are $3.00 a pound."</code>.</p> + +<pre class="brush: js language-js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">switch</span> <span class="punctuation token" style="color: #999999;">(</span>fruittype<span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">case</span> <span class="string token" style="color: #669900;">"Oranges"</span><span class="punctuation token" style="color: #999999;">:</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">"Oranges are $0.59 a pound."</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">break</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">case</span> <span class="string token" style="color: #669900;">"Apples"</span><span class="punctuation token" style="color: #999999;">:</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">"Apples are $0.32 a pound."</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">break</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">case</span> <span class="string token" style="color: #669900;">"Bananas"</span><span class="punctuation token" style="color: #999999;">:</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">"Bananas are $0.48 a pound."</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">break</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">case</span> <span class="string token" style="color: #669900;">"Cherries"</span><span class="punctuation token" style="color: #999999;">:</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">"Cherries are $3.00 a pound."</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">break</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">case</span> <span class="string token" style="color: #669900;">"Mangoes"</span><span class="punctuation token" style="color: #999999;">:</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">"Mangoes are $0.56 a pound."</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">break</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">case</span> <span class="string token" style="color: #669900;">"Papayas"</span><span class="punctuation token" style="color: #999999;">:</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">"Mangoes and papayas are $2.79 a pound."</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">break</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">default</span><span class="punctuation token" style="color: #999999;">:</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">"Sorry, we are out of "</span> <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> fruittype <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> <span class="string token" style="color: #669900;">"."</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">}</span> +console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">"Is there anything else you'd like?"</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span></code></pre> + +<h2 id="Инструкции_обработки_исключений">Инструкции обработки исключений</h2> + +<p>Инструкция <code>throw</code> используется, чтобы выбросить исключение, а инструкция <code>try...catch</code>, чтобы его обработать.</p> + +<h3 id="Типы_исключений">Типы исключений</h3> + +<p>Практически любой объект может быть выброшен как исключение. Тем не менее, не все выброшенные объекты создаются равными. Обычно числа или строки выбрасываются как исключения, но часто более эффективным является использование одного из типов исключений, специально созданных для этой цели:</p> + +<ul> + <li><a href="/ru/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types">Исключения ECMAScript</a></li> + <li>{{domxref("DOMException")}} и {{domxref("DOMError")}}</li> +</ul> + +<h3 id="Инструкция_throw">Инструкция throw</h3> + +<p>Используйте инструкцию <code>throw</code>, чтобы выбросить исключение. При выбросе исключения нужно указать выражение, содержащее значение, которое будет выброшено:</p> + +<pre style="font-size: 14px; white-space: normal;">throw expression;</pre> + +<p>Вы можете выбросить любое выражение, а не только выражения определенного типа. В следующем примере выбрасываются исключения различных типов:</p> + +<pre class="brush: js language-js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">throw</span> <span class="string token" style="color: #669900;">"Error2"</span><span class="punctuation token" style="color: #999999;">;</span> <span class="comment token" style="color: #708090;"> // string +</span><span class="keyword token" style="color: #0077aa;">throw</span> <span class="number token" style="color: #990055;">42</span><span class="punctuation token" style="color: #999999;">;</span> <span class="comment token" style="color: #708090;"> // number +</span><span class="keyword token" style="color: #0077aa;">throw</span> <span class="keyword token" style="color: #0077aa;">true</span><span class="punctuation token" style="color: #999999;">;</span> <span class="comment token" style="color: #708090;"> // boolean +</span><span class="keyword token" style="color: #0077aa;">throw</span> <span class="punctuation token" style="color: #999999;">{ </span>toString<span class="punctuation token" style="color: #999999;">:</span> <span class="keyword token" style="color: #0077aa;">function</span><span class="punctuation token" style="color: #999999;">(</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> <span class="keyword token" style="color: #0077aa;">return</span> <span class="string token" style="color: #669900;">"I'm an object!"</span><span class="punctuation token" style="color: #999999;">;</span> <span class="punctuation token" style="color: #999999;">}</span> <span class="punctuation token" style="color: #999999;">}</span><span class="punctuation token" style="color: #999999;">; </span></code><code class="language-js" style="direction: ltr; white-space: pre;"><span class="comment token" style="color: #708090;">// object</span></code></pre> + +<div class="note"><strong>Примечание:</strong> Вы можете выбросить объект как исключение. Вы можете обращаться к свойствам данного объекта в блоке <code>catch</code>.</div> + +<p class="note">В следующем примере объект <code>UserException</code> выбрасывается как исключение:</p> + +<pre class="brush: js language-js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">function</span> UserException <span class="punctuation token" style="color: #999999;">(</span>message<span class="punctuation token" style="color: #999999;">) </span><span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">this</span><span class="punctuation token" style="color: #999999;">.</span>message <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">= </span>message<span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">this</span><span class="punctuation token" style="color: #999999;">.</span>name <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">= </span><span class="string token" style="color: #669900;">"UserException"</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">}</span> +<span class="comment token" style="color: #708090;"> +</span>UserException<span class="punctuation token" style="color: #999999;">.</span>prototype<span class="punctuation token" style="color: #999999;">.</span>toString <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="keyword token" style="color: #0077aa;">function</span> <span class="punctuation token" style="color: #999999;">(</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">return</span> <span class="keyword token" style="color: #0077aa;">this</span><span class="punctuation token" style="color: #999999;">.</span>name <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> <span class="string token" style="color: #669900;">': "'</span> <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> <span class="keyword token" style="color: #0077aa;">this</span><span class="punctuation token" style="color: #999999;">.</span>message <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> <span class="string token" style="color: #669900;">'"'</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">}</span> +<span class="comment token" style="color: #708090;"> +</span><span class="keyword token" style="color: #0077aa;">throw</span> <span class="keyword token" style="color: #0077aa;">new</span> <span class="class-name token">UserException</span><span class="punctuation token" style="color: #999999;">(</span><span class="string token" style="color: #669900;">"Value too high"</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span></code></pre> + +<h3 id="Инструкция_try...catch">Инструкция try...catch</h3> + +<p>Инструкция <code>try...catch</code> состоит из блока <code>try</code>, который содержит одну или несколько инструкций, и блок <code>catch</code>, которые содержит инструкции, определяющие порядок действий при выбросе исключения в блоке <code>try</code>. Иными словами, если в блоке <code>try</code> будет выброшено исключение, то управление будет передано в блок <code>catch</code>. Если в блоке <code>try</code> не возникнет исключений, то блок <code>catch</code> будет пропущен. Блок <code>finally</code> будет выполнен после окончания работы блоков <code>try</code> и <code>catch</code>, вне зависимости от того, было ли выброшено исключение.</p> + +<p>В следующем примере вызывается функция <code>getMonthName</code>, которая возвращает название месяца по его номеру. Если месяца с указанным номером не существует, то функция выбросит исключение <code>"InvalidMonthNo"</code>, которое будет перехвачено в блоке <code>catch</code>:</p> + +<pre class="brush: js notranslate">function getMonthName(mo) { + mo = mo - 1; // Adjust month number for array index (1 = Jan, 12 = Dec) + var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul", + "Aug","Sep","Oct","Nov","Dec"]; + if (months[mo]) { + return months[mo]; + } else { + throw "InvalidMonthNo"; //throw keyword is used here + } +} + +try { // statements to try + monthName = getMonthName(myMonth); // function could throw exception +} +catch (e) { + monthName = "unknown"; + logMyErrors(e); // pass exception object to error handler -> your own +} + +</pre> + +<h4 id="The_catch_Block" name="The_catch_Block">Блок <code>catch</code></h4> + +<p>Используйте блок <code>catch</code>, чтобы обработать исключения, сгенерированные в блоке <code>try</code>.</p> + +<pre style="font-size: 14px; white-space: normal;">catch (catchID) { statements }</pre> + +<p>JavaScript создает идентификатор <code>catchID</code>, которому присваивается перехваченное исключение, при входе в блок <code>catch</code>; данный идентификатор доступен только в пределах блока <code>catch</code> и уничтожается при выходе из него.</p> + +<p>В следующем примере выбрасывается исключение, которое перехватывается в блоке <code>catch</code>:</p> + +<pre class="brush: js language-js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">try</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">throw</span> <span class="string token" style="color: #669900;">"myException"</span><span class="comment token" style="color: #708090;"> +</span><span class="punctuation token" style="color: #999999;">}</span><span class="punctuation token"> </span><span class="keyword token" style="color: #0077aa;">catch</span> <span class="punctuation token" style="color: #999999;">(</span><span class="class-name token">e</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{ + </span></code><code class="language-js" style="direction: ltr; white-space: pre;">console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">error<span class="punctuation token" style="color: #999999;">(</span></span>e<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span></code><code class="language-js" style="direction: ltr; white-space: pre;"><span class="comment token" style="color: #708090;"> +</span><span class="punctuation token" style="color: #999999;">}</span></code></pre> + +<h4 id="Блок_finally">Блок <code>finally</code></h4> + +<p>Блок <code>finally</code> содержит код, который будет выполнен после окончания работы блоков <code>try</code> и <code>catch</code>, но до того, как будет выполнен код, который следует за инструкцией <code>try...catch</code>. Блок <code>finally</code> выполняется вне зависимости от того, было ли выброшено исключение. Блок <code>finally</code> выполняется даже в том случае, если исключение не перехватывается в блоке <code>catch</code>.</p> + +<p>В следующем примере открывается файл, затем в блоке <code>try</code> происходит вызов функции <code>writeMyFile</code>, который может выбросить исключение. Если возникает исключение, то оно обрабатывается в блоке <code>catch</code>. В любом случае файл будет закрыт функцией <code>closeMyFile</code>, вызов которой находится в блоке <code>finally</code>.</p> + +<pre class="brush: js language-js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="function token" style="color: #dd4a68;">openMyFile<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="keyword token" style="color: #0077aa;">try</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="function token" style="color: #dd4a68;">writeMyFile<span class="punctuation token" style="color: #999999;">(</span></span>theData<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> +</span><span class="punctuation token" style="color: #999999;">}</span> <span class="keyword token" style="color: #0077aa;">catch</span><span class="punctuation token" style="color: #999999;">(</span>e<span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="function token" style="color: #dd4a68;">handleError<span class="punctuation token" style="color: #999999;">(</span></span>e<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> +</span><span class="punctuation token" style="color: #999999;">}</span> <span class="keyword token" style="color: #0077aa;">finally</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="function token" style="color: #dd4a68;">closeMyFile<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> +</span><span class="punctuation token" style="color: #999999;">}</span></code></pre> + +<p>Если блок <code>finally</code> возвращает значение, то данное значение становится возвращаемым значением всей связки <code>try-catch-finally</code>. Значения, возвращаемые блоками <code>try</code> и <code>catch</code>, будут проигнорированы.</p> + +<pre class="brush: js language-js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">function</span> <span class="function token" style="color: #dd4a68;">f<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">try</span> <span class="punctuation token" style="color: #999999;">{</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="number token" style="color: #990055;">0</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">throw</span> <span class="string token" style="color: #669900;">"bogus"</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="punctuation token" style="color: #999999;">}</span> <span class="keyword token" style="color: #0077aa;">catch</span><span class="punctuation token" style="color: #999999;">(</span>e<span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="number token" style="color: #990055;">1</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">return</span> <span class="keyword token" style="color: #0077aa;">true</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // приостанавливается до завершения блока `finally`</span><span class="comment token" style="color: #708090;"> +</span> console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="number token" style="color: #990055;">2</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // не выполняется +</span> <span class="punctuation token" style="color: #999999;">}</span> <span class="keyword token" style="color: #0077aa;">finally</span> <span class="punctuation token" style="color: #999999;">{</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="number token" style="color: #990055;">3</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">return</span> <span class="keyword token" style="color: #0077aa;">false</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // заменяет предыдущий `return` +</span> console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="number token" style="color: #990055;">4</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // не выполняется +</span> <span class="punctuation token" style="color: #999999;">}</span> + <span class="comment token" style="color: #708090;"> // `return false` выполняется сейчас +</span> console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="number token" style="color: #990055;">5</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // не выполняется +</span><span class="punctuation token" style="color: #999999;">}</span> +<span class="function token" style="color: #dd4a68;">f<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // отображает 0, 1, 3 и возвращает `false`</span></code></pre> + +<p>Замена возвращаемых значений блоком <code>finally</code> распространяется в том числе и на исключения, которые выбрасываются или перевыбрасываются в блоке <code>catch</code>:</p> + +<pre class="brush: js language-js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">function</span> <span class="function token" style="color: #dd4a68;">f<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">try</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">throw</span> <span class="string token" style="color: #669900;">"bogus"</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="punctuation token" style="color: #999999;">}</span> <span class="keyword token" style="color: #0077aa;">catch</span><span class="punctuation token" style="color: #999999;">(</span>e<span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">'caught inner "bogus"'</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="keyword token" style="color: #0077aa;">throw</span> e<span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // приостанавливается до завершения блока `finally`</span><span class="comment token" style="color: #708090;"> +</span> <span class="punctuation token" style="color: #999999;">}</span> <span class="keyword token" style="color: #0077aa;">finally</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">return</span> <span class="keyword token" style="color: #0077aa;">false</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // заменяет предыдущий `throw` +</span> <span class="punctuation token" style="color: #999999;">}</span> + <span class="comment token" style="color: #708090;"> // `return false` выполняется сейчас +</span><span class="punctuation token" style="color: #999999;">}</span> + +<span class="keyword token" style="color: #0077aa;">try</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="function token" style="color: #dd4a68;">f<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">}</span> <span class="keyword token" style="color: #0077aa;">catch</span><span class="punctuation token" style="color: #999999;">(</span>e<span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="comment token" style="color: #708090;"> // Не выполняется, т.к. `throw` в `catch `заменяется на `return` в `finally`</span><span class="comment token" style="color: #708090;"> +</span> console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">'caught outer "bogus"'</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">}</span> +<span class="comment token" style="color: #708090;"> +// В результате отображается сообщение </span><span class="comment token" style="color: #708090;">caught inner "bogus" +// и возвращается значение `false`</span></code></pre> + +<h4 id="Nesting_try...catch_Statements" name="Nesting_try...catch_Statements">Вложенные инструкции <code>try...catch</code></h4> + +<p>Вы можете вкладывать инструкции <code>try...catch</code> друг в друга. Если внутренняя инструкция <code>try...catch</code> не имеет блока <code>catch</code>, то она должна иметь блок finally, кроме того исключение будет перехвачено во внешнем блоке <code>catch</code>. Для получения большей информации ознакомьтесь с вложенными <a href="/en-US/docs/Web/JavaScript/Reference/Statements/try...catch#Nested_try-blocks">try-блоками</a>.</p> + +<h3 id="Использование_объекта_Error">Использование объекта Error</h3> + +<p>В зависимости от типа ошибки вы можете использовать свойства <code>name</code> и <code>message</code>, чтобы получить более подробную информацию. Свойство <code>name</code> содержит название ошибки (например, <code>DOMException</code> или <code>Error</code>), свойство <code>message</code> — описание ошибки.</p> + +<p>Если вы выбрасываете собственные исключения, то чтобы получить преимущество, которое предоставляют эти свойства (например, если ваш блок <code>catch</code> не делает различий между вашими исключениями и системными), используйте конструктор <code>Error</code>. Например:</p> + +<pre class="brush: js language-js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">function</span> doSomethingErrorProne <span class="punctuation token" style="color: #999999;">(</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">if</span> <span class="punctuation token" style="color: #999999;">( </span><span class="function token" style="color: #dd4a68;">ourCodeMakesAMistake<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">) </span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">throw</span> <span class="punctuation token" style="color: #999999;">( </span><span class="keyword token" style="color: #0077aa;">new</span> <span class="class-name token">Error</span><span class="punctuation token" style="color: #999999;">(</span><span class="string token" style="color: #669900;">'The message'</span><span class="punctuation token" style="color: #999999;">) </span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="punctuation token" style="color: #999999;">}</span> <span class="keyword token" style="color: #0077aa;">else</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="function token" style="color: #dd4a68;">doSomethingToGetAJavascriptError<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="punctuation token" style="color: #999999;">}</span> +<span class="punctuation token" style="color: #999999;">} +</span> +<span class="keyword token" style="color: #0077aa;">try</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="function token" style="color: #dd4a68;">doSomethingErrorProne<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">}</span><span class="punctuation token"> </span><span class="keyword token" style="color: #0077aa;">catch</span> <span class="punctuation token" style="color: #999999;">(</span><span class="class-name token">e</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>e<span class="punctuation token" style="color: #999999;">.</span>name<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // 'Error' +</span> console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>e<span class="punctuation token" style="color: #999999;">.</span>message<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // 'The message' или JavaScript error message +</span><span class="punctuation token" style="color: #999999;">}</span></code></pre> + +<h2 id="Объект_Promise">Объект Promise</h2> + +<p>Начиная с ECMAScript2015, JavaScript поддерживает объект {{jsxref("Promise")}}, который используется для отложенных и асинхронных операций.</p> + +<p>Объект <code>Promise</code> может находиться в следующих состояниях:</p> + +<ul> + <li><em>ожидание (pending)</em>: начальное состояние, не выполнено и не отклонено.</li> + <li><em>выполнено (fulfilled)</em>: операция завершена успешно.</li> + <li><em>отклонено (rejected)</em>: операция завершена с ошибкой.</li> + <li><em>заданный (settled)</em>: обещание выполнено или отклонено, но не находится в состоянии ожидания.</li> +</ul> + +<p><img alt="" src="https://mdn.mozillademos.org/files/8633/promises.png" style="height: 297px; width: 801px;"></p> + +<h3 id="Загрузка_изображения_при_помощи_XHR">Загрузка изображения при помощи XHR</h3> + +<p>Простой пример использования объектов <code>Promise</code> и <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest">XMLHttpRequest</a></code> для загрузки изображения доступен в репозитории MDN <a href="https://github.com/mdn/js-examples/tree/master/promises-test">promise-test</a> на GitHub. Вы также можете <a href="https://mdn.github.io/js-examples/promises-test/">посмотреть его в действии</a>. Каждый шаг прокомментирован, что позволяет вам разобраться в архитектуре <code>Promise</code> и XHR. Здесь приводится версия без комментариев:</p> + +<pre class="brush: js language-js notranslate" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">function</span> <span class="function token" style="color: #dd4a68;">imgLoad<span class="punctuation token" style="color: #999999;">(</span></span>url<span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">return</span> <span class="keyword token" style="color: #0077aa;">new</span> <span class="class-name token">Promise</span><span class="punctuation token" style="color: #999999;">(</span><span class="keyword token" style="color: #0077aa;">function</span><span class="punctuation token" style="color: #999999;">(</span>resolve<span class="punctuation token" style="color: #999999;">,</span> reject<span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">var</span> request <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="keyword token" style="color: #0077aa;">new</span> <span class="class-name token">XMLHttpRequest</span><span class="punctuation token" style="color: #999999;">(</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + request<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">open<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">'GET'</span><span class="punctuation token" style="color: #999999;">,</span> url<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + request<span class="punctuation token" style="color: #999999;">.</span>responseType <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="string token" style="color: #669900;">'blob'</span><span class="punctuation token" style="color: #999999;">;</span> + request<span class="punctuation token" style="color: #999999;">.</span>onload <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="keyword token" style="color: #0077aa;">function</span><span class="punctuation token" style="color: #999999;">(</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">if</span> <span class="punctuation token" style="color: #999999;">(</span>request<span class="punctuation token" style="color: #999999;">.</span>status <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">===</span> <span class="number token" style="color: #990055;">200</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="function token" style="color: #dd4a68;">resolve<span class="punctuation token" style="color: #999999;">(</span></span>request<span class="punctuation token" style="color: #999999;">.</span>response<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="punctuation token" style="color: #999999;">}</span> <span class="keyword token" style="color: #0077aa;">else</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="function token" style="color: #dd4a68;">reject<span class="punctuation token" style="color: #999999;">(</span></span><span class="function token" style="color: #dd4a68;">Error<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">'Image didn\'t load successfully; error code:'</span> + <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> request<span class="punctuation token" style="color: #999999;">.</span>statusText<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="punctuation token" style="color: #999999;">}</span> + <span class="punctuation token" style="color: #999999;">}</span><span class="punctuation token" style="color: #999999;">;</span> + request<span class="punctuation token" style="color: #999999;">.</span>onerror <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="keyword token" style="color: #0077aa;">function</span><span class="punctuation token" style="color: #999999;">(</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="function token" style="color: #dd4a68;">reject<span class="punctuation token" style="color: #999999;">(</span></span><span class="function token" style="color: #dd4a68;">Error<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">'There was a network error.'</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="punctuation token" style="color: #999999;">}</span><span class="punctuation token" style="color: #999999;">;</span> + request<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">send<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="punctuation token" style="color: #999999;">}</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">}</span></code></pre> + +<p>{{PreviousNext("Web/JavaScript/Guide/Grammar_and_types", "Web/JavaScript/Guide/Loops_and_iteration")}}</p> diff --git a/files/ru/web/javascript/guide/details_of_the_object_model/index.html b/files/ru/web/javascript/guide/details_of_the_object_model/index.html new file mode 100644 index 0000000000..a5fda463eb --- /dev/null +++ b/files/ru/web/javascript/guide/details_of_the_object_model/index.html @@ -0,0 +1,723 @@ +--- +title: Подробнее об объектной модели +slug: Web/JavaScript/Guide/Details_of_the_Object_Model +translation_of: Web/JavaScript/Guide/Details_of_the_Object_Model +--- +<p>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Working_with_Objects", "Web/JavaScript/Guide/Ispolzovanie_promisov")}}</p> + +<p class="summary">JavaScript — это объектно-ориентированный язык, основанный на прототипировании, а не на классах. Из-за этого, менее очевидно то, каким образом JavaScript позволяет создавать иерархии объектов и обеспечивает наследование свойств и их значений. Эта глава является скромной попыткой прояснить ситуацию.</p> + +<p>Эта глава предполагает что читатель знаком с основами JavaScript, и имеет опыт использования функций для создания простейших объектов.</p> + +<h2 id="Языки_основанные_на_классах_против_Прототипно-ориентированных_языков">Языки, основанные на классах против Прототипно-ориентированных языков</h2> + +<p>Основанные на классах объектно-ориентированные языки программирования, такие как Java и C++, строятся на концепции двух отдельных сущностей: класс и экземпляр.</p> + +<ul> + <li><em>Класс</em> определяет все свойства (учитывая методы и все поля в Java, или свойства в C++), которые характеризуют группу объектов. Класс это абстрактная вещь, а не какой-либо конкретный член множества объектов, которые он описывает. Например, класс <code><span style="font-family: consolas,monaco,andale mono,monospace;">Employee</span></code> может описывать множество всех сотрудников.</li> + <li><em>Экземпляр</em>, это воплощение класса в виде конкретного объекта. Например, <font face="Consolas, Liberation Mono, Courier, monospace"><code>Victoria</code> </font>может быть экземпляром класса <code><span style="font-family: consolas,monaco,andale mono,monospace;">Employee</span></code>, представляющий собой конкретного сотрудника. Экземпляр класса имеет ровно столько свойств, сколько и родительский класс (не больше и не меньше).</li> +</ul> + +<p>Прототипно-ориентированный язык, например JavaScript, не реализует данное различие: он имеет только объекты. Языки, основанные на прототипах, имеют понятие <em>прототипа объекта — </em>это<em> </em>объект, используемый в качестве шаблона, с целью получить изначальные свойства для нового объекта. Любой объект может иметь собственные свойства, присвоенные либо во время создания, либо во время выполнения. В дополнение, любой объект может быть указан в качестве <em>прототипа </em>для другого объекта, это позволит второму объекту использовать свойства первого.</p> + +<h3 id="Определение_класса">Определение класса</h3> + +<p>В классо-ориентированных языках, вы можете <em>определить класс</em>. В этом определении вы можете указать специальные методы, называемые <em>конструкторами</em>, которые позволят создать экземпляр класса. Метод конструктор может задать начальные значения для свойств экземпляра и выполнять другие действия, в момент создания. Вы можете использовать оператор <code>new</code>, совместно с методом конструктора, для создания экземпляров классов.</p> + +<p>JavaScript использует похожую модель, но не имеет определения класса отдельно от конструктора. Вместо этого, вы определяете функцию-конструктор для создания объектов с начальным набором свойств и значений. Любая функция в JavaScript может быть использована, как конструктор. Вы должны использовать оператор <code>new</code> для создания нового объекта.</p> + +<h3 id="Подклассы_и_наследование">Подклассы и наследование</h3> + +<p>В языках, основанных на классах, вы создаете иерархию классов через объявление классов. В объявлении класса вы можете указать, что новый класс является <em>подклассом</em> уже существующего класса. При этом, подкласс унаследует все свойства суперкласса и в дополнение сможет добавить свои свойства или переопределить унаследованные. Например, предположим, что класс <code><span style="font-family: consolas,monaco,andale mono,monospace;">Employee</span></code> включает два свойства: <code>name</code> и <code>dept</code>, а класс <code><span style="font-family: consolas,monaco,andale mono,monospace;">Manager</span></code> является подклассом <code><span style="font-family: consolas,monaco,andale mono,monospace;">Employee</span></code> и добавляет свойство <code>reports</code>. В этом случае, экземпляр класса <code><span style="font-family: consolas,monaco,andale mono,monospace;">Manager</span></code> будет иметь три свойства: <code>name</code>, <code>dept</code>, и <code>reports</code>.</p> + +<p>JavaScript реализует наследование, позволяя связать прототипный объект с любой функцией-конструктором. Итак, вы можете создать объект точь-в-точь, как в примере <code><span style="font-family: consolas,monaco,andale mono,monospace;">Employee</span></code> — <code><span style="font-family: consolas,monaco,andale mono,monospace;">Manager</span></code>, но используя несколько иную технику. Для начала нужно определить функцию-конструктор <code><span style="font-family: consolas,monaco,andale mono,monospace;">Employee</span></code>, которая определяет свойства <code>name</code> и <code>dept</code>. Затем, определяем функцию-конструктор <code><span style="font-family: consolas,monaco,andale mono,monospace;">Manager</span></code>, в которой в свою очередь, будет явно вызываться конструктор <span style="font-family: consolas,monaco,andale mono,monospace;"><code>Employee</code> и</span> определяться новое свойство <code>reports</code>. Наконец, присваиваем новый экземпляр <code><span style="font-family: consolas,monaco,andale mono,monospace;">Employee</span></code>, в качестве <code>prototype</code> для функции-конструктора <code><span style="font-family: consolas,monaco,andale mono,monospace;">Manager</span></code>. Теперь, когда вы создадите нового <span style="font-family: consolas,monaco,andale mono,monospace;">Manager</span>, он унаследует свойства <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">name</span></font> и <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">dept</span></font> из объекта <code><span style="font-family: consolas,monaco,andale mono,monospace;">Employee</span></code>.</p> + +<h3 id="Добавление_и_удаление_свойств">Добавление и удаление свойств</h3> + +<p>В языках, основанных на классах, вы, как правило, создаете класс во время компиляции, а затем вы создаёте экземпляры класса либо во время компиляции, либо во время выполнения. Вы не можете изменить количество или тип свойств класса после определения класса. В JavaScript, однако, вы можете добавлять или удалять свойства любого объекта. Если вы добавляете свойство к объекту, который используется в качестве прототипа для множества объектов, то все эти объекты, для которых он является прототипом, также получат это свойство.</p> + +<h3 id="Подытожим_различия">Подытожим различия</h3> + +<p>Следующая таблица дает краткий обзор некоторых из этих различий. А оставшаяся часть этой главы описывает детали использования конструкторов и прототипов JavaScript для создания иерархии объектов и сравнивает это с тем, как вы могли бы сделать это в Java.</p> + +<table class="fullwidth-table"> + <caption>Сравнение языков на основе классов (Java) и на базе прототипов (JavaScript)</caption> + <thead> + <tr> + <th scope="col">Основанные на классах (Java)</th> + <th scope="col">Основанные на базе прототипов (JavaScript)</th> + </tr> + </thead> + <tbody> + <tr> + <td>Класс и экземпляр являются разными сущностями.</td> + <td>Все объекты могут наследовать свойства другого объекта.</td> + </tr> + <tr> + <td>Определяем класс с помощью определения класса; создаем экземпляр класса с помощью метода-конструктора.</td> + <td>Определение и создание объекта происходит с помощью функций-конcтрукторов.</td> + </tr> + <tr> + <td>Создание отдельного объекта с помощью оператора <code>new</code>.</td> + <td>Так же.</td> + </tr> + <tr> + <td>Иерархия объектов строится с помощью определения классов и их подклассов.</td> + <td> + <p>Построение иерархии объектов происходит путем присвоения объекта в качестве прототипа функции-конструктора.</p> + </td> + </tr> + <tr> + <td>Наследование свойств в цепочке классов.</td> + <td>Наследование свойств в цепочке прототипов.</td> + </tr> + <tr> + <td>Определение класса определяет <em>все</em> свойства всех экземпляров класса. Нельзя динамически добавлять свойства во время выполнения.</td> + <td>Функция-конструктор или прототип задает <em>начальный</em> набор свойств. Можно добавить или удалить свойства динамически к отдельным объектам или всей совокупности объектов.</td> + </tr> + </tbody> +</table> + +<h2 id="Пример_Сотрудник">Пример Сотрудник</h2> + +<p>Оставшаяся часть этой главы объясняет иерархию сотрудников, показанную на следующем рисунке:</p> + +<p><img alt="" class="internal" src="/@api/deki/files/4452/=figure8.1.png" style="height: 194px; width: 281px;"></p> + +<p><small><strong>Рисунок 8.1: Простая иерархия объектов</strong></small></p> + +<p>Этот пример использует следующие объекты:</p> + +<ul> + <li><code>Employee</code> имеет свойство <code>name</code> (значение которого по умолчанию пустая строка) и <code>dept</code> (значение которого по умолчанию "general").</li> + <li><code>Manager</code> основывается на <code>Employee</code>. Он добавляет свойство <code>reports</code> (значение которого по умолчанию пустой массив, предназначенный для хранения массива объектов <code>Employee</code>).</li> + <li><code>WorkerBee</code> так же основан на <code>Employee</code>. Он добавляет свойство <code>projects</code> (значение которого по умолчанию пустой массив, предназначенный для хранения строк).</li> + <li><code>SalesPerson</code> основан на <code>WorkerBee</code>. Он добавляет свойство <code>quota </code>(значение которого по умолчанию 100). Он также переопределяет свойство <code>dept</code>, со значением "sales", указывая, что все продавцы находятся в одном отделе.</li> + <li><code>Engineer</code> основан на <code>WorkerBee</code>. Он добавляет свойство <code>machine</code> (значение которого по умолчанию пустая строка), а так же определяет свойство <code>dept</code> значением "engineering".</li> +</ul> + +<h2 id="Создание_иерархии">Создание иерархии</h2> + +<p>Известно несколько способов определить подходящие функции-конструкторы, которые реализуют иерархию <code>Employee</code>. Выбор способа определения в большей степени зависит от того, на что рассчитано ваше приложение.</p> + +<p>В этом разделе приведены очень простые (и сравнительно не гибкие) определения, для демонстрации того, как же работает наследование. В этих определениях, вы не можете указать значения свойствам при создании объекта. Свойства вновь созданного объекта попросту получают значения по умолчанию, которые можно изменить позднее.</p> + +<p>В реальном приложении, вы, вероятно, будете определять конструкторы, которые позволяют устанавливать нужные вам значения свойств во время создания объекта (см <a href="#Более_гибкие_конструкторы">Более гибкие конструкторы</a>). В данном же случае конструкторы упрощены сознательно для того, чтобы сфокусироваться на сути наследования.</p> + +<p>Следующие определения <code>Employee</code> для языков Java и JavaScript довольно похожи. Единственное отличие состоит в том, что вам необходимо указать тип каждого свойства в Java, но не в JavaScript (потому что Java является <a href="https://ru.wikipedia.org/wiki/Сильная_и_слабая_типизация">строго типизированным языком</a>, в то время как JavaScript слабо типизированный).</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">JavaScript</th> + <th scope="col">Java</th> + </tr> + </thead> + <tbody> + <tr> + <td> + <pre class="brush: js"> +function Employee() { + this.name = ''; + this.dept = 'general'; +} +</pre> + </td> + <td> + <pre class="brush: java"> +public class Employee { + public String name = ""; + public String dept = "general"; +} +</pre> + </td> + </tr> + </tbody> +</table> + +<p>Определения классов <code>Manager</code> и <code>WorkerBee</code> показывают разницу в определении вышестоящего объекта в цепочке наследования. В JavaScript вводится связующий объект (прототипный экземпляр), который присваивается в качестве значения свойству <code>prototype </code>функции-конструктора. Вы можете сделать это в любое время после того, как вы создали конструктор. В Java, необходимо указать суперкласс внутри определения класса. Вы не можете изменить суперкласс вне определения класса.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">JavaScript</th> + <th scope="col">Java</th> + </tr> + </thead> + <tbody> + <tr> + <td> + <pre class="brush: js"> +function Manager() { + Employee.call(this); + this.reports = []; +} +//создаем пустой бъект с прототипом от коструктора Employee +//и используем этот объект как прототип для Manager +Manager.prototype = Object.create(Employee.prototype); + +Manager.prototype.constructor = Manager; + +function WorkerBee() { + Employee.call(this); + this.projects = []; +} +WorkerBee.prototype = Object.create(Employee.prototype); +WorkerBee.prototype.constructor = WorkerBee; +</pre> + </td> + <td> + <pre class="brush: java"> +public class Manager extends Employee { + public Employee[] reports = new Employee[0]; +} + +public class WorkerBee extends Employee { + public String[] projects = new String[0]; +} +</pre> + </td> + </tr> + </tbody> +</table> + +<p>Классы <code>Engineer</code> и <code>SalesPerson</code> создают объекты, которые происходят от <code>WorkerBee</code> и, следовательно, от <code>Employee</code>. Объект этих типов имеет свойства всех объектов, расположенных над ним в иерархии. Также, эти классы переопределяют наследуемое значение свойства <code>dept</code> своими значениями, характерными для этих объектов.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">JavaScript</th> + <th scope="col">Java</th> + </tr> + </thead> + <tbody> + <tr> + <td> + <pre class="brush: js"> +function SalesPerson() { + WorkerBee.call(this); + this.dept = 'sales'; + this.quota = 100; +} +SalesPerson.prototype = Object.create(WorkerBee.prototype); +SalesPerson.prototype.constructor = SalesPerson; + +function Engineer() { + WorkerBee.call(this); + this.dept = 'engineering'; + this.machine = ''; +} +Engineer.prototype = Object.create(WorkerBee.prototype); +Engineer.prototype.constructor = Engineer; +</pre> + </td> + <td> + <pre class="brush: java"> +public class SalesPerson extends WorkerBee { + public double quota; + public dept = "sales"; + public quota = 100.0; +} + +public class Engineer extends WorkerBee { + public String machine; + public dept = "engineering"; + public machine = ""; +} +</pre> + </td> + </tr> + <tr> + <td></td> + <td></td> + </tr> + </tbody> +</table> + +<p>Используя эти определения, вы можете создавать экземпляры объектов, которые получат значения по умолчанию для своих свойств. Рисунок 8.3 иллюстрирует использование этих определений и показывает значения свойств у полученных объектов.</p> + +<p>{{ note('Термин <em>экземпляр </em>имеет специфическое значение в языках, основанных на классах. В этих языках экземпляр — это индивидуальная сущность определенного класса и принципиально отличается от класса. В JavaScript «экземпляр» не имеет такого технического значения, потому что JavaScript не делает таких отличий между классами и экземплярами. Однако, в разговоре о JavaScript, термин «экземпляр» может неформально использоваться для обозначения объекта, созданного с использованием конкретной <span>функции конструктора. Так, в этом примере, вы можете неформально сказать, что <code>jane</code> является экземпляром <code>Engineer</code>. Аналогично, хотя термины <em>parent, child, ancestor</em> и <em>descendant</em> (<em>родитель, ребенок, предок</em> и <em>потомок</em>) не имеют формальных значений в JavaScript, вы можете использовать их неформально для ссылки на объекты выше или ниже</span> <span>в</span> <span>цепочке прототипов.') }}</span></p> + +<p><img alt="figure8.3.png" class="default internal" id="figure8.3" src="/@api/deki/files/4403/=figure8.3.png"><br> + <a id="8.3" name="8.3"><small><strong>Рисунок 8.3: Создание объектов с простыми определениями</strong></small></a></p> + +<h2 id="Свойства_объекта">Свойства объекта</h2> + +<p>Этот раздел о том, как объекты наследуют свойства из других объектов в цепочке прототипов, и что происходит, когда вы добавляете свойство во время выполнения.</p> + +<h3 id="Наследование_свойств">Наследование свойств</h3> + +<p>Предположим, вы создаете объект <code>mark</code> в качестве <code>WorkerBee</code> (как показано на <a href="#8.3">Рисунок 8.3</a>) с помощью следующего выражения:</p> + +<pre class="brush: js">var mark = new WorkerBee; +</pre> + +<p>Когда JavaScript видит оператор <code>new</code>, он создает новый обобщенный объект и неявно устанавливает значение внутреннего свойства [[Prototype]] в <code>WorkerkBee.prototype</code>, затем передает этот новый объект в качестве значения <code>this</code> в функцию-конструктор <code>WorkerBee</code>. Внутреннее свойство [[Prototype]] определяет цепочку прототипов, используемых для получения значений свойств. После того, как эти свойства установлены, JavaScript возвращает новый объект, а оператор присваивания устанавливает переменную <code>mark</code> для этого объекта.</p> + +<p>Этот процесс не задает значения свойств (<em>локальных</em> значений), которые унаследованы по цепочке прототипов, объекта <code>mark</code> напрямую. Когда вы запрашиваете значение свойства, JavaScript сначала проверяет, существует ли это значение в данном объекте. Если так и есть, тогда возвращается это значение. Если значение не найдено в самом объекте, JavaScript проверяет цепочку прототипов (используя внутреннее свойство [[Prorotype]]). Если объект в цепочке прототипов имеет значение для искомого свойства, это значение возвращается. Если такое свойство не найдено, JavaScript сообщает, что объект не обладает свойством. Таким образом, объект <code>mark</code> содержит следующие свойства и значения:</p> + +<pre class="brush: js">mark.name = ''; +mark.dept = 'general'; +mark.projects = []; +</pre> + +<p>Значения для свойств <code>name</code> и <code>dept</code> объекту <code>mark</code> присваиваются из конструктора <code>Employee</code>. Также из конструктора <code>WorkerBee</code> присваивается локальное значение для свойства <code>projects</code>. Это дает вам наследование свойств и их значений в JavaScript. Некоторые детали этого процесса обсуждаются в <a href="#Тонкости_наследования_свойств">Тонкости наследования свойств</a>.</p> + +<p>Поскольку эти конструкторы не позволяют вводить значения, специфичные для экземпляра, добавленная информация является общей. Значения свойств устанавливаются по умолчанию одинаковыми для всех объектов, созданных функцией <code>WorkerBee</code>. Конечно, вы можете изменить значения любого из этих свойств. Так, вы можете добавить специфичную информацию для <code>mark</code> следующим образом:</p> + +<pre class="brush: js">mark.name = 'Doe, Mark'; +mark.dept = 'admin'; +mark.projects = ['navigator'];</pre> + +<h3 id="Добавление_свойств">Добавление свойств</h3> + +<p>В JavaScript вы можете добавить свойства для любого объекта в реальном времени. Вы не ограничены только свойствами, установленными функцией-конструктором. Чтобы добавить свойство, специфичное для конкретного объекта, вы присваиваете ему значение в объекте, вот так:</p> + +<pre class="brush: js">mark.bonus = 3000; +</pre> + +<p>Теперь объект <code>mark</code> имеет свойство <code>bonus</code>, но никакой другой <code>WorkerBee</code> не имеет этого свойства.</p> + +<p>Если вы добавляете новое свойство в объект, который используется в качестве прототипа для функции-конструктора, вы добавляете это свойство для всех объектов, наследующих свойства из этого прототипа. Например, вы можете добавить свойство <code>specialty</code> для всех сотрудников с помощью следующего выражения:</p> + +<pre class="brush: js">Employee.prototype.specialty = 'none'; +</pre> + +<p>Как только JavaScript выполняет это выражение, объект <code>mark</code> также получает свойство <code>specialty</code> со значением <code>"none"</code>. Следующий рисунок показывает результат добавления этого свойства в прототип <code>Employee</code> и последующее переопределение его в прототипе <code>Engineer</code>.</p> + +<p><img alt="" class="internal" src="/@api/deki/files/4422/=figure8.4.png" style="height: 519px; width: 833px;"><br> + <small><strong>Рисунок 8.4: Добавление свойств</strong></small></p> + +<h2 id="Более_гибкие_конструкторы">Более гибкие конструкторы</h2> + +<p><span id="result_box" lang="ru"><span>Функции</span>-<span>конструкторы</span><span>, показанные</span> <span>до сих пор,</span> <span>не</span> <span>позволяют задавать</span> <span>значения</span> <span>свойств при создании</span> <span>экземпляра. Как и в</span> <span>Java</span><span>,</span> <span>вы можете передать</span> <span>аргументы в</span> <span>конструкторах</span> <span>для инициализации значений свойств</span><span> экземпляров</span><span>.</span> <span>На следующем рисунке показан</span> <span>один из способов сделать</span> <span>это</span><span>.</span></span></p> + +<p><img alt="" class="internal" id="figure8.5" src="/@api/deki/files/4423/=figure8.5.png" style="height: 481px; width: 1012px;"><br> + <a id="8.5" name="8.5"><small><strong>Рисунок 8.5: Определение свойств в конструкторе, вариант 1</strong></small></a></p> + +<p>Следующая таблица показывает определения для этих объектов в JavaScript и Java.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">JavaScript</th> + <th scope="col">Java</th> + </tr> + </thead> + <tbody> + <tr> + <td> + <pre class="brush: js"> +function Employee (name, dept) { + this.name = name || ''; + this.dept = dept || 'general'; +} +</pre> + </td> + <td> + <pre class="brush: java"> +public class Employee { + public String name; + public String dept; + public Employee () { + this("", "general"); + } + public Employee (String name) { + this(name, "general"); + } + public Employee (String name, String dept) { + this.name = name; + this.dept = dept; + } +} +</pre> + </td> + </tr> + <tr> + <td> + <pre class="brush: js"> +function WorkerBee (projs) { + + this.projects = projs || []; +} +WorkerBee.prototype = new Employee; +</pre> + </td> + <td> + <pre class="brush: java"> +public class WorkerBee extends Employee { + public String[] projects; + public WorkerBee () { + this(new String[0]); + } + public WorkerBee (String[] projs) { + projects = projs; + } +} + +</pre> + </td> + </tr> + <tr> + <td> + <pre class="brush: js"> + +function Engineer (mach) { + this.dept = 'engineering'; + this.machine = mach || ''; +} +Engineer.prototype = new WorkerBee; +</pre> + </td> + <td> + <pre class="brush: java"> +public class Engineer extends WorkerBee { + public String machine; + public Engineer () { + dept = "engineering"; + machine = ""; + } + public Engineer (String mach) { + dept = "engineering"; + machine = mach; + } +} +</pre> + </td> + </tr> + </tbody> +</table> + +<p>В JavaScript эти определения используют специальную идеому для установки значений по умолчанию:</p> + +<pre class="brush: js">this.name = name || ''; +</pre> + +<p>В JavaScript логический оператор ИЛИ (<code>||</code>) оценивает свой первый аргумент. Если этот аргумент преобразуется в true, оператор возвращает его. Иначе, оператор возвращает значение второго аргумента. Следовательно, эта строчка кода проверяет, содержит ли аргумент <code>name</code> значение, пригодное для свойства <code>name</code>. Если так и есть, <code>this.name</code> определяется этим значением. В противном случае, значению <code>this.name</code> присваивается пустая строка. Эта глава использует такую идиому для краткости; тем не менее, с первого взгляда она может озадачить.</p> + +<p>{{ note('Это может работать не так, как ожидается, если функция-конструктор вызывается с аргументами, которые преобразуются в <code><code>false</code></code>, вроде нуля (<code>0</code>) или пустой строки (<code>""</code>). В этом случае будет выбрано значение по умолчанию.') }}</p> + +<p>С помощью таких определений, создавая экземпляр объекта, вы можете указать значения для локально определенных свойств. Как показано на <a href="#8.5">Рисунок 8.5</a>, можно использовать следующее выражение для создания нового <code>Engineer</code>:</p> + +<pre class="brush: js">var jane = new Engineer('belau'); +</pre> + +<p>Свойства созданного объекта <code>jane</code>:</p> + +<pre class="brush: js">jane.name == ''; +jane.dept == 'engineering'; +jane.projects == []; +jane.machine == 'belau' +</pre> + +<p>Обратите внимание, что с таким способом вы не можете указать начальное значение наследуемого свойства, такого как <code>name</code>. Если вы хотите задать начальное значение для наследуемых свойств в JavaScript, вам нужно добавить больше кода в функцию-конструктор.</p> + +<p>До сих пор функция-конструктор создавала обобщенный объект, а затем определяла локальные свойства и значения для нового объекта. Вы можете использовать конструктор, который добавляет дополнительные свойства путем непосредственного вызова функции-конструктора для объекта, расположенного выше в цепочке прототипов. На следующем рисунке показаны эти новые определения.</p> + +<p><img alt="" class="internal" src="/@api/deki/files/4430/=figure8.6.png" style="height: 534px; width: 1063px;"><br> + <small><strong>Рисунок 8.6: Определение свойств в конструкторе, вариант 2</strong></small></p> + +<p>Давайте рассмотрим одно из этих определений детальнее. Вот новое определение функции-конструктора <code>Engineer</code>:</p> + +<pre class="brush: js">function Engineer (name, projs, mach) { + this.base = WorkerBee; + this.base(name, 'engineering', projs); + this.machine = mach || ''; +} +</pre> + +<p>Предположим, вы создаете новый объект, используя <code>Engineer, следующим образом:</code></p> + +<pre class="brush: js">var jane = new Engineer('Doe, Jane', ['navigator', 'javascript'], 'belau'); +</pre> + +<p>JavaScript <span id="result_box" lang="ru"><span>выполняет следующие действия</span><span>:</span></span></p> + +<ol> + <li>Оператор <code>new</code> создает обобщенный объект и устанавливает его свойству <code>__proto__</code> значение <code>Engineer.prototype</code>.</li> + <li>Оператор <code>new</code> передает этот новый объект в конструктор <code>Engineer</code> в качестве значения ключевого слова <code>this</code>.</li> + <li>Конструктор создает новое свойство с именем <code>base</code> для этого объекта и присваивает значение свойства <code>base</code> из конструктора <code>WorkerBee</code>. Это делает конструктор <code>WorkerBee</code> методом объекта, созданного <code>Engineer</code>. Имя свойства <code>base</code> не является специальным словом. Вы можете использовать любое допустимое для свойства имя; <code>base</code> всего-лишь напоминает о предназначении свойства.</li> + <li>Конструктор вызывает метод <code>base</code>, передавая в качестве аргументов два аргумента, переданных конструктору (<code>"Doe, Jane"</code> и <code>["navigator", "javascript"]</code>), а также строку <code>"engineering"</code>. Явное использование <code>"engineering"</code> в конструкторе указывает на то, что все объекты, созданные <code>Engineer</code>, имеют одинаковое значение для наследуемого свойства <code>dept</code>, это значение переопределяет значение, унаследованное из <code>Employee</code>.</li> + <li>Поскольку <code>base</code> является методом <code>Engineer</code>, внутри вызова <code>base</code> JavaScript привязывает ключевое свойство <code>this</code> к объекту, созданному в шаге 1. Таким образом, функция <code>WorkerBee</code> передает поочередно аргументы <code>"Doe, Jane"</code> и <code>"engineering"</code> в функцию-конструктор <code>Employee</code>. Получив результат из <code>Employee</code>, функция <code>WorkerBee</code> использует оставшийся аргумент для установки значения свойства <code>projects</code>.</li> + <li>После возвращения из метода <code>base</code>, конструктор <code>Engineer</code> инициализирует свойство объекта <code>machine</code> со значением <code>"belau"</code>.</li> + <li>После возвращения из конструктора, JavaScript присваивает новый объект переменной <code>jane</code>.</li> +</ol> + +<p>Можно подумать, что вызвав <code>WorkerBee</code> из конструктора <code>Engineer</code>, вы настроили соответствующим образом наследование для объектов, создаваемых <code>Engineer</code>. Это не так. Вызов конструктора <code>WorkerBee</code> обеспечивает только то, что объект <code>Engineer</code> запускается со свойствами, определенными во всех функциях-конструкторах, которые были вызваны. Так, если позже добавить свойства в прототипы <code>Employee</code> или <code>WorkerBee</code>, эти свойства не унаследуются объектами из <code>Engineer</code>. Например, предположим, вы использовали следующие определения:</p> + +<pre class="brush: js">function Engineer (name, projs, mach) { + this.base = WorkerBee; + this.base(name, 'engineering', projs); + this.machine = mach || ''; +} +var jane = new Engineer('Doe, Jane', ['navigator', 'javascript'], 'belau'); +Employee.prototype.specialty = 'none'; +</pre> + +<p>В примере выше <code>jane</code> не унаследует свойство <code>specialty</code>. Для динамического наследования необходимо явно устанавливать прототип, что и сделано в следующем дополнении:</p> + +<pre class="brush: js">function Engineer (name, projs, mach) { + this.base = WorkerBee; + this.base(name, 'engineering', projs); + this.machine = mach || ''; +} +Engineer.prototype = new WorkerBee; +var jane = new Engineer('Doe, Jane', ['navigator', 'javascript'], 'belau'); +Employee.prototype.specialty = "none"; +</pre> + +<p>Теперь свойство <code>specialty</code> объекта <code>jane</code> имеет значение "none".</p> + +<p>Другой способ вызвать родительский конструктор в контексте создаваемого объекта это использование методов <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Function/call" title="en-US/docs/JavaScript/Reference/Global Objects/Function/call"><code>call()</code></a> / <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply" title="en-US/docs/JavaScript/Reference/Global Objects/Function/apply"><code>apply()</code></a>. Следующие блоки эквивалентны:</p> + +<table> + <tbody> + <tr> + <td> + <pre class="brush: js"> +function Engineer (name, projs, mach) { + this.base = WorkerBee; + this.base(name, 'engineering', projs); + this.machine = mach || ''; +} +</pre> + </td> + <td> + <pre class="brush: js"> +function Engineer (name, projs, mach) { + WorkerBee.call(this, name, 'engineering', projs); + this.machine = mach || ''; +} +</pre> + </td> + </tr> + </tbody> +</table> + +<p>Использование метода <code>call()</code> является более чистой реализацией наследования, так как он не требует создания дополнителного свойства, именованного в примере как <code>base</code>.</p> + +<h2 id="Тонкости_наследования_свойств">Тонкости наследования свойств</h2> + +<p>В секции выше рассказывалось каким образом конструкторы и прототипы в JavaScript обеспечивают иерархию и наследование. В секции ниже будут затронуты тонкости, которые выше были не так очевидны.</p> + +<h3 id="Локальные_значения_против_унаследованных">Локальные значения против унаследованных</h3> + +<p>Когда вы пытаетесь получить значение некоторого свойства объекта, JavaScript выполняет следующие шаги, которые уже перечислялись ранее в этой главе:</p> + +<ol> + <li>Проверяется, существует ли локальное свойство с запрашиваемым именем. Если да, то возвращается значение этого свойства.</li> + <li>Если локального свойства не существует, проверяется цепочка прототипов (через использование свойства <code>__proto__</code>).</li> + <li>Если один из объектов в цепочке прототипов имеет свойство c запрашиваемым именем, возвращается значение этого свойства.</li> + <li>Если искомое свойство не обнаружено, считается, что объект его не имеет.</li> +</ol> + +<p>Результат выполнения этих шагов будет зависеть от того, в каком порядке вы создаете объекты, прототипы и их свойства. Рассмотрим пример:</p> + +<pre class="brush: js">function Employee () { + this.name = ""; + this.dept = "general"; +} + +function WorkerBee () { + this.projects = []; +} +WorkerBee.prototype = new Employee; +</pre> + +<p>Предположим, на основе конструкции выше, вы создаете объект <code>amy</code> как экземпляр класса <code>WorkerBee</code> следующим выражением:</p> + +<pre class="brush: js">var amy = new WorkerBee; +</pre> + +<p><code><font face="Open Sans, Arial, sans-serif">В результате, объект </font>amy</code> будет иметь одно локальное своство - <code>projects</code>. Свойства <code>name</code> и <code>dept</code> не будут локальными для <code>amy</code> но будут взяты из прототипа (объект на который ссылается свойство <code>__proto__</code> объекта <code>amy)</code>. Таким образом, <code>amy</code> имеет три свойства:</p> + +<pre class="brush: js">amy.name == ""; +amy.dept == "general"; +amy.projects == []; +</pre> + +<p>Теперь предположим, что вы изменили значение свойства <code>name</code> у прототипа <code>Employee</code>:</p> + +<pre class="brush: js">Employee.prototype.name = "Unknown" +</pre> + +<p>На первый взгляд вы можете ожидать, что это изменение распространится на все экземпляры <code>Employee</code>. Однако этого не случится.</p> + +<p>Когда вы устанавливаете прототип для <code>WorkerBee</code> вы создаете новый объект <code>Employee</code>, таким образом <code>WorkerBee.prototype</code> получает свое собственное локальное свойство <code>name</code> (в данном примере пустую строку). Следовательно, когда JavaScript ищет свойство <code>name</code> у объекта <code>amy</code> (экземпляра <code>WorkerBee</code>), он первым делом натыкается на него в прототипе <code>WorkerBee.prototype,</code> и до проверки <code>Employee.prototype</code> дело не доходит.</p> + +<p>Если у вас есть необходимость изменять некоторое свойство объекта во время работы приложения, и применять это изменение на все существующие экземпляры, не нужно создавать это свойство внутри конструктора. Вместо этого добавьте свойство в прототип, принадлежащий конструктору. Для примера, предположим, вы изменили код, который был показан выше, следующим образом:</p> + +<pre class="brush: js">function Employee () { + this.dept = "general"; +} +Employee.prototype.name = ""; + +function WorkerBee () { + this.projects = []; +} +WorkerBee.prototype = new Employee; + +var amy = new WorkerBee; + +Employee.prototype.name = "Unknown"; +</pre> + +<p>в таком случае свойство <code>name</code> у объекта <code>amy</code> примет значение "Unknown".</p> + +<p>Как показано в этом примере, если вы хотите иметь значения свойств по умолчанию, и иметь возможность менять эти значения во время работы приложения, создавайте их в прототипе конструктора, а не в самом конструкторе.</p> + +<h3 id="Разбираемся_во_взаимосвязи_экземпляров">Разбираемся во взаимосвязи экземпляров</h3> + +<p>Поиск свойств в JavaScript начинается с просмотра самого объекта, и если в нем свойство не найдено, поиск переключается на объект, на который указывает ссылка <code>__proto__</code>. Это продолжается рекурсивно и такой процесс поиска называется "поиск в цепочке прототипов".</p> + +<p>Специальное свойство <code>__proto__</code> устанавливается автоматически при создании объекта. Оно принимает значение свойства <code>prototype</code> функции-конструктора. Таким образом, <code>new Foo()</code> создаст объект для которого справедливо выражение <code>__proto__ == <code class="moz-txt-verticalline">Foo.prototype</code></code>. Вследствие этого, любые изменения свойств у <code class="moz-txt-verticalline">Foo.prototype,</code> оказывают эффект на процесс поиска свойств во всех объектах, созданных при помощи <code>new Foo()</code>.</p> + +<p>Все объекты (за исключением глобального объекта <code>Object</code>) имеют свойство <code>__proto__.</code> Все функции имеют свойство <code>prototype</code>. Благодаря этому, могут быть установлены родственные связи в иерархии объектов. Вы можете установить родство и происхождение объекта, сравнив его свойство <code>__proto__</code> со свойством <code>prototype</code> конструктора. Здесь JavaScript представляет оператор <code>instanceof</code> как более простой способ проверки, наследуется ли объект от конкретного конструктора. Для примера:</p> + +<pre class="brush: js">var f = new Foo(); +var isTrue = (f instanceof Foo);</pre> + +<p>Для более детального примера, предположим, у вас имеются те же определения, что приведены в разделе <a href="#Inheriting_properties">Inheriting properties</a>. Создадим экземпляр <code>Engineer</code> как показано здесь:</p> + +<pre class="brush: js">var chris = new Engineer("Pigman, Chris", ["jsd"], "fiji"); +</pre> + +<p>Для полученного объекта будут истинными все из следующих выражений:</p> + +<pre class="brush: js">chris.__proto__ == Engineer.prototype; +chris.__proto__.__proto__ == WorkerBee.prototype; +chris.__proto__.__proto__.__proto__ == Employee.prototype; +chris.__proto__.__proto__.__proto__.__proto__ == Object.prototype; +chris.__proto__.__proto__.__proto__.__proto__.__proto__ == null; +</pre> + +<p>Зная это, вы можете написать свою функцию <code>instanceOf</code> как показано ниже:</p> + +<pre class="brush: js">function instanceOf(object, constructor) { + object = object.__proto__; + while (object != null) { + if (object == constructor.prototype) + return true; + if (typeof object == 'xml') { + return constructor.prototype == XML.prototype; + } + object = object.__proto__; + } + return false; +} +</pre> + +<div class="note"><strong>Замечание:</strong> Реализация выше особым образом обрабатывает тип "xml". Это сделано для того, чтобы обойти особенность представления XML объектов в последних версиях JavaScript. Смотрите описание ошибки {{ bug(634150) }} если вам интересны детали.</div> + +<p>Следующие вызовы функции instanceOf, заданной выше, вернут истинные значения:</p> + +<pre>instanceOf (chris, Engineer) +instanceOf (chris, WorkerBee) +instanceOf (chris, Employee) +instanceOf (chris, Object) +</pre> + +<p>Но следующее выражение вернет <code>false</code>:</p> + +<pre class="brush: js">instanceOf (chris, SalesPerson) +</pre> + +<h3 id="Глобальные_данные_в_конструкторах">Глобальные данные в конструкторах</h3> + +<p>При написании конструкторов, следует с особым вниманием относиться к изменению глобальных переменных. Например, если вам нужен уникальный ID, который был бы автоматически назначен каждому экземпляру <code>Employee,</code> вы примените следующий подход для определения <code>Employee</code>:</p> + +<pre class="brush: js">var idCounter = 1; + +function Employee (name, dept) { + this.name = name || ""; + this.dept = dept || "general"; + this.id = idCounter++; +} +</pre> + +<p>Здесь, когда вы создаете новый экземпляр <code>Employee</code>, конструктор присваивает ему все новый и новый ID увеличивая значение глобальной переменной <code>idCounter</code>. Следовательно, при выполнении кода ниже, <code>victoria.id</code> станет равным 1 а <code>harry.id</code> — 2:</p> + +<pre class="brush: js">var victoria = new Employee("Pigbert, Victoria", "pubs") +var harry = new Employee("Tschopik, Harry", "sales") +</pre> + +<p>Навскидку, все выглядит предсказуемо. Однако, <code>idCounter</code> увеличивается при создании каждого объекта <code>Employee</code> вне зависимости от цели его создания. Если вы создаете полную иерархию класса <code>Employee,</code> показанную выше в этой главе, конструктор <code>Employee</code> будет так же вызван каждый раз, когда вы устанавливаете прототип для подклассов. Следующий код раскрывает суть возможной проблемы:</p> + +<pre class="brush: js">var idCounter = 1; + +function Employee (name, dept) { + this.name = name || ""; + this.dept = dept || "general"; + this.id = idCounter++; +} + +function Manager (name, dept, reports) {...} +Manager.prototype = new Employee; + +function WorkerBee (name, dept, projs) {...} +WorkerBee.prototype = new Employee; + +function Engineer (name, projs, mach) {...} +Engineer.prototype = new WorkerBee; + +function SalesPerson (name, projs, quota) {...} +SalesPerson.prototype = new WorkerBee; + +var mac = new Engineer("Wood, Mac"); +</pre> + +<p>Предположим, каждый из конструкторов, тело которого опущено для краткости, содержит вызов конструктора прародителя. Это приведет к тому, что <code>id</code> у объекта <code>mac</code> примет значение 5 вместо ожидаемой единицы.</p> + +<p>В зависимости от приложения, лишние увеличения счетчика могут быть не критичны. В случае же, когда точный контроль за значениями счетчика важен, одним из возможных решений станет такой код:</p> + +<pre class="brush: js">function Employee (name, dept) { + this.name = name || ""; + this.dept = dept || "general"; + if (name) + this.id = idCounter++; +} +</pre> + +<p>Когда вы создаете экземпляр <code>Employee</code> в качестве прототипа, вы не предоставляете аргументы в конструктор за ненадобностью. Конструктор выше проверяет наличие аргумента <code>name,</code> и в случае, если значение не указано, идентификатор id объекту не присваивается, а значение глобального счетчика <code>idCounter</code> не увеличивается. Таким образом, для получения уникального <code>id</code> становится обязательным указание параметра <code>name</code> при вызове конструктора <code>Employee</code>. С внесенными в пример выше изменениями, <code>mac.id</code> станет равным долгожданной, заветной единице.</p> + +<h3 id="Никакого_множественного_наследования">Никакого множественного наследования</h3> + +<p>Некоторые из объектно-ориентированных языков предоставляют возможность множественного наследования. Когда один объект может унаследовать свойства и методы множества других, не связанных друг с другом объектов. В JavaScript такого не предусмотрено.</p> + +<p>В JavaScript наследование свойств осуществляется путем поиска в цепочке прототипов. Так как объект может иметь лишь единственный присвоенный ему прототип, JavaScript не может осуществить наследование более чем от одной цепочки прототипов.</p> + +<p>Однако конструктор в JavaScript может вызывать любое количество вложенных конструкторов. Это дает некоторую, хоть и ограниченную (отсутствием прототипной связанности) видимость множественного наследования. Рассмотрим следуюший фрагмент:</p> + +<pre class="brush: js">function Hobbyist (hobby) { + this.hobby = hobby || "scuba"; +} + +function Engineer (name, projs, mach, hobby) { + this.base1 = WorkerBee; + this.base1(name, "engineering", projs); + this.base2 = Hobbyist; + this.base2(hobby); + this.machine = mach || ""; +} +Engineer.prototype = new WorkerBee; + +var dennis = new Engineer("Doe, Dennis", ["collabra"], "hugo") +</pre> + +<p>Предполагается, что определение <code>WorkerBee</code> задано ранее, как уже было показано в этой главе. В таком случае список свойств для объекта <code>dennis</code> примет следующий вид:</p> + +<pre class="brush: js">dennis.name == "Doe, Dennis" +dennis.dept == "engineering" +dennis.projects == ["collabra"] +dennis.machine == "hugo" +dennis.hobby == "scuba" +</pre> + +<p>Мы видим, что <code>dennis</code> получил свойство <code>hobby</code> из конструктора <code>Hobbyist</code>. Однако, если вы добавите любое свойство в прототип конструктора <code>Hobbyist</code>:</p> + +<pre class="brush: js">Hobbyist.prototype.equipment = ["mask", "fins", "regulator", "bcd"] +</pre> + +<p>Объект <code>dennis</code> этого свойства не унаследует.</p> + +<div>{{PreviousNext("Web/JavaScript/Guide/Working_with_Objects", "Web/JavaScript/Guide/Iterators_and_Generators")}}</div> diff --git a/files/ru/web/javascript/guide/expressions_and_operators/index.html b/files/ru/web/javascript/guide/expressions_and_operators/index.html new file mode 100644 index 0000000000..dea3cef0d6 --- /dev/null +++ b/files/ru/web/javascript/guide/expressions_and_operators/index.html @@ -0,0 +1,937 @@ +--- +title: Выражения и операторы +slug: Web/JavaScript/Guide/Expressions_and_Operators +tags: + - Beginner + - Expressions + - Guide + - Operators + - Начинающий +translation_of: Web/JavaScript/Guide/Expressions_and_Operators +--- +<p>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Functions", "Web/JavaScript/Guide/Numbers_and_dates")}}</p> + +<p class="summary">Эта глава описывает выражения и операторы языка JavaScript, такие как операторы присваивания, сравнения, арифметические, битовые, логические, строчные, и различные специальные операторы.</p> + +<ul> +</ul> + +<p>Полный и детальный список операторов и выражений также доступен в этом <a href="/ru/docs/Web/JavaScript/Reference/Operators">руководстве</a>.</p> + +<h2 id="Операторы">Операторы</h2> + +<p>В JavaScript есть следующие типы операторов. Данный подраздел описывает каждый тип и содержит информацию об их приоритетах друг над другом.</p> + +<ul> + <li>{{ web.link("#Операторы_присваивания", "Операторы присваивания") }}</li> + <li>{{ web.link("#Операторы_сравнения", "Операторы сравнения") }}</li> + <li>{{ web.link("#Арифметические_операторы", "Арифметические операторы") }}</li> + <li>{{ web.link("#Бинарные_операторы", "Бинарные операторы") }}</li> + <li>{{ web.link("#Логические_операторы", "Логические операторы") }}</li> + <li>{{ web.link("#Строковые_операторы", "Строковые операторы") }}</li> + <li>{{ web.link("#Условный_(тернарный)_оператор", "Условный (тернарный) оператор")}}</li> + <li>{{ web.link("#Оператор_запятая", "Оператор запятая")}}</li> + <li>{{ web.link("#Унарные_операторы", "Унарные операторы")}}</li> + <li>{{ web.link("#Операторы_отношения", "Операторы отношения")}}</li> + <li>{{ web.link("#Приоритет_операторов", "Приоритет операторов")}}</li> +</ul> + +<p>JavaScript поддерживает бинарные и унарные операторы, а также ещё один специальный тернарный оператор - условный оператор. Бинарная операция использует два операнда, один перед оператором и другой за ним:</p> + +<pre class="syntaxbox"><em>operand1</em> <em>operator</em> <em>operand2</em> +</pre> + +<p>Например: <code>3+4</code> или <code>x*y</code>.</p> + +<p>В свою очередь унарная операция использует один операнд, перед или после оператора:</p> + +<pre class="syntaxbox"><em>operator</em> <em>operand</em> +</pre> + +<p>или</p> + +<pre class="syntaxbox"><em>operand</em> <em>operator</em> +</pre> + +<p>Например: <code>x++</code> или <code>++x</code>.</p> + +<h3 id="Операторы_присваивания">Операторы присваивания</h3> + +<p>В результате операции присваивания операнду слева от <a href="/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators">оператора присваивания</a> (знак "=") устанавливается значение , которое берётся из правого операнда. Основным оператором присваивания является =, он присваивает значение правого операнда операнду, находящемуся слева. Таким образом, выражение x = y означает, что x присваивается значение y.</p> + +<p>Существуют также составные операторы присваивания, которые используются для сокращенного представления операций, описанных в следующей таблице:</p> + +<table class="standard-table"> + <caption>Список операторов присваивания</caption> + <tbody> + <tr> + <th>Имя</th> + <th>Сокращенный оператор</th> + <th>Смысл</th> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Assignment">Присваивание</a></td> + <td><code>x = y</code></td> + <td><code>x = y</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Addition_assignment">Присваивание со сложением</a></td> + <td><code>x += y</code></td> + <td><code>x = x + y</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Subtraction_assignment">Присваивание с вычитанием</a></td> + <td><code>x -= y</code></td> + <td><code>x = x - y</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Multiplication_assignment">Присваивание с умножением</a></td> + <td><code>x *= y</code></td> + <td><code>x = x * y</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Division_assignment">Присваивание с делением</a></td> + <td><code>x /= y</code></td> + <td><code>x = x / y</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Remainder_assignment">Присваивание по модулю</a></td> + <td><code>x %= y</code></td> + <td><code>x = x % y</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Left_shift_assignment">Присваивание с левым сдвигом</a></td> + <td><code>x <<= y</code></td> + <td><code>x = x << y</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Right_shift_assignment">Присваивание с правым сдвигом</a></td> + <td><code>x >>= y</code></td> + <td><code>x = x >> y</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Unsigned_right_shift_assignment">Присваивание с беззнаковым сдвигом вправо</a></td> + <td><code>x >>>= y</code></td> + <td><code>x = x >>> y</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Bitwise_AND_assignment">Присваивание с побитовым AND</a></td> + <td><code>x &= y</code></td> + <td><code>x = x & y</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Bitwise_XOR_assignment">Присваивание с побитовым XOR</a></td> + <td><code>x ^= y</code></td> + <td><code>x = x ^ y</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Bitwise_OR_assignment">Присваивание с побитовым OR</a></td> + <td><code>x |= y</code></td> + <td><code>x = x | y</code></td> + </tr> + </tbody> +</table> + +<h4 id="Деструктуризация">Деструктуризация</h4> + +<p>Для более сложного присваивания в JavaScript есть синтаксис <a href="/ru/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">деструктуризации</a> - это выражение, которое позволяет извлекать данные из массивов или объектов, используя синтаксис, который зеркалирует конструкторы массивов и литералы объектов.</p> + +<pre class="brush: js">var foo = ["one", "two", "three"]; + +// без деструктуризации +var one = foo[0]; +var two = foo[1]; +var three = foo[2]; + +// с деструктуризацией +var [one, two, three] = foo;</pre> + +<h3 id="Операторы_сравнения">Операторы сравнения</h3> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Operators/Comparison_Operators">Оператор сравнения</a> сравнивает свои операнды и возвращает логическое значение, базируясь на истинности сравнения. Операнды могут быть числами, строками, логическими величинами или объектами. Строки сравниваются на основании стандартного лексикографического порядка, используя Unicode-значения. В большинстве случаев, если операнды имеют разный тип, то JavaScript пробует преобразовать их в тип, подходящий для сравнения. Такое поведение обычно происходит при сравнении числовых операндов. Единственным исключением из данного правила является сравнение с использованием операторов <code>===</code> и <code>!==</code>, которые производят строгое сравнение на равенство или неравенство. Эти операторы не пытаются преобразовать операнды перед их сравнением. Следующая таблица описывает операторы сравнения в контексте следующего примера кода:</p> + +<pre class="brush: js">var var1 = 3, var2 = 4; +</pre> + +<table class="standard-table"> + <caption>Операторы сравнения</caption> + <thead> + <tr> + <th scope="col">Оператор</th> + <th scope="col">Описание</th> + <th scope="col">Примеры, возвращающие true</th> + </tr> + </thead> + <tbody> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Операторы_сравнения#Equality">Равно</a> (<code>==</code>)</td> + <td>Возвращает true, если операнды равны.</td> + <td><code>3 == var1</code><br> + <code>"3" == var1</code><br> + <code>3 == '3'</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Операторы_сравнения#Inequality">Не равно</a> (<code>!=</code>)</td> + <td>Возвращает true, если операнды не равны.</td> + <td><code>var1 != 4<br> + var2 != "3"</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Операторы_сравнения#Identity">Строго равно</a> (<code>===</code>)</td> + <td>Возвращает true, если операнды равны и имеют одинаковый тип. См. также {{jsxref("Object.is")}} и <a href="/ru/docs/Web/JavaScript/Equality_comparisons_and_sameness" title="/ru/docs/Web/JavaScript/Guide/Sameness">sameness in JS</a>.</td> + <td><code>3 === var1</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Операторы_сравнения#Nonidentity">Строго не равно</a>(<code>!==</code>)</td> + <td>Возвращает true, если операнды не равны и/или имеют разный тип.</td> + <td><code>var1 !== "3"<br> + 3 !== '3'</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Операторы_сравнения#Greater_than_operator">Больше</a> (<code>></code>)</td> + <td>Возвращает true, если операнд слева больше операнда справа.</td> + <td><code>var2 > var1<br> + "12" > 2</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Операторы_сравнения#Greater_than_or_equal_operator">Больше или равно</a> (<code>>=</code>)</td> + <td>Возвращает true, если операнд слева больше или равен операнду справа.</td> + <td><code>var2 >= var1<br> + var1 >= 3</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Операторы_сравнения#Less_than_operator">Меньше</a> (<code><</code>)</td> + <td>Возвращает true, если операнд слева меньше операнда справа.</td> + <td><code>var1 < var2<br> + "2" < 12</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Операторы_сравнения#Less_than_or_equal_operator">Меньше или равно</a> (<code><=</code>)</td> + <td>Возвращает true, если операнд слева меньше или равен операнду справа.</td> + <td><code>var1 <= var2<br> + var2 <= 5</code></td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>Замечание: </strong>(<strong>=></strong>) не оператор, а нотация <a href="/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions">Стрелочных функций</a>.</p> +</div> + +<h3 id="Арифметические_операторы">Арифметические операторы</h3> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators">Арифметические операторы</a> используют в качестве своих операндов числа (также литералы или переменные) и в качестве результата возвращают одно числовое значение. Стандартными арифметическими операторами являются сложение (+), вычитание (-), умножение (*), и деление (/). При работе с числами с плавающей точкой эти операторы работают аналогично их работе в большинстве других языках программирования (обратите внимание, что деление на ноль возвращает бесконечность {{jsxref("Infinity")}}). Например:</p> + +<pre class="brush: js">console.log(1 / 2); /* возвращает 0.5 */ +console.log(1 / 2 == 1.0 / 2.0); /* возвращает true */ +</pre> + +<p>Кроме того, JavaScript позволяет использовать следующие арифметические операторы, представленные в таблице:</p> + +<table class="fullwidth-table"> + <caption>Арифметические операторы</caption> + <thead> + <tr> + <th scope="col">Оператор</th> + <th scope="col">Описание</th> + <th scope="col">Пример</th> + </tr> + </thead> + <tbody> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Remainder">Остаток от деления</a> (<code>%</code>)</td> + <td>Бинарный оператор. Возвращает целочисленный остаток от деления двух операндов.</td> + <td>12 % 5 вернёт 2.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Increment">Инкремент</a> (<code>++</code>)</td> + <td>Унарный оператор. Добавляет единицу к своему операнду. Если используется в качестве префикса (<code>++x</code>), то возвращает значение операнда с добавленной к нему единицей; а в случае применения в качестве окончания (<code>x++</code>) возвращает значение операнда перед добавлением к нему единицы.</td> + <td><code>Если x</code> равно 3, тогда <code>++x</code> установит значение <code>x</code> равным 4 и вернёт 4, напротив <code>x++</code> вернёт 3 и потом установит значение <code>x</code> равным 4.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Decrement">Декремент</a> (<code>--</code>)</td> + <td>Унарный оператор. Вычитает единицу из значения своего операнда. Логика данного оператора аналогична оператору инкремента.</td> + <td>Если <code>x</code> равно 3, тогда <code>--x</code> установит значение <code>x</code> равным 2 и вернёт 2, напротив <code>x--</code> вернёт 3 и потом установит значение <code>x</code> равным 2.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_negation">Унарный минус</a><code>-</code></td> + <td>Унарный оператор. Возвращает отрицательное значение своего операнда.</td> + <td>Если <code>x</code> равно 3, тогда <code>-x</code> вернёт -3.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_plus">Унарный плюс</a> (<code>+</code>)</td> + <td>Унарный оператор. Пытается конвертировать операнд в число, если он ещё не оно.</td> + <td><code>+"3"</code> вернёт <code>3</code>.<br> + <code>+true</code> вернёт <code>1.</code></td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Exponentiation">Возведение в степень</a> (<code>**</code>) {{experimental_inline}}</td> + <td>Возводит <code>основание</code> в показатель <code>степени</code>, как, <code>основание<sup>степень</sup></code></td> + <td><code>2 ** 3</code> вернёт <code>8</code>.<br> + <code>10 ** -1</code> вернёт <code>0.1</code>.</td> + </tr> + </tbody> +</table> + +<h3 id="Битовые_(поразрядные)_операторы">Битовые (поразрядные) операторы</h3> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators">Битовые операторы</a> обрабатывают свои операнды как последовательности из 32 бит (нулей и единиц), а не как десятичные, шестнадцатеричные или восьмеричные числа. Например, десятичное число 9 имеет двоичное представление 1001. Битовые операторы выполняют операции над таким двоичным представлением, но результат возвращают как обычное числовое значение JavaScript.</p> + +<p>Следующая таблица обобщает битовые операторы JavaScript.</p> + +<table class="standard-table"> + <caption>Битовые операторы</caption> + <thead> + <tr> + <th scope="col">Оператор</th> + <th scope="col">Использование</th> + <th scope="col">Описание</th> + </tr> + </thead> + <tbody> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_AND">Побитовое И</a></td> + <td><code>a & b</code></td> + <td>Возвращает единицу в каждой битовой позиции, для которой соответствующие биты обеих операндов являются единицами.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_OR">Побитовое ИЛИ </a></td> + <td><code>a | b</code></td> + <td>Возвращает единицу в каждой битовой позиции, для которой один из соответствующих битов или оба бита операндов являются единицами.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_XOR">Исключающее ИЛИ</a></td> + <td><code>a ^ b</code></td> + <td>Возвращает единицу в каждой битовой позиции, для которой только один из соответствующих битов операндов является единицей.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_NOT">Побитовое НЕ</a></td> + <td><code>~ a</code></td> + <td>Заменяет биты операнда на противоположные.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Left_shift">Сдвиг влево</a></td> + <td><code>a << b</code></td> + <td>Сдвигает <code>a</code> в двоичном представлении на <code>b</code> бит влево, добавляя справа нули.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Right_shift">Сдвиг вправо с переносом знака</a></td> + <td><code>a >> b</code></td> + <td>Сдвигает <code>a</code> в двоичном представлении на <code>b</code> бит вправо, отбрасывая сдвигаемые биты.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Unsigned_right_shift">Сдвиг вправо с заполнением нулями</a></td> + <td><code>a >>> b</code></td> + <td>Сдвигает <code>a</code> в двоичном представлении на <code>b</code> бит вправо, отбрасывая сдвигаемые биты и добавляя слева нули.</td> + </tr> + </tbody> +</table> + +<h4 id="Bitwise_Logical_Operators" name="Bitwise_Logical_Operators">Битовые логические операторы</h4> + +<p>Основной смысл работы битовых логических операторов состоит в следующем:</p> + +<ul> + <li>Операнды преобразуются в 32-битные целые числа и представляются в виде последовательности бит (нулей и единиц). Числа, имеющие более 32 битов будут сокращены. Например, следующее число имеет больше 32 битов и сконвертируется в 32-х битное: + <pre class="brush: html">До : 11100110111110100000000000000110000000000001 +После : 10100000000000000110000000000001</pre> + </li> + <li>Каждый бит первого операнда связывается с соответствующим битом второго операнда: первый бит с первым битом, второй бит - со вторым, и так далее.</li> + <li>К каждой паре бит применяется заданный оператор, и побитово формируется итоговый результат.</li> +</ul> + +<p>Например, двоичным представлением числа 9 является 1001, а двоичным представлением пятнадцати - 1111. Результаты применения к этим числам битовых логических операторов выглядят следующим образом:</p> + +<table class="standard-table"> + <caption>Примеры работы битовых операторов</caption> + <thead> + <tr> + <th scope="col">Выражение</th> + <th scope="col">Результат</th> + <th scope="col">Двоичное описание</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>15 & 9</code></td> + <td><code>9</code></td> + <td><code>1111 & 1001 = 1001</code></td> + </tr> + <tr> + <td><code>15 | 9</code></td> + <td><code>15</code></td> + <td><code>1111 | 1001 = 1111</code></td> + </tr> + <tr> + <td><code>15 ^ 9</code></td> + <td><code>6</code></td> + <td><code>1111 ^ 1001 = 0110</code></td> + </tr> + <tr> + <td><code>~15</code></td> + <td><code>-16</code></td> + <td><code>~</code><code>00000000...</code><code>00001111 = </code><code>1111</code><code>1111</code><code>...</code><code>11110000</code></td> + </tr> + <tr> + <td><code>~9</code></td> + <td><code>-10</code></td> + <td><code>~</code><code>00000000</code><code>...</code><code>0000</code><code>1001 = </code><code>1111</code><code>1111</code><code>...</code><code>1111</code><code>0110</code></td> + </tr> + </tbody> +</table> + +<p>Обратите внимание, что все 32 бита преобразуются с использованием битового оператора НЕ, и что величины с наиболее значимым (самым левым) битом равным 1 представляют собой отрицательные числа (в представлении дополнения до двух).</p> + +<h4 id="Bitwise_Shift_Operators" name="Bitwise_Shift_Operators">Битовые операторы сдвига</h4> + +<p>Битовые операторы сдвига используют два операнда: первый представляет величину, подлежащую сдвигу, а второй операнд указывает число битовых позиций на которое должен быть сдвинут первый операнд. Направление операции сдвига определяется используемым оператором.</p> + +<p>Операторы сдвига преобразуют свои операнды в 32-битные целые числа и возвращают результат того же типа, каким является левый операнд.</p> + +<p>Операторы сдвига перечислены в следующей таблице.</p> + +<table class="fullwidth-table"> + <caption>Битовые операторы сдвига</caption> + <thead> + <tr> + <th scope="col">Оператор</th> + <th scope="col">Описание</th> + <th scope="col">Пример</th> + </tr> + </thead> + <tbody> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#<<_(Left_shift)">Сдвиг влево</a><br> + (<code><<</code>)</td> + <td>Данный оператор сдвигает первый операнд на указанное количество бит влево. Излишние биты, сдвинутые влево, отбрасываются. Справа число дополняется нулевыми битами.</td> + <td><code>9<<2</code> равно 36, так как 1001 после сдвига на 2 бита влево превращается в 100100, что соответствует числу 36.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#>>_(Sign-propagating_right_shift)">Сдвиг вправо с переносом знака</a> (<code>>></code>)</td> + <td>Данный оператор сдвигает первый операнд на указанное количество бит вправо. Излишние биты, сдвинутые вправо, отбрасываются. Слева число дополняется копиями крайнего слева бита.</td> + <td><code>9>>2</code> равно 2, так как 1001 после сдвига на 2 бита вправо превращается в 10, что соответствует числу 2. Подобным же образом <code>-9>>2</code> равно -3, так как знак сохраняется.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#>>>_(Zero-fill_right_shift)">Сдвиг вправо с заполнением нулями</a> (<code>>>></code>)</td> + <td>Данный оператор сдвигает первый операнд на указанное количество бит вправо. Излишние биты, сдвинутые вправо, отбрасываются. Слева число дополняется нулевыми битами.</td> + <td><code>19>>>2</code> равно 4, так как 10011 после сдвига на 2 бита вправо превращается в 100, что соответствует числу 4. Для неотрицательных чисел сдвиг вправо с заполнением нулями и сдвиг вправо с переносом знака дают одинаковый результат.</td> + </tr> + </tbody> +</table> + +<h3 id="Логические_операторы">Логические операторы</h3> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Operators/Logical_Operators">Логические операторы</a> обычно используются с булевыми (логическими) значениями; при этом возвращаемое ими значение также является булевым. Однако операторы && и || фактически возвращают значение одного из операндов, поэтому, если эти операторы используются с небулевыми величинами, то возвращаемая ими величина также может быть не булевой. Логические операторы описаны в следующей таблице.</p> + +<table class="fullwidth-table"> + <caption>Логические операторы</caption> + <thead> + <tr> + <th scope="col">Оператор</th> + <th scope="col">Использование</th> + <th scope="col">Описание</th> + </tr> + </thead> + <tbody> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_AND">Логическое И</a><code> </code>(<code>&&</code>)</td> + <td><code>expr1 && expr2</code></td> + <td>(Логическое И) Возвращает операнд <code>expr1</code>, если он может быть преобразован в <code>false</code>; в противном случае возвращает операнд <code>expr2</code>. Таким образом, при использовании булевых величин в качестве операндов, оператор <code>&&</code> возвращает <code>true</code>, если оба операнда <code>true</code>; в противном случае возвращает <code>false</code>.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_OR">Логическое ИЛИ </a>(<code>||</code>)</td> + <td><code>expr1 || expr2</code></td> + <td>(Логическое ИЛИ) Возвращает операнд <code>expr1</code>, если он может быть преобразован в <code>true</code>; в противном случае возвращает операнд <code>expr2</code>. Таким образом, при использовании булевых величин в качестве операндов, оператор <code>||</code> возвращает <code>true</code>, если один из операндов <code>true</code>; если же оба <code>false</code>, то возвращает <code>false</code>.</td> + </tr> + <tr> + <td><a href="/ru/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_NOT">Логическое НЕ </a>(<code>!</code>)</td> + <td><code>!expr</code></td> + <td>(Логическое НЕ) Возвращает <code>false</code>, если операнд может быть преобразован в <code>true</code>; в противном случае возвращает <code>true</code>.</td> + </tr> + </tbody> +</table> + +<p>Примерами выражений, которые могут быть преобразованы в false являются: null, 0, NaN, пустая строка ("") или undefined.</p> + +<p>Следующий код демонстрирует примеры использования оператора && (логическое И).</p> + +<pre class="brush: js">var a1 = true && true; // t && t возвращает true +var a2 = true && false; // t && f возвращает false +var a3 = false && true; // f && t возвращает false +var a4 = false && (3 == 4); // f && f возвращает false +var a5 = "Cat" && "Dog"; // t && t возвращает Dog +var a6 = false && "Cat"; // f && t возвращает false +var a7 = "Cat" && false; // t && f возвращает false +</pre> + +<p>Следующий код демонстрирует примеры использования оператора || (логическое ИЛИ).</p> + +<pre class="brush: js">var o1 = true || true; // t || t возвращает true +var o2 = false || true; // f || t возвращает true +var o3 = true || false; // t || f возвращает true +var o4 = false || (3 == 4); // f || f возвращает false +var o5 = "Cat" || "Dog"; // t || t возвращает Cat +var o6 = false || "Cat"; // f || t возвращает Cat +var o7 = "Cat" || false; // t || f возвращает Cat +</pre> + +<p>Следующий код демонстрирует примеры использования оператора ! (логическое НЕ).</p> + +<pre class="brush: js">var n1 = !true; // !t возвращает false +var n2 = !false; // !f возвращает true +var n3 = !"Cat"; // !t возвращает false +</pre> + +<h4 id="Short-Circuit_Evaluation" name="Short-Circuit_Evaluation">Сокращённая оценка</h4> + +<p>Так как логические выражения вычисляются слева направо, они проверяются на возможность выполнения сокращённой оценки с использованием следующих правил:</p> + +<ul> + <li><code>false</code> && anything<em> - </em>сокращение с результатом false.</li> + <li><code>true</code> || <em>anything - </em>сокращение с результатом true.</li> +</ul> + +<p>Правила логики гарантируют, что данные вычисления всегда корректны. Обратите внимание, что часть "<em>anything"</em> представленных выше выражений не вычисляется, таким образом удается избежать любых побочных эффектов вычисления данной части.</p> + +<h3 id="Строковые_операторы">Строковые операторы</h3> + +<p>В дополнение к операторам сравнения, которые могут использоваться со строковыми значениями, оператор (+) позволяет объединить две строки, возвращая при этом третью строку, которая представляет собой объединение двух строк-операндов:</p> + +<pre class="brush: js">console.log("my " + "string"); // в консоли выведется строка "my string".</pre> + +<p>Сокращенный оператор присваивания += также может быть использован для объединения (конкатенации) строк:</p> + +<pre class="brush: js">var mystring = "alpha"; mystring += "bet"; // получается значение "alphabet" и присваивается mystring. +</pre> + +<h3 id="Условный_(тернарный)_оператор" name="Условный_(тернарный)_оператор">Условный (тернарный) оператор</h3> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">Условный оператор</a> является единственным оператором JavaScript, который использует три операнда. Оператор принимает одно из двух значений в зависимости от заданного условия. Синтаксис оператора:</p> + +<pre class="syntaxbox"><em>condition</em> ? <em>val1</em> : <em>val2</em> +</pre> + +<div class="warning"> +<p><em> val1 и val2 обязательно должны что-то возвращать, поэтому в этой конструкции нельзя использовать continue или break</em></p> +</div> + +<p>Если <code>condition (условие)</code> - истина, то оператор принимает значение <code>val1</code>. В противном случае оператор принимает значение <code>val2</code>. Вы можете использовать условный оператор во всех случаях, где может быть использован стандартный оператор.</p> + +<pre class="brush: js">var status = (age >= 18) ? "adult" : "minor"; +</pre> + +<p>Данное выражение присваивает значение "adult" переменной <code>status</code>, если <code>age</code> имеет значение 18 или более. В противном случае переменной <code>status</code> присваивается значение "minor".</p> + +<h3 id="Оператор_запятая" name="Оператор_запятая">Оператор запятая</h3> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Operators/Comma_Operator">Оператор запятая</a> (<code>,</code>) просто вычисляет оба операнда и возвращает значение последнего операнда. Данный оператор в основном используется внутри цикла <code>for</code>, что позволяет при каждом прохождении цикла одновременно обновлять значения нескольких переменных.</p> + +<p>Например, если <code>a</code> является двумерным массивом, каждая строка которого содержит 10 элементов, то следующий код с использованием оператора запятая позволяет выполнять одновременное приращение двух переменных. Данный код выводит на экран значения диагональных элементов массива:</p> + +<pre class="brush: js">for (var i = 0, j = 9; i <= 9; i++, j--) + document.writeln("a[" + i + "][" + j + "]= " + a[i][j]); +</pre> + +<h3 id="Унарные_операторы">Унарные операторы</h3> + +<p>Унарная операция - операция только с одним операндом.</p> + +<h4 id="delete" name="delete"><code>delete</code></h4> + +<p>Оператор <a href="/ru/docs/Web/JavaScript/Reference/Operators/delete">delete</a> выполняет удаление объекта, свойства объекта, или элемента массива с заданным индексом. Синтаксис оператора:</p> + +<pre class="brush: js">delete objectName; +delete objectName.property; +delete objectName[index]; +delete property; // допустимо только внутри with +</pre> + +<p>где <code>objectName</code> представляет собой имя объекта, <code>property</code> - свойство объекта, а <code>index</code> - целое число, указывающее на положение (номер позиции) элемента в массиве.</p> + +<p>Четвертый вариант использования позволяет удалить свойство объекта, но допускается только внутри <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/with">with</a></code>.</p> + +<p>Вы можете использовать оператор <code>delete</code> для удаления переменных, объявленных неявно, но вы не можете с его помощью удалять переменные, объявленные с помощью <code>var</code>.</p> + +<p>После применения оператора <code>delete</code> свойство элемента меняется на <code>undefined</code>. Оператор <code>delete</code> возвращает <code>true</code> если выполнение операции возможно; оператор возвращает <code>false</code>, если выполнение операции невозможно.</p> + +<pre class="brush: js">x = 42; +var y = 43; +myobj = new Number(); +myobj.h = 4; // создаём свойство h +delete x; // возвращает true (можно удалить переменную объявленную неявно) +delete y; // возвращает false (нельзя удалить переменную объявленную с помощью var) +delete Math.PI; // возвращает false (нельзя удалить встроенные свойства) +delete myobj.h; // возвращает true (можно удалить пользовательские свойства) +delete myobj; // возвращает true (можно удалить объект объявленный неявно) +</pre> + +<h5 id="Удаление_элементов_массива">Удаление элементов массива</h5> + +<p>Удаление элемента массива не влияет на длину массива. Например, если вы удалите <code>a[3]</code>, элемент <code>a[4]</code> останется <code>a[4],</code> <code>a[3]</code> станет undefined.</p> + +<p>Когда элемент массива удаляется с помощью оператора <code>delete</code>, то из массива удаляется значение данного элемента. В следующем примере элемент <code>trees[3]</code> удален с помощью оператора <code>delete</code>. Однако, элемент <code>trees[3]</code> остается адресуемым и возвращает значение <code>undefined</code>.</p> + +<pre class="brush: js">var trees = new Array("redwood", "bay", "cedar", "oak", "maple"); +delete trees[3]; +if (3 in trees) { + // условие не выполняется +} +</pre> + +<p>Если вы хотите, чтобы элемент оставался в массиве, но имел значение undefined, то используйте ключевое слово <code>undefined</code> вместо оператора <code>delete</code>. В следующем примере элементу <code>trees[3]</code> присвоено значение <code>undefined</code>, но элемент при этом остается в массиве:</p> + +<pre class="brush: js">var trees = new Array("redwood", "bay", "cedar", "oak", "maple"); +trees[3] = undefined; +if (3 in trees) { + // данный блок кода выполняется +} +</pre> + +<h4 id="typeof" name="typeof"><code>Оператор typeof</code></h4> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Operators/typeof">Оператор<code> typeof</code></a> используется одним из следующих способов:</p> + +<pre class="syntaxbox">typeof operand +typeof (operand)</pre> + +<p>Оператор <code>typeof</code> возвращает строку обозначающую тип невычисленного операнда. Значение <code>operand</code> может быть строкой, переменной, дескриптором, или объектом, тип которого следует определить. Скобки вокруг операнда необязательны.</p> + +<p>Предположим, вы определяете следующие переменные:</p> + +<pre class="brush: js">var myFun = new Function("5 + 2"); +var shape = "round"; +var size = 1; +var today = new Date(); +</pre> + +<p>Оператор <code>typeof</code> возвращает следующие результаты для этих переменных:</p> + +<pre class="brush: js">typeof myFun; // возвращает "function" +typeof shape; // возвращает "string" +typeof size; // возвращает "number" +typeof today; // возвращает "object" +typeof dontExist; // возвращает "undefined" +</pre> + +<p>Для дескрипторов <code>true</code> и <code>null</code> оператор <code>typeof</code> возвращает следующие результаты:</p> + +<pre class="brush: js">typeof true; // возвращает "boolean" +typeof null; // возвращает "object" +</pre> + +<p>Для чисел и строк оператор <code>typeof</code> возвращает следующие результаты:</p> + +<pre class="brush: js">typeof 62; // возвращает "number" +typeof 'Hello world'; // возвращает "string" +</pre> + +<p>Для свойств оператор <code>typeof</code> возвращает тип значения данного свойства:</p> + +<pre class="brush: js">typeof document.lastModified; // возвращает "string" +typeof window.length; // возвращает "number" +typeof Math.LN2; // возвращает "number" +</pre> + +<p>Для методов и функций оператор <code>typeof</code> возвращает следующие результаты:</p> + +<pre class="brush: js">typeof blur; // возвращает "function" +typeof eval; // возвращает "function" +typeof parseInt; // возвращает "function" +typeof shape.split; // возвращает "function" +</pre> + +<p>Для встроенных объектов оператор <code>typeof</code> возвращает следующие результаты:</p> + +<pre class="brush: js">typeof Date; // возвращает "function" +typeof Function; // возвращает "function" +typeof Math; // возвращает "object" +typeof Option; // возвращает "function" +typeof String; // возвращает "function"</pre> + +<h4 id="void" name="void"><code>Оператор void</code></h4> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Operators/void">Оператор<code> </code><code>void</code></a> используется любым из следующих способов:</p> + +<pre class="syntaxbox">void (expression) +void expression +</pre> + +<p>Оператор <code>void</code> определяет выражение, которое должно быть вычислено без возвращения результата. <code>expression</code> - это выражение JavaScript, требующее вычисления. Скобки вокруг выражения необязательны, но их использование является правилом хорошего тона.</p> + +<p>Вы можете использовать оператор <code>void</code> для указания на то, что операнд-выражение является гипертекстовой ссылкой. При этом выражение обрабатывается, но не загружается в текущий документ.</p> + +<p>Следующий код служит примером создания гипертекстовой ссылки, которая бездействует при нажатии на неё пользователем. Когда пользователь нажимает на ссылку, <code>void(0)</code> вычисляется равным <code>undefined</code>, что не приводит ни к каким действиям в JavaScript.</p> + +<pre class="brush: html"><A HREF="javascript:void(0)">Нажмите здесь, чтобы ничего не произошло</A> +</pre> + +<p>Приведенный ниже код создает гипертекстовую ссылку, которая подтверждает отправку формы при клике на ней пользователем:</p> + +<pre class="brush: html"><A HREF="javascript:void(document.form.submit())"> +Нажмите здесь, чтобы подтвердить отправку формы</A></pre> + +<h3 id="Операторы_отношения">Операторы отношения</h3> + +<p>Оператор отношения сравнивает свои операнды и возвращает результат сравнения в виде булева значения.</p> + +<h4 id="Оператор_in"><code>Оператор in</code></h4> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Operators/in">Оператор <code>in</code></a> возвращает true, если указанный объект имеет указанное свойство. Синтаксис оператора:</p> + +<pre class="syntaxbox">propNameOrNumber in objectName +</pre> + +<p>где <code>propNameOrNumber</code> - строка или числовое выражение, представляющее имя свойства или индекс массива, а <code>objectName</code> - имя объекта.</p> + +<p>Некоторые примеры способов использования оператора <code>in</code>:</p> + +<pre class="brush: js">// Массивы +var trees = new Array("redwood", "bay", "cedar", "oak", "maple"); +0 in trees; // возвращает true +3 in trees; // возвращает true +6 in trees; // возвращает false +"bay" in trees; // возвращает false (следует указать индекс элемента массива, + // а не значение элемента) +"length" in trees; // возвращает true (length является свойством объекта Array) + +// Встроенные объекты +"PI" in Math; // возвращает true +var myString = new String("coral"); +"length" in myString; // возвращает true + +// Пользовательские объекты +var mycar = {make: "Honda", model: "Accord", year: 1998}; +"make" in mycar; // возвращает true +"model" in mycar; // возвращает true +</pre> + +<h4 id="instanceof" name="instanceof">Оператор <code>instanceof</code></h4> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Operators/instanceof">Оператор <code>instanceof</code> </a>возвращает true, если заданный объект является объектом указанного типа. Его синтаксис:</p> + +<pre class="syntaxbox">objectName instanceof objectType +</pre> + +<p>где <code>objectName</code> - имя объекта, тип которого необходимо сравнить с <code>objectType</code>, а <code>objectType</code> - тип объекта, например, {{jsxref("Date")}} или {{jsxref("Array")}}.</p> + +<p><code><font face="Open Sans, Arial, sans-serif">Используйте оператор </font>instanceof</code>, когда вам необходимо подтвердить тип объекта во время выполнения программы. Например, при перехвате исключений вы можете создать различные программные переходы для обработки исключений в зависимости от типа обрабатываемого исключения.</p> + +<p>Например, следующий код использует оператор <code>instanceof</code> для проверки того, является ли объект <code>theDay</code> объектом типа <code>Date</code>. Так как <code>theDay</code> действительно является объектом типа <code>Date</code>, то программа выполняет код, содержащийся в утверждении <code>if</code>.</p> + +<pre class="brush: js">var theDay = new Date(1995, 12, 17); +if (theDay instanceof Date) { + // выполняемый код +} +</pre> + +<h3 id="Приоритет_операторов">Приоритет операторов</h3> + +<p><em>Приоритет</em> операторов определяет порядок их выполнения при вычислении выражения. Вы можете влиять на приоритет операторов с помощью скобок.</p> + +<p>Приведенная ниже таблица описывает приоритет операторов от наивысшего до низшего.</p> + +<table class="standard-table"> + <caption>Таблица 3.7 Приоритет операторов</caption> + <thead> + <tr> + <th scope="col">Тип оператора</th> + <th scope="col">Операторы</th> + </tr> + </thead> + <tbody> + <tr> + <td>свойство объекта</td> + <td><code>. []</code></td> + </tr> + <tr> + <td>вызов, создание экземпляра объекта</td> + <td><code>() new</code></td> + </tr> + <tr> + <td>отрицание, инкремент</td> + <td><code>! ~ - + ++ -- typeof void delete</code></td> + </tr> + <tr> + <td>умножение, деление</td> + <td><code>* / %</code></td> + </tr> + <tr> + <td>сложение, вычитание</td> + <td><code>+ -</code></td> + </tr> + <tr> + <td>побитовый сдвиг</td> + <td><code><< >> >>></code></td> + </tr> + <tr> + <td>сравнение, вхождение</td> + <td><code>< <= > >= in instanceof</code></td> + </tr> + <tr> + <td>равенство</td> + <td><code>== != === !==</code></td> + </tr> + <tr> + <td>битовое-и</td> + <td><code>&</code></td> + </tr> + <tr> + <td>битовое-исключающее-или</td> + <td><code>^</code></td> + </tr> + <tr> + <td>битовое-или</td> + <td><code>|</code></td> + </tr> + <tr> + <td>логическое-и</td> + <td><code>&&</code></td> + </tr> + <tr> + <td>логическое-или</td> + <td><code>||</code></td> + </tr> + <tr> + <td>условный (тернарный) оператор</td> + <td><code>?:</code></td> + </tr> + <tr> + <td>присваивание</td> + <td><code>= += -= *= /= %= <<= >>= >>>= &= ^= |=</code></td> + </tr> + <tr> + <td>запятая</td> + <td><code>,</code></td> + </tr> + </tbody> +</table> + +<p>Более подробная версия данной таблицы, содержащая ссылки и дополнительную информацию по каждому оператору, находится в <a href="/ru/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table">справочнике JavaScript</a>.</p> + +<h2 id="Выражения">Выражения</h2> + +<p><em>Выражением </em>является любой корректный блок кода, который возвращает значение.</p> + +<p>Концептуально, существуют два типа выражений: те которые присваивают переменной значение, и те, которые вычисляют значение без его присваивания.</p> + +<p>Выражение <code>x = 7</code> является примером выражения первого типа. Данное выражение использует <em>оператор</em> = для присваивания переменной<span style="line-height: 1.5;"> </span><code style="font-style: normal; line-height: 1.5;">x </code><span style="line-height: 1.5;">значения 7</span><span style="line-height: 1.5;">. Само выражение также равняется 7.</span></p> + +<p>Код <code>3 + 4</code> является примером выражения второго типа. Данное выражение использует <em>оператор</em><span style="line-height: 1.5;"> "+" для сложения чисел 3 и 4 без присваивания переменной полученного результата 7.</span></p> + +<p>Все выражения в JavaScript делятся на следующие категории:</p> + +<ul> + <li><strong>Арифметические</strong>: вычисляются в число, например: 3.14159 (Используют {{ web.link("#Arithmetic_operators", "арифметические операторы") }}).</li> + <li><strong>Строковые</strong>: вычисляются в текстовую строку, например: "Fred" или "234" (Используют {{ web.link("#String_operators", "строковые операторы") }}).</li> + <li><strong>Логические</strong>: вычисляются в true или false (Используют {{ web.link("#Logical_operators", "логические операторы") }}).</li> + <li><strong>Основные выражения</strong>: Базовые ключевые слова и основные выражения в JavaScript.</li> + <li><strong>Левосторонние выражения</strong>: Значениям слева назначаются значения справа.</li> +</ul> + +<h3 id="Основные_выражения">Основные выражения</h3> + +<p>Базовые ключевые слова и основные выражения в JavaScript.</p> + +<h4 id="this" name="this">Оператор <code>this</code></h4> + +<p>Используйте ключевое слово <code>this</code> для указания на текущий объект. В общем случае <code>this</code> указывает на вызываемый объект, которому принадлежит данный метод. Используйте <code>this</code> следующим образом:</p> + +<pre class="syntaxbox">this["propertyName"] +this.propertyName +</pre> + +<p>Предположим, функция <code>validate</code> выполняет проверку свойства <code>value</code> некоторого объекта; задан объект, а также верхняя и нижняя граница величины данного свойства:</p> + +<pre class="brush: js">function validate(obj, lowval, hival){ + if ((obj.value < lowval) || (obj.value > hival)) + alert("Неверное значение!"); +} +</pre> + +<p>Вы можете вызвать функцию <code>validate</code> для обработчика события <code>onChange</code> для каждого элемента формы, используя <code>this</code> для указания на элемент формы, как это показано в следующем примере:</p> + +<pre class="brush: html"><B>Введите число от 18 до 99:</B> +<INPUT TYPE="text" NAME="age" SIZE=3 + onChange="validate(this, 18, 99);"> +</pre> + +<h4 id="Оператор_группировки">Оператор группировки</h4> + +<p>Оператор группировки <code>"скобки" ( )</code> контролирует приоритет вычисления выражений. Например, вы можете переопределить порядок - "умножение и деление, а потом сложение и вычитание", так чтобы, например, чтобы сложение выполнялось до умножения:</p> + +<pre class="brush: js">var a = 1; +var b = 2; +var c = 3; + +// обычный порядок +a + b * c // 7 +// выполняется, как обычно, так +a + (b * c) // 7 + +// теперь поменяем порядок +// сложение до умножения +(a + b) * c // 9 + +// что эквивалентно следующему +a * c + b * c // 9</pre> + +<h4 id="Упрощенный_синтаксис_создания_массивов_и_генераторов">Упрощенный синтаксис создания массивов и генераторов</h4> + +<p>Упрощенный синтаксис - экспериментальная возможность JavaScript, которая возможно будет добавлена в будущие версии ECMAScript. Есть 2 версии синтаксиса:</p> + +<dl> + <dt>{{experimental_inline}} {{jsxref("Operators/Array_comprehensions", "[for (x of y) x]")}}</dt> + <dd>Упрощенный синтаксис для массивов.</dd> + <dt>{{experimental_inline}} {{jsxref("Operators/Generator_comprehensions", "(for (x of y) y)")}}</dt> + <dd>Упрощенный синтаксис для генераторов.</dd> +</dl> + +<p>Упрощенные синтаксисы существуют во многих языках программирования и позволяют вам быстро собирать новый массив, основанный на существующем. Например:</p> + +<pre class="brush: js">[for (i of [ 1, 2, 3 ]) i*i ]; +// [ 1, 4, 9 ] + +var abc = [ "A", "B", "C" ]; +[for (letters of abc) letters.toLowerCase()]; +// [ "a", "b", "c" ]</pre> + +<h3 id="Левосторонние_выражения">Левосторонние выражения</h3> + +<p>Значениям слева назначаются значения справа.</p> + +<h4 id="new" name="new"><code>new</code></h4> + +<p>Вы можете использовать <a href="/ru/docs/Web/JavaScript/Reference/Operators/new">оператор <code>new</code></a> для создания экземпляра объекта пользовательского типа или одного из встроенных объектов. Используйте оператор <code>new</code> следующим образом:</p> + +<pre class="brush: js">var objectName = new objectType([param1, param2, ..., paramN]); +</pre> + +<h4 id="super">super</h4> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Operators/super">Ключевое слово</a> используется, чтобы вызывать функции родительского объекта. Это полезно и с <a href="/ru/docs/Web/JavaScript/Reference/Classes">классами</a> для вызова конструктора родителя, например.</p> + +<pre class="brush: js">super([arguments]); // вызывает конструктор родителя. super.functionOnParent([arguments]);</pre> + +<h4 id="Оператор_расширения">Оператор расширения</h4> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Operators/Spread_operator">Оператор расширения</a> позволяет выражению расширяться в местах с множеством аргументов (для вызовов функций) или множестве элементов (для массивов).</p> + +<p><strong>Пример:</strong> Сегодня, если у вас есть массив и вы хотите создать новый с существующей частью первого, то литерального синтаксиса массива уже не достаточно, и вы должны писать императивный (без вариантов) код, используя комбинацию <code>push</code>, <code>splice</code>, <code>concat</code> и т.д. Но с этим оператором код становится более коротким:</p> + +<pre class="brush: js">var parts = ['shoulder', 'knees']; +var lyrics = ['head', ...parts, 'and', 'toes'];</pre> + +<p>Похожим образом оператор работает с вызовами функций:</p> + +<pre class="brush: js">function f(x, y, z) { } +var args = [0, 1, 2]; +f(...args);</pre> + +<p>{{PreviousNext("Web/JavaScript/Guide/Functions", "Web/JavaScript/Guide/Numbers_and_dates")}}</p> + +<h3 id="sect1"> </h3> + +<h2 id="sect2"> </h2> + +<ul> +</ul> diff --git a/files/ru/web/javascript/guide/functions/index.html b/files/ru/web/javascript/guide/functions/index.html new file mode 100644 index 0000000000..5e487e354d --- /dev/null +++ b/files/ru/web/javascript/guide/functions/index.html @@ -0,0 +1,669 @@ +--- +title: Функции +slug: Web/JavaScript/Guide/Functions +tags: + - Основы + - Функции +translation_of: Web/JavaScript/Guide/Functions +--- +<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Loops_and_iteration", "Web/JavaScript/Guide/Expressions_and_Operators")}}</div> + +<h2 id="Функции_в_JavaScript">Функции в JavaScript</h2> + +<p>Функции - ключевая концепция в JavaScript. Важнейшей особенностью языка является {{interwiki("wikipedia", "Функции_первого_класса", "первоклассная поддержка функций")}} <em>(functions as first-class citizen)</em>. Любая <strong>функция это объект,</strong> и следовательно ею можно манипулировать как объектом, в частности:</p> + +<ul> + <li>передавать как аргумент и возвращать в качестве результата при вызове других функций ({{interwiki("wikipedia", "Функция_высшего_порядка", "функций высшего порядка")}});</li> + <li>создавать анонимно и присваивать в качестве значений переменных или свойств объектов.</li> +</ul> + +<p>Это определяет высокую выразительную мощность JavaScript и позволяет относить его к числу языков, реализующих {{interwiki("wikipedia", "Функциональное_программирование", "функциональную парадигму программирования")}} (что само по себе есть очень круто по многим соображениям).</p> + +<p><strong>Функция в JavaScript</strong> специальный тип объектов, позволяющий формализовать средствами языка определённую логику поведения и обработки данных.</p> + +<p>Для понимания работы функций необходимо (и достаточно?) иметь представление о следующих моментах:</p> + +<ul> + <li>способы <a href="#definition">объявления</a></li> + <li>способы <a href="#call">вызова</a></li> + <li>параметры и аргументы вызова (<code>arguments</code>)</li> + <li>область данных (<code>Scope</code>) и замыкания (<code>Closures</code>)</li> + <li>объект привязки (<code>this</code>)</li> + <li>возвращаемое значение (<code>return</code>)</li> + <li>исключения (<code>throw</code>)</li> + <li>использование в качестве конструктора объектов</li> + <li>сборщик мусора (<code>garbage collector</code>)</li> +</ul> + +<h2 id="Объявление_функций"><a id="definition" name="definition"></a>Объявление функций</h2> + +<h3 id="Функции_вида_function_declaration_statement">Функции вида "function declaration statement"</h3> + +<p>Объявление функции (<em>function definition</em>, или <em>function declaration</em>, или <em>function statement</em>) состоит из ключевого слова <code><a href="/ru/docs/Web/JavaScript/Reference/Statements/function">function</a></code> и следующих частей:</p> + +<ul> + <li>Имя функции.</li> + <li>Список параметров (принимаемых функцией) заключенных в круглые скобки <code>()</code> и разделенных запятыми.</li> + <li>Инструкции, которые будут выполненны после вызова функции, заключают в фигурные скобки <code>{ }</code>.</li> +</ul> + +<p>Например, следующий код объявляет простую функцию с именем <code>square:</code></p> + +<pre class="brush: js">function square(number) { + return number * number; +} +</pre> + +<p>Функция <code>square</code> принимает один параметр, названный <code>number.</code> Состоит из одной инструкции, которая означает вернуть параметр этой функции (это <code>number</code>) умноженный на самого себя. Инструкция <a href="/ru/docs/Web/JavaScript/Reference/Statements/return">return</a> указывает на значение, которые будет возвращено функцией.</p> + +<pre class="brush: js">return number * number; +</pre> + +<p>Примитивные параметры (например, число) передаются функции значением; <strong>значение</strong> передаётся в функцию, но если функция меняет значение параметра,<strong> это изменение не отразится глобально или после вызова функции.</strong></p> + +<p>Если Вы передадите объект как параметр (не примитив, например, <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" title="The JavaScript Array object is a global object that is used in the construction of arrays; which are high-level, list-like objects.">массив</a></code> или определяемые пользователем объекты), и функция изменит свойство переданного в неё объекта, это изменение будет видно и вне функции, как показано в следующим примере:</p> + +<pre class="brush: js">function myFunc(theObject) { + theObject.make = 'Toyota'; +} + +var mycar = {make: 'Honda', model: 'Accord', year: 1998}; +var x, y; + +x = mycar.make; // x получает значение "Honda" + +myFunc(mycar); +y = mycar.make; // y получает значение "Toyota" + // (свойство было изменено функцией) +</pre> + +<h3 id="Функции_вида_function_definition_expression">Функции вида "function definition expression"</h3> + +<p>Функция вида "function declaration statement" по синтаксису является инструкцией (<em>statement</em>), ещё функция может быть вида "function definition expression". Такая функция может быть <strong>анонимной</strong> (она не имеет имени). Например, функция <code>square</code> может быть вызвана так:</p> + +<pre class="brush: js">var square = function(number) { return number * number; }; +var x = square(4); // x получает значение 16 +</pre> + +<p>Однако, имя может быть и присвоено для вызова самой себя внутри самой функции и для отладчика (<em>debugger</em>) для идентифицирования функции в стек-треках (<em>stack traces</em>; "trace" — "след" / "отпечаток").</p> + +<pre class="brush: js">var factorial = function fac(n) { return n < 2 ? 1 : n * fac(n - 1); }; + +console.log(factorial(3)); +</pre> + +<p>Функции вида "function definition expression" удобны, когда функция передается аргументом другой функции. Следующий пример показывает функцию <code>map</code>, которая должна получить функцию первым аргументом и массив вторым.</p> + +<pre class="brush: js">function map(f, a) { + var result = [], // Create a new Array + i; + for (i = 0; i != a.length; i++) + result[i] = f(a[i]); + return result; +} +</pre> + +<p>В следующим коде наша функция принимает функцию, которая является function definition expression, и выполняет его для каждого элемента принятого массива вторым аргументом.</p> + +<pre class="brush: js">function map(f, a) { + var result = []; // Create a new Array + var i; // Declare variable + for (i = 0; i != a.length; i++) + result[i] = f(a[i]); + return result; +} +var f = function(x) { + return x * x * x; +} +var numbers = [0, 1, 2, 5, 10]; +var cube = map(f,numbers); +console.log(cube);</pre> + +<p>Функция возвращает: [0, 1, 8, 125, 1000].</p> + +<p>В JavaScript функция может быть объявлена с условием. Например, следующая функция будет присвоена переменной <code>myFunc</code> только, если <code>num</code> равно 0: </p> + +<pre class="brush: js">var myFunc; +if (num === 0) { + myFunc = function(theObject) { + theObject.make = 'Toyota'; + } +}</pre> + +<p>В дополнение к объявлениям функций, описанных здесь, Вы также можете использовать конструктор <a href="/ru/docs/Web/JavaScript/Reference/Global_Objects/Function">Function</a> для создания функций из строки во время выполнения (<em>runtime</em>), подобно <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/eval" title="The eval() method evaluates JavaScript code represented as a string."><code>eval()</code></a>.</p> + +<p><strong>Метод</strong> — это функция, которая является свойством объекта. Узнать больше про объекты и методы можно по ссылке: <a href="/ru/docs/Web/JavaScript/Guide/Working_with_Objects">Работа с объектами</a>.</p> + +<h2 id="Вызовы_функций"><a id="call" name="call"></a>Вызовы функций</h2> + +<p>Объявление функции не выполняет её. Объявление функции просто называет функцию и указывает, что делать при вызове функции.</p> + +<p><strong>Вызов</strong> функции фактически выполняет указанные действия с указанными параметрами. Например, если Вы определите функцию <code>square</code>, Вы можете вызвать её следующим образом:</p> + +<pre class="brush: js">square(5);</pre> + +<p>Эта инструкция вызывает функцию с аргументом 5. Функция вызывает свои инструкции и возвращает значение 25.</p> + +<p>Функции могут быть в области видимости, когда они уже определены, но функции вида "function declaration statment" могут быть подняты (<em><a href="/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/%D0%9F%D0%BE%D0%B4%D0%BD%D1%8F%D1%82%D0%B8%D0%B5">поднятие </a>—</em> <em>hoisting</em>), также как в этом примере:</p> + +<pre class="brush: js">console.log(square(5)); +/* ... */ +function square(n) { return n * n; }</pre> + +<p>Область видимости функции — функция, в котором она определена, или целая программа, если она объявлена по уровню выше.</p> + +<div class="note"> +<p><strong>Примечание:</strong> Это работает только тогда, когда объявлении функции использует вышеупомянутый синтаксис (т.е. <code>function funcName(){}</code>). Код ниже не будет работать. Имеется в виду то, что поднятие функции работает только с function declaration и не работает с function expression.</p> +</div> + +<pre class="brush: js example-bad">console.log(square); // square поднят со значением undefined. +console.log(square(5)); // TypeError: square is not a function +var square = function(n) { + return n * n; +}</pre> + +<p>Аргументы функции не ограничиваются строками и числами. Вы можете передавать целые объекты в функцию. Функция <code>show_props()</code> (объявленная в <a href="/ru/docs/Web/JavaScript/Guide/Working_with_Objects">Работа с объектами</a>) является примером функции, принимающей объекты аргументом.</p> + +<p>Функция может вызвать саму себя. Например, вот функция рекурсивного вычисления факториала:</p> + +<pre class="brush: js">function factorial(n) { + if ((n === 0) || (n === 1)) + return 1; + else + return (n * factorial(n - 1)); +} +</pre> + +<p>Затем вы можете вычислить факториалы от одного до пяти следующим образом:</p> + +<pre class="brush: js">var a, b, c, d, e; +a = factorial(1); // a gets the value 1 +b = factorial(2); // b gets the value 2 +c = factorial(3); // c gets the value 6 +d = factorial(4); // d gets the value 24 +e = factorial(5); // e gets the value 120 +</pre> + +<p>Есть другие способы вызвать функцию. Существуют частые случаи, когда функции необходимо вызывать динамически, или поменять номера аргументов функции, или необходимо вызвать функцию с привязкой к определенному контексту. Оказывается, что функции сами по себе являются объектами, и эти объекты в свою очередь имеют методы (посмотрите объект <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function" title="The Function constructor creates a new Function object. Calling the constructor directly can create functions dynamically, but suffers from security and similar (but far less significant) performance issues similar to eval. However, unlike eval, the Function constructor allows executing code in the global scope, prompting better programming habits and allowing for more efficient code minification."><code>Function</code></a>). Один из них это метод <code><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/apply" title="The apply() method calls a function with a given this value, and arguments provided as an array (or an array-like object).">apply()</a></code>, использование которого может достигнуть этой цели.</p> + +<h2 id="Область_видимости_функций"><a id="definition" name="definition"></a>Область видимости функций</h2> + +<p><u><em>(function scope)</em></u></p> + +<p>Переменные объявленные в функции не могут быть доступными где-нибудь вне этой функции, поэтому переменные (которые нужны именно для функции) объявляют только в scope функции. При этом функция имеет доступ ко всем переменным и функциям, объявленным внутри её scope. Другими словами функция объявленная в глобальном scope имеет доступ ко всем переменным в глобальном scope. Функция объявленная внутри другой функции ещё имеет доступ и ко всем переменным её родителькой функции и другим переменным, к которым эта родительская функция имеет доступ.</p> + +<pre class="brush: js">// Следующие переменные объявленны в глобальном scope +var num1 = 20, + num2 = 3, + name = 'Chamahk'; + +// Эта функция объявленна в глобальном scope +function multiply() { + return num1 * num2; +} + +multiply(); // вернет 60 + +// Пример вложенной функции +function getScore() { + var num1 = 2, + num2 = 3; + + function add() { + return name + ' scored ' + (num1 + num2); + } + + return add(); +} + +getScore(); // вернет "Chamahk scored 5" +</pre> + +<h2 id="Scope_и_стек_функции"><a id="definition" name="definition"></a>Scope и стек функции</h2> + +<p><em><u>(function stack)</u></em></p> + +<h3 id="Рекурсия">Рекурсия</h3> + +<p>Функция может вызывать саму себя. Три способа такого вызова:</p> + +<ol> + <li>по имени функции</li> + <li><code><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/arguments/callee">arguments.callee</a></code></li> + <li>по переменной, которая ссылается на функцию</li> +</ol> + +<p>Для примера рассмотрим следующие функцию:</p> + +<pre class="brush: js">var foo = function bar() { + // statements go here +};</pre> + +<p>Внутри функции (<em>function body</em>) все следующие вызовы эквивалентны:</p> + +<ol> + <li><code>bar()</code></li> + <li><code>arguments.callee()</code></li> + <li><code>foo()</code></li> +</ol> + +<p>Функция, которая вызывает саму себя, называется <em>рекурсивной функцией</em> (<em>recursive function</em>). Получается, что рекурсия аналогична циклу (<em>loop</em>). Оба вызывают некоторый код несколько раз, и оба требуют условия (чтобы избежать бесконечного цикла, вернее бесконечной рекурсии). Например, следующий цикл:</p> + +<pre class="brush: js">var x = 0; +while (x < 10) { // "x < 10" — это условие для цикла + // do stuff + x++; +}</pre> + +<p>можно было изменить на рекурсивную функцию и вызовом этой функции:</p> + +<pre class="brush: js">function loop(x) { + if (x >= 10) // "x >= 10" — это условие для конца выполения (тоже самое, что "!(x < 10)") + return; + // делать что-то + loop(x + 1); // рекурсионный вызов +} +loop(0); +</pre> + +<p>Однако некоторые алгоритмы не могут быть простыми повторяющимися циклами. Например, получение всех элементов структуры дерева (например, <a href="https://developer.mozilla.org/ru/docs/DOM">DOM</a>) проще всего реализуется использованием рекурсии:</p> + +<pre class="brush: js">function walkTree(node) { + if (node == null) // + return; + // что-то делаем с элементами + for (var i = 0; i < node.childNodes.length; i++) { + walkTree(node.childNodes[i]); + } +}</pre> + +<p>В сравнении с функцией <code>loop</code>, каждый рекурсивный вызов сам вызывает много рекурсивных вызовов.</p> + +<p>Также возможно превращение некоторых рекурсивных алгоритмов в нерекурсивные, но часто их логика очень сложна, и для этого потребуется использование стека (<em>stack</em>). По факту рекурсия использует stack: function stack.</p> + +<p>Поведение stack'а можно увидеть в следующем примере:</p> + +<pre class="brush: js">function foo(i) { + if (i < 0) + return; + console.log('begin: ' + i); + foo(i - 1); + console.log('end: ' + i); +} +foo(3); + +// Output: + +// begin: 3 +// begin: 2 +// begin: 1 +// begin: 0 +// end: 0 +// end: 1 +// end: 2 +// end: 3</pre> + +<h3 id="Вложенные_функции_nested_functions_и_замыкания_closures">Вложенные функции (nested functions) и замыкания (closures)</h3> + +<p>Вы можете вложить одну функцию в другую. Вложенная функция (<em>nested function</em>;<em> inner</em>) приватная (<em>private</em>) и она помещена в другую функцию (<em>outer</em>). Так образуется <em>замыкание</em> (<em>closure</em>). Closure — это выражение (обычно функция), которое может иметь свободные переменные вместе со средой, которая связывает эти переменые (что "закрывает" (<em>"close"</em>) выражение).</p> + +<p>Поскольку вложенная функция это closure, это означает, что вложенная функция может "унаследовать" (<em>inherit</em>) аргументы и переменные функции, в которую та вложена. Другими словами, вложенная функция содержит scope внешней (<em>"outer"</em>) функции.</p> + +<p>Подведем итог:</p> + +<ul> + <li>Вложенная функция имеет доступ ко всем инструкциям внешней функции.</li> +</ul> + +<ul> + <li>Вложенная функция формирует closure: она может использовать аргументы и переменные внешней функции, в то время как внешняя функция не может использовать аргументы и переменные вложенной функции.</li> +</ul> + +<p>Следующий пример показывает вложенную функцию:</p> + +<pre class="brush: js">function addSquares(a, b) { + function square(x) { + return x * x; + } + return square(a) + square(b); +} +a = addSquares(2, 3); // возвращает 13 +b = addSquares(3, 4); // возвращает 25 +c = addSquares(4, 5); // возвращает 41 +</pre> + +<p>Поскольку вложенная функция формирует closure, Вы можете вызвать внешную функцию и указать аргументы для обоих функций (для outer и innner).</p> + +<pre class="brush: js">function outside(x) { + function inside(y) { + return x + y; + } + return inside; +} +fn_inside = outside(3); // Подумайте над этим: дайте мне функцию, + // который передай 3 + +result = fn_inside(5); // возвращает 8 + +result1 = outside(3)(5); // возвращает 8 +</pre> + +<h3 id="Сохранение_переменных">Сохранение переменных</h3> + +<p>Обратите внимание, значение <code>x</code> сохранилось, когда возвращалось <code>inside</code>. Closure должно сохранять аргументы и переменные во всем scope. Поскольку каждый вызов предоставляет потенциально разные аргументы, создается новый closure для каждого вызова во вне. Память может быть очищена только тогда, когда <code>inside</code> уже возвратился и больше не доступен.</p> + +<p>Это не отличается от хранения ссылок в других объектах, но часто менее очевидно, потому что не устанавливаются ссылки напрямую и нельзя посмотреть там.</p> + +<h3 id="Несколько_уровней_вложенности_функций_Multiply-nested_functions">Несколько уровней вложенности функций (Multiply-nested functions)</h3> + +<p>Функции можно вкадывать несколько раз, т.е. функция (A) хранит в себе функцию (B), которая хранит в себе функцию (C). Обе фукнкции B и C формируют closures, так B имеет доступ к переменным и аргументам A, и C имеет такой же доступ к B. В добавок, поскольку C имеет такой доступ к B, который имеет такой же доступ к A, C ещё имеет такой же доспут к A. Таким образом closures может хранить в себе несколько scope; они рекурсивно хранят scope функций, содержащих его. Это называется <em>chaining</em> (<em>chain — цепь</em>; Почему названо "chaining" будет объяснено позже)</p> + +<p>Рассмотрим следующий пример:</p> + +<pre class="brush: js">function A(x) { + function B(y) { + function C(z) { + console.log(x + y + z); + } + C(3); + } + B(2); +} +A(1); // в консоле выведится 6 (1 + 2 + 3)</pre> + +<p>В этом примере C имеет доступ к <code>y</code> функции <code>B</code> и к <code>x</code> функции <code>A</code>. Так получается, потому что:</p> + +<ol> + <li>Функция <code>B</code> формирует closure, включающее <code>A</code>, т.е. <code>B</code> имеет доступ к аргументам и переменным функции <code>A</code>.</li> + <li>Функция <code>C</code> формирует closure, включающее <code>B</code>.</li> + <li>Раз closure функции <code>B</code> включает <code>A</code>, то closure <code>С</code> тоже включает A, <code>C</code> имеет доступ к аргументам и переменным обоих функций <code>B</code> <em>и</em> <code>A</code>. Другими словами, <code>С</code> cвязывает <em>цепью</em> (<em>chain</em>) scopes функций <code>B</code> и <code>A</code> в таком порядке.</li> +</ol> + +<p>В обратном порядке, однако, это не верно. <code>A</code> не имеет доступ к переменным и аргументам <code>C</code>, потому что <code>A</code> не имеет такой доступ к <code>B</code>. Таким образом, <code>C</code> остается приватным только для <code>B</code>.</p> + +<h3 id="Конфликты_имен_Name_conflicts">Конфликты имен (Name conflicts)</h3> + +<p>Когда два аргумента или переменных в scope у closure имеют одинаковые имена, происходит <em>конфликт имени</em> (<em>name conflict</em>). Более вложенный (<em>more inner</em>) scope имеет приоритет, так самый вложенный scope имеет наивысший приоритет, и наоборот. Это цепочка областей видимости (<em>scope chain</em>). Самым первым звеном является самый глубокий scope, и наоборот. Рассмотрим следующие:</p> + +<pre class="brush: js">function outside() { + var x = 5; + function inside(x) { + return x * 2; + } + return inside; +} + +outside()(10); // возвращает 20 вместо 10</pre> + +<p>Конфликт имени произошел в инструкции <code>return x * 2</code> между параметром <code>x</code> функции <code>inside</code> и переменной <code>x</code> функции <code>outside</code>. Scope chain здесь будет таким: {<code>inside</code> ==> <code>outside</code> ==> глобальный объект (<em>global object</em>)}. Следовательно <code>x</code> функции <code>inside</code> имеет больший приоритет по сравнению с <code>outside</code>, и нам вернулось 20 (= 10 * 2), а не 10 (= 5 * 2).</p> + +<h2 id="Замыкания"><a id="definition" name="definition"></a>Замыкания</h2> + +<p><em><u>(Closures)</u></em></p> + +<p>Closures это один из главных особенностей JavaScript. JavaScript разрешает вложенность функций и предоставляет вложенной функции полный доступ ко всем переменным и функциям, объявленным внутри внешней функции (и другим переменным и функцим, к которым имеет доступ эта внешняя функция).</p> + +<p>Однако, внешняя функция не имеет доступа к переменным и функциям, объявленным во внутренней функции. Это обеспечивает своего рода инкапсуляцию для переменных внутри вложенной функции.</p> + +<p>Также, поскольку вложенная функция имеет доступ к scope внешней функции, переменные и функции, объявленные во внешней функции, будет продолжать существовать и после её выполнения для вложенной функции, если на них и на неё сохранился доступ (имеется ввиду, что переменные, объявленные во внешней функции, сохраняются, только если внутренняя функция обращается к ним).</p> + +<p>Closure создается, когда вложенная функция как-то стала доступной в неком scope вне внешней функции.</p> + +<pre class="brush: js">var pet = function(name) { // Внешняя функция объявила переменную "name" + var getName = function() { + return name; // Вложенная функция имеет доступ к "name" внешней функции + } + return getName; // Возвращаем вложенную функцию, тем самым сохраняя доступ + // к ней для другого scope +} +myPet = pet('Vivie'); + +myPet(); // Возвращается "Vivie", + // т.к. даже после выполнения внешней функции + // name сохранился для вложенной функции +</pre> + +<p>Более сложный пример представлен ниже. Объект с методами для манипуляции вложенной функции внешней функцией можно вернуть (<em>return</em>).</p> + +<pre class="brush: js">var createPet = function(name) { + var sex; + + return { + setName: function(newName) { + name = newName; + }, + + getName: function() { + return name; + }, + + getSex: function() { + return sex; + }, + + setSex: function(newSex) { + if(typeof newSex === 'string' && (newSex.toLowerCase() === 'male' || + newSex.toLowerCase() === 'female')) { + sex = newSex; + } + } + } +} + +var pet = createPet('Vivie'); +pet.getName(); // Vivie + +pet.setName('Oliver'); +pet.setSex('male'); +pet.getSex(); // male +pet.getName(); // Oliver</pre> + +<p>В коде выше переменная <code>name</code> внешней функции доступна для вложенной функции, и нет другого способа доступа к вложенным переменным кроме как через вложенную функцию. Вложенные переменные вложенной функции являются безопасными хранилищами для внешних аргументов и переменных. Они содержат "постоянные" и "инкапсулированные" данные для работы с ними вложенными функциями. Функции даже не должны присваиваться переменной или иметь имя.</p> + +<pre class="brush: js">var getCode = (function() { + var apiCode = '0]Eal(eh&2'; // A code we do not want outsiders to be able to modify... + + return function() { + return apiCode; + }; +}()); + +getCode(); // Returns the apiCode +</pre> + +<p>Однако есть ряд подводных камней, которые следует учитывать при использовании замыканий. Если закрытая функция определяет переменную с тем же именем, что и имя переменной во внешней области, нет способа снова ссылаться на переменную во внешней области.</p> + +<pre class="brush: js">var createPet = function(name) { // The outer function defines a variable called "name". + return { + setName: function(name) { // The enclosed function also defines a variable called "name". + name = name; // How do we access the "name" defined by the outer function? + } + } +} +</pre> + +<h2 id="Использование_объекта_arguments"><a id="definition" name="definition"></a>Использование объекта arguments</h2> + +<p>Объект arguments функции является псевдо-массивом. Внутри функции Вы можете ссылаться к аргументам следующим образом:</p> + +<pre class="brush: js">arguments[i] +</pre> + +<p>где <code>i</code> — это порядковый номер аргумента, отсчитывающийся с 0. К первому аргументу, переданному функции, обращаются так <code>arguments[0]</code>. А получить количество всех аргументов — <code>arguments.length</code>.</p> + +<p>С помощью объекта <code>arguments</code> Вы можете вызвать функцию, передавая в неё больше аргументов, чем формально объявили принять. Это очень полезно, если Вы не знаете точно, сколько аргументов должна принять Ваша функция. Вы можете использовать <code>arguments.length</code> для определения количества аргументов, переданных функции, а затем получить доступ к каждому аргументу, используя объект <code>arguments</code>.</p> + +<p>Для примера рассмотрим функцию, которая конкатенирует несколько строк. Единственным формальным аргументом для функции будет строка, которая указывает символы, которые разделяют элементы для конкатенации. Функция определяется следующим образом:</p> + +<pre class="brush: js">function myConcat(separator) { + var result = ''; + var i; + + // iterate through arguments + for (i = 1; i < arguments.length; i++) { + result += arguments[i] + separator; + } + return result; +}</pre> + +<p>Вы можете передавать любое количество аргументов в эту функцию, и он конкатенирует каждый аргумент в одну строку.</p> + +<pre class="brush: js">// возвращает "red, orange, blue, " +myConcat(', ', 'red', 'orange', 'blue'); + +// возвращает "elephant; giraffe; lion; cheetah; " +myConcat('; ', 'elephant', 'giraffe', 'lion', 'cheetah'); + +// возвращает "sage. basil. oregano. pepper. parsley. " +myConcat('. ', 'sage', 'basil', 'oregano', 'pepper', 'parsley'); +</pre> + +<p>Т.к. <code>arguments</code> является псевдо-массивом, к нему применимы некоторые методы массивов, например, for .. in</p> + +<pre>function func() { + for (value in arguments){ + console.log(value); + } +} + +func(1, 2, 3); +// 1 +// 2 +// 3 +</pre> + +<div class="note"> +<p><strong>Примечание:</strong> <code>arguments</code> является псевдо-массивом, но не массивом. Это псевдо-массив, в котором есть пронумерованные индексы и свойство <code>length</code>. Однако он не обладает всеми методами массивов.</p> +</div> + +<p>Рассмотрите объект <code><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function" title="The Function constructor creates a new Function object. Calling the constructor directly can create functions dynamically, but suffers from security and similar (but far less significant) performance issues similar to eval. However, unlike eval, the Function constructor allows executing code in the global scope, prompting better programming habits and allowing for more efficient code minification.">Function</a></code> в JavaScript-справочнике для большей информации.</p> + +<h2 id="Параметры_функции"><a id="definition" name="definition"></a>Параметры функции</h2> + +<p>Начиная с ECMAScript 2015 появились два новых вида параметров: параметры по умолчанию (<em>default parameters</em>) и оставшиеся параметры (<em>rest parameters</em>).</p> + +<h3 id="Параметры_по_умолчанию_Default_parameters">Параметры по умолчанию (Default parameters)</h3> + +<p>В JavaScript параметры функции по умолчанию имеют значение <code>undefined</code>. Однако в некоторых ситуация может быть полезным поменять значение по умолчанию. В таких случаях default parameters могут быть весьма кстати.</p> + +<p>В прошлом для этого было необходимо в теле функции проверять значения параметров на <code>undefined</code> и в положительном случае менять это значение на дефолтное (<em>default</em>). В следующем примере в случае, если при вызове не предоставили значение для <code>b</code>, то этим значением станет <code>undefined</code>, тогда результатом вычисления <code>a * b</code> в функции <code>multiply</code> будет <code>NaN</code>. Однако во второй строке мы поймаем это значение:</p> + +<pre class="brush: js">function multiply(a, b) { + b = typeof b !== 'undefined' ? b : 1; + + return a * b; +} + +multiply(5); // 5</pre> + +<p>С параметрами по умолчанию проверка наличия значения параметра в теле функции не нужна. Теперь Вы можете просто указать значение по умолчанию для параметра <code>b</code> в объявлении функции:</p> + +<pre class="brush: js">function multiply(a, b = 1) { + return a * b; +} + +multiply(5); // 5</pre> + +<p>Для более детального рассмотрения ознакомьтесь с <a href="/ru/docs/Web/JavaScript/Reference/Functions/Default_parameters">параметрами по умолчанию</a>.</p> + +<h3 id="Оставшиеся_параметры_Rest_parameters">Оставшиеся параметры (Rest parameters)</h3> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Functions/Rest_parameters">Оставшиеся параметры</a> предоставляют нам массив неопределенных аргументов. В примере мы используем оставшиеся параметры, чтобы собрать аргументы с индексами со 2-го до последнего. Затем мы умножим каждый из них на значение первого аргумента. В этом примере используется стрелочная функция (<u><em><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions">Arrow functions</a>)</em></u>, о которой будет рассказано в следующей секции.</p> + +<pre class="brush: js">function multiply(multiplier, ...theArgs) { + return theArgs.map(x => multiplier * x); +} + +var arr = multiply(2, 1, 2, 3); +console.log(arr); // [2, 4, 6] +</pre> + +<h2 id="Стрелочные_функции"><a id="definition" name="definition"></a>Стрелочные функции</h2> + +<p><u><em>(Arrow functions)</em></u></p> + +<p><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions">Стрелочные функции</a> — функции вида "arrow function expression" (неверно <strong>fat arrow function</strong>) — имеют укороченный ситаксис по сравнению с function expression и лексически связывает значение <code>this</code>. Стрелочные функции всегда анонимны. Посмотрите также пост блога hacks.mozilla.org "<a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/" rel="noopener">ES6 In Depth: Arrow functions</a>".</p> + +<p>На введение стрелочных функций повлияли два фактора: более короткие функции и лексика <code>this</code>.</p> + +<h3 id="Более_короткие_функции">Более короткие функции</h3> + +<p>В некоторых функциональных паттернах приветствуется использование более коротких функций. Сравните:</p> + +<pre class="brush: js">var a = [ + 'Hydrogen', + 'Helium', + 'Lithium', + 'Beryllium' +]; + +var a2 = a.map(function(s) { return s.length; }); + +console.log(a2); // logs [8, 6, 7, 9] + +var a3 = a.map(s => s.length); + +console.log(a3); // logs [8, 6, 7, 9]</pre> + +<h3 id="Лексика_this">Лексика <code>this</code></h3> + +<p>До стрелочных функций каждая новая функция определяла свое значение <code>this</code> (новый объект в случае конструктора, undefined в strict mode, контекстный объект, если функция вызвана как метод объекта, и т.д.). Это оказалось раздражающим с точки зрения объектно-орентированного стиля программирования.</p> + +<pre class="brush: js">function Person() { + // Конструктор Person() определяет `this` как самого себя. + this.age = 0; + + setInterval(function growUp() { + // Без strict mode функция growUp() определяет `this` + // как global object, который отличается от `this` + // определенного конструктором Person(). + this.age++; + }, 1000); +} + +var p = new Person();</pre> + +<p>В ECMAScript 3/5 эта проблема была исправлена путем присвоения значения <code>this</code> переменной, которую можно было бы замкнуть.</p> + +<pre class="brush: js">function Person() { + var self = this; // Некоторые выбирают `that` вместо `self`. + // Выберите что-то одно и будьте последовательны. + self.age = 0; + + setInterval(function growUp() { + // The callback refers to the `self` variable of which + // the value is the expected object. + self.age++; + }, 1000); +}</pre> + +<p>Альтернативой может быть <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">связанная функция</a> (<em>bound function</em>), с которой можно правильно вручную определить значение <code>this</code> для функции <code>growUp()</code>.</p> + +<p>В arrow function значением <code>this</code> является окружающий его контекст, так следующий код работает ожидаемо:</p> + +<pre class="brush: js">function Person() { + this.age = 0; + + setInterval(() => { + this.age++; // |this| должным образом ссылается на объект Person + }, 1000); +} + +var p = new Person(); + +</pre> + +<h2 id="Далее">Далее</h2> + +<p>Подробное техническое описание функций в статье справочника {{jsxref("Functions","Функции")}}</p> + +<p>Смотрите также <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Function" title="en-US/docs/JavaScript/Reference/Global Objects/Function"><code>Function</code></a> в Справочнике JavaScript для получения дополнительной информации по функции как объекту.</p> + +<p>Внешние ресурсы:</p> + +<ul> + <li><a href="http://www.ecma-international.org/ecma-262/6.0/index.html#sec-ecmascript-function-objects">ECMAScript® 2015 Language Specification</a></li> + <li><a href="https://learn.javascript.ru/closures">Учебник по Javascript - замыкания</a></li> +</ul> + +<p>{{PreviousNext("Web/JavaScript/Guide/Loops_and_iteration", "Web/JavaScript/Guide/Expressions_and_Operators")}}</p> diff --git a/files/ru/web/javascript/guide/grammar_and_types/index.html b/files/ru/web/javascript/guide/grammar_and_types/index.html new file mode 100644 index 0000000000..6618946fbb --- /dev/null +++ b/files/ru/web/javascript/guide/grammar_and_types/index.html @@ -0,0 +1,642 @@ +--- +title: Грамматика и типы +slug: Web/JavaScript/Guide/Grammar_and_types +tags: + - JavaScript + - Руководство +translation_of: Web/JavaScript/Guide/Grammar_and_types +--- +<p>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Introduction", "Web/JavaScript/Guide/Control_flow_and_error_handling")}}</p> + +<div class="summary"> +<p>В данной главе рассматриваются базовая грамматика, объявление переменных, типы данных и литералы.</p> +</div> + +<h2 id="Основы">Основы</h2> + +<p>JavaScript заимствует большую часть синтаксиса из Java, но также испытал влияние таких языков, как Awk, Perl и Python.</p> + +<p>JavaScript <strong>чувствителен к регистру</strong> и использует кодировку символов <strong>Unicode</strong>. Например, слово Früh ("рано" по-немецки) может использоваться в качестве имени переменной.</p> + +<pre class="brush: js">var Früh = "foobar";</pre> + +<p>Но, переменная <code>früh</code> не то же самое что <code>Früh</code> потому что JavaScript чувствителен к регистру.</p> + +<p>В JavaScript инструкции называются {{Glossary("Statement", "statements")}} и разделяются точкой с запятой (;). Пробел (space), табуляция (tab) и перевод строки (newline) называются пробельными символами (whitespace). Исходный текст скриптов на JavaScript сканируется слева направо и конвертируется в последовательность входных элементов, являющихся токенами (tokens), управляющими символами, символами конца строки, комментариями или пробельными символами. ECMAScript также определяет некоторые ключевые слова и литералы и устанавливает правила для автоматической вставки точек с запятой (<a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Lexical_grammar#Automatic_semicolon_insertion">ASI</a>), чтобы обозначить конец инструкций (statements). Однако, рекомендуется всегда ставить точку с запятой в конце каждой инструкции вручную, чтобы избежать побочных эффектов. Чтобы получить более подробную информацию, прочитайте <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Lexical_grammar">Lexical Grammar</a>.</p> + +<h2 id="Комментарии">Комментарии</h2> + +<p>Синтаксис <strong>комментариев</strong> является таким же, как и в C++ и во многих других языках:</p> + +<pre class="brush: js language-js" style="margin-top: 0px; margin-bottom: 20px; padding: 1em 0px 1em 30px; border-width: 0px 0px 0px 6px; border-left-style: solid; font-family: Consolas, Monaco, 'Andale Mono', monospace; font-size: 14px; line-height: 19px; color: rgb(77, 78, 83); overflow: auto; direction: ltr; white-space: normal; position: relative; text-shadow: none; background: 50% 0% rgb(250, 251, 252);"><code class="language-js" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-weight: inherit; font-family: Consolas, Monaco, 'Andale Mono', monospace; direction: ltr; white-space: pre; text-shadow: none;"><span class="comment token" style="border: 0px; color: #708090; display: inherit; margin: 0px; padding: 0px;">// Комментарий, занимающий одну строку. +</span> +<span class="comment token" style="border: 0px; color: #708090; display: inherit; margin: 0px; padding: 0px;">/* Комментарий, + занимающий несколько строк. + */</span> + +<span class="comment token" style="border: 0px; color: #708090; display: inherit; margin: 0px; padding: 0px;">/* Нельзя вкладывать /* комментарий в комментарий */</span> SyntaxError <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); border: 0px; color: #a67f59; margin: 0px; padding: 0px;">*</span><span class="operator token" style="background: rgba(255, 255, 255, 0.498039); border: 0px; color: #a67f59; margin: 0px; padding: 0px;">/</span></code></pre> + +<h2 id="Объявления">Объявления</h2> + +<p>В JavaScript существует три вида объявлений:</p> + +<dl> + <dt><strong style="font-weight: bold;">{{jsxref("Statements/var", "var")}}</strong></dt> + <dd>Объявляет переменную, инициализация переменной значением является необязательной.</dd> + <dt><strong style="font-weight: bold;">{{jsxref("Statements/let", "let")}}</strong></dt> + <dd>Объявляет локальную переменную в области видимости блока, инициализация переменной значением является необязательной.</dd> + <dt><strong style="font-weight: bold;">{{jsxref("Statements/const", "const")}}</strong></dt> + <dd>Объявляет именованную константу, доступную только для чтения.</dd> +</dl> + +<h3 id="Переменные">Переменные</h3> + +<p>Вы можете использовать переменные как символические имена для значений в вашем приложении. Имена переменных называются {{Glossary("Identifier", "identifiers")}} и должны соответствовать определенным правилам.</p> + +<p>Идентификатор в JavaScript должен начинаться с буквы, нижнего подчеркивания (_) или знака доллара ($); последующие символы могут также быть цифрами (0-9). Поскольку JavaScript чувствителен к регистру, буквы включают символы от "A" до "Z" (верхний регистр) и символы от "a" до "z" (нижний регистр).</p> + +<p>Вы можете использовать в идентификаторах буквы ISO 8859-1 или Unicode, например, å или ü. Вы также можете использовать<a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Lexical_grammar#String_literals"> управляющие последовательности Unicode</a> как символы в идентификаторах.</p> + +<p>Некоторые примеры корректных имен: <code style="font-style: normal;">Number_hits</code>, <code style="font-style: normal;">temp99</code>, <code style="font-style: normal;">_name</code>.</p> + +<h3 id="Объявление_переменных">Объявление переменных</h3> + +<p>Вы можете объявить переменную тремя способами:</p> + +<ul> + <li>Используя ключевое слово {{jsxref("Statements/var", "var")}}. Например, <code>var x = 42</code>. Данный синтаксис может быть использован для объявления как локальных, так и глобальных переменных.</li> + <li>Просто присвоить переменной значение. Например, <code>x = 42</code>. Переменные, объявленные данным способом, являются глобальными. Такое объявление генерирует <a href="/ru/docs/Web/JavaScript/Reference/Strict_mode">строгое предупреждение</a> (<a href="/ru/docs/Web/JavaScript/Reference/Strict_mode">strict mode</a>). Не рекомендуется использовать данный способ.</li> + <li>Используя ключевое слово {{jsxref("Statements/let", "let")}}. Например, <code>let y = 13</code>. Данный синтаксис может быть использован для объявления локальной переменной в области видимости блока.</li> +</ul> + +<h3 id="Присваивание_значений">Присваивание значений</h3> + +<p>Переменная, объявленная через <code>var</code> или <code>let</code> без присвоения начального значения, имеет значение {{jsxref("undefined")}}.</p> + +<p>При попытке доступа к необъявленной переменной или переменной до её объявления будет выброшено исключение {{jsxref("ReferenceError")}}:</p> + +<pre class="brush: js">var a; +console.log("The value of a is " + a); //Значение переменной a undefined + +console.log("The value of b is " + b); //Uncaught ReferenceError: b не определена + +console.log("The value of c is " + c); //Значение переменной c undefined +var c; + +console.log("The value of x is " + x); //Uncaught ReferenceError: x не определена +let x; </pre> + +<p>Вы можете использовать <code>undefined</code>, чтобы определить, имеет ли переменная значение. В следующем примере переменной <code>input</code> не присвоено значение, и оператор <code>if</code> будет вычислен как <code>true</code>:</p> + +<pre class="brush: js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> input<span class="punctuation token" style="color: #999999;">;</span> +<span class="keyword token" style="color: #0077aa;">if </span><span class="punctuation token" style="color: #999999;">(</span>input <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">===</span> undefined<span class="punctuation token" style="color: #999999;">) </span><span class="punctuation token" style="color: #999999;">{</span> + <span class="function token" style="color: #dd4a68;">doThis<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">}</span> <span class="keyword token" style="color: #0077aa;">else</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="function token" style="color: #dd4a68;">doThat<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">}</span></code></pre> + +<p>Значение <code>undefined</code> ведет себя как <code>false</code>, когда используется в логическом контексте. Например, следующий код выполняет функцию <code>myFunction</code>, т.к. элемент <code>myArray</code> не определен:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> myArray <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="punctuation token" style="color: #999999;">[</span><span class="punctuation token" style="color: #999999;">]</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="keyword token" style="color: #0077aa;">if</span> <span class="punctuation token" style="color: #999999;">(</span><span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">!</span>myArray<span class="punctuation token" style="color: #999999;">[</span><span class="number token" style="color: #990055;">0</span><span class="punctuation token" style="color: #999999;">]</span><span class="punctuation token" style="color: #999999;">)</span> { +<span class="function token" style="color: #dd4a68;"> myFunction<span class="punctuation token" style="color: #999999;">(</span></span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> +</code>} +</pre> + +<p>Значение <code>undefined</code> конвертируется в <code>NaN</code>, когда используется в числовом контексте:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> a<span class="punctuation token" style="color: #999999;">;</span> +a <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> <span class="number token" style="color: #990055;">2</span></code><code class="language-js" style="direction: ltr; white-space: pre;"><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // NaN</span></code></pre> + +<p>Значение {{jsxref("null")}} ведет себя как 0 в числовом контексте и как <code>false</code> в логическом контексте:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> n <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="keyword token" style="color: #0077aa;">null</span><span class="punctuation token" style="color: #999999;">;</span> +console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>n <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">*</span> <span class="number token" style="color: #990055;">32</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // В консоль выведется 0</span></code></pre> + +<h3 id="Область_видимости_переменных">Область видимости переменных</h3> + +<p>Когда вы объявляете переменную вне функции, то такая переменная называется <em>глобальной</em> переменной, т.к. доступна любому коду в текущем документе. Когда вы объявляете переменную внутри функции, то такая переменная называется <em>локальной</em> переменной, т.к. доступна только внутри данной функции.</p> + +<p>До ECMAScript 6 в JavaScript отсутствовала область видимости <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Statements">блока</a>; переменная, объявленная внутри блока, является локальной для <em><strong>функции </strong></em>(или <em>глобальной</em> области видимости), внутри которой находится данный блок. Например, следующий код выведет значение 5, т.к. областью видимости переменной <code>x</code> является функция (или глобальный контекст), внутри которой объявлена переменная <code>x</code>, а <em><strong>не блок</strong>,</em> которым в данном случае является оператор <code>if</code>:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">if</span> <span class="punctuation token" style="color: #999999;">(</span><span class="keyword token" style="color: #0077aa;">true</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">var</span> x <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="number token" style="color: #990055;">5</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">}</span> +console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>x<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="punctuation token"> </span><span class="comment token" style="color: #708090;">// 5</span></code></pre> + +<p>Такое поведение меняется, если используется оператор <code>let</code>, введенный в ECMAScript 6:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">if</span> <span class="punctuation token" style="color: #999999;">(</span><span class="keyword token" style="color: #0077aa;">true</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">let</span> y <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="number token" style="color: #990055;">5</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">}</span> +console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>y<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="punctuation token"> </span><span class="comment token" style="color: #708090;">// ReferenceError</span></code></pre> + +<h3 id="Поднятие_переменных">Поднятие переменных</h3> + +<p>Другим необычным свойством переменных в JavaScript является то, что можно сослаться на переменную, которая объявляется позже, и не получить при этом исключения. Эта концепция известна как <strong>поднятие</strong> (hoisting) переменных; переменные в JavaScript поднимаются в самое начало функции или выражения. Однако, переменные, которые еще не были инициализированы, возвратят значение <code>undefined</code>:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="comment token" style="color: #708090;">/* + * Example 1 +*/ +</span>console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>x <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">===</span> undefined<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // true +</span><span class="keyword token" style="color: #0077aa;">var</span> x <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="number token" style="color: #990055;">3</span><span class="punctuation token" style="color: #999999;">;</span> + +<span class="comment token" style="color: #708090;">/* + * Example 2 +*/</span><span class="comment token" style="color: #708090;"> +</span><span class="keyword token" style="color: #0077aa;">var</span> myvar <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="string token" style="color: #669900;">"my value"</span><span class="punctuation token" style="color: #999999;">;</span> + +<span class="punctuation token" style="color: #999999;">(</span><span class="keyword token" style="color: #0077aa;">function</span><span class="punctuation token" style="color: #999999;">(</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>myvar<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // undefined +</span> <span class="keyword token" style="color: #0077aa;">var</span> myvar <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="string token" style="color: #669900;">"local value"</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">}</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">(</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span></code></pre> + +<p>Приведенные выше примеры будут интерпретироваться так же, как:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="comment token" style="color: #708090;">/* + * Example 1 +*/ +</span><span class="keyword token" style="color: #0077aa;">var</span> x<span class="punctuation token" style="color: #999999;">;</span> +console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>x <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">===</span> undefined<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // true +</span>x <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="number token" style="color: #990055;">3</span><span class="punctuation token" style="color: #999999;">;</span> + +<span class="comment token" style="color: #708090;">/* + * Example 2 +*/ +</span><span class="keyword token" style="color: #0077aa;">var</span> myvar <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="string token" style="color: #669900;">"my value"</span><span class="punctuation token" style="color: #999999;">;</span> + +<span class="punctuation token" style="color: #999999;">(</span><span class="keyword token" style="color: #0077aa;">function</span><span class="punctuation token" style="color: #999999;">(</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">var</span> myvar<span class="punctuation token" style="color: #999999;">;</span> + console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>myvar<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // undefined +</span> myvar <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="string token" style="color: #669900;">"local value"</span><span class="punctuation token" style="color: #999999;">;</span> +<span class="punctuation token" style="color: #999999;">}</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">(</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span></code></pre> + +<p>Из-за поднятия переменных, все операторы <code>var</code> в функции следует размещать настолько близко к началу функции, насколько это возможно. Следование этому правилу улучшает ясность кода.</p> + +<p>В ECMAScript 2015, <code>let (const)</code> <strong>не будет подниматься </strong>вверх блока. Однако, ссылки на переменную в блоке до объявления переменной вызовут {{jsxref("ReferenceError")}}<code>.</code> Переменная во "временной мёртвой зоне" в начале блока, до объявления.</p> + +<pre class="brush: js">function do_something() { + console.log(foo); // ReferenceError + let foo = 2; +}</pre> + +<h3 id="Поднятие_функций">Поднятие функций</h3> + +<p>Для функций: только определения функций поднимаются наверх, но не функции, определённые через выражения.</p> + +<pre class="brush: js">/* Определение функции */ +foo(); // "bar" + +function foo() { + console.log("bar"); +} + +/* Определение функции через выражение */ +baz(); // TypeError: baz is not a function + +var baz = function() { + console.log("bar2"); +}; +</pre> + +<h3 id="Глобальные_переменные">Глобальные переменные</h3> + +<p>Глобальные переменные на самом деле являются свойствами <em>глобального объекта</em>. На веб-страницах глобальным объектом является {{domxref("window")}}, поэтому вы можете устанавливать глобальные переменные и обращаться к ним, используя синтаксис <code>window.<em>variable</em></code>:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">window</span></code><span style="color: #999999; font-style: inherit; font-weight: inherit; white-space: pre;">.</span><code class="language-js" style="direction: ltr; white-space: pre;">foo <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="string token" style="color: #669900;">'bar'</span><span class="punctuation token" style="color: #999999;">;</span></code></pre> + +<p>Следовательно, вы можете обращаться к глобальным переменным, объявленным в одном объекте window или frame из другого объекта window или frame, указав имя window или frame. Например, если переменная <code>phoneNumber</code> объявлена в документе, то вы можете сослаться на эту переменную из iframe как <code>parent.phoneNumber</code>.</p> + +<h3 id="Константы"><a id="Constants" name="Constants">Константы</a></h3> + +<p>Вы можете создать именованную константу, доступную только для чтения, используя ключевое слово {{jsxref("Statements/const", "const")}}. Синтаксис идентификатора константы является таким же, как и у идентификатора переменной: он должен начинаться с буквы, нижнего подчеркивания или знака $ и может содержать буквы, цифры или нижнее подчеркивание.</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">const</span> PREFIX <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="string token" style="color: #669900;">'212'</span><span class="punctuation token" style="color: #999999;">;</span></code></pre> + +<p>Нельзя изменить значение константы через присваивание или повторное объявление во время выполнения скрипта. Значение должно быть указано при инициализации.</p> + +<p>Правила, касающиеся области видимости, для констант являются такими же, как и для переменных, объявленных через <code>let</code>. Если ключевое слово <code>const</code> не указано, то идентификатор будет являться переменной.</p> + +<p>Нельзя объявить константу с таким же именем, как у функции или переменной в одной области видимости. Следующие примеры выбросят исключение <code>TypeError</code>:</p> + +<pre class="brush: js"><span style="color: #696969;">// Это вызовет ошибку </span> +function f() <span style="color: #800080;">{</span><span style="color: #800080;">}</span> +const f = 5<span style="color: #808030;">;</span> <span style="color: #696969;"> + +// Это тоже вызовет ошибку </span> +function f() <span style="color: #800080;">{ +</span> const g <span style="color: #808030;">=</span> <span style="color: #008c00;">5</span><span style="color: #800080;">;</span> + var g<span style="color: #800080;">;</span> + +<span style="color: #696969;"> // какие-то выражения </span> +<span style="color: #800080;">}</span> </pre> + +<p>Однако, атрибуты объектов не защищены, так что следующее выражение выполнится без проблем</p> + +<pre class="brush: js">const MY_OBJECT = {"key": "value"}; +MY_OBJECT.key = "otherValue";</pre> + +<h2 id="Структуры_и_типы_данных">Структуры и типы данных</h2> + +<h3 id="Типы_данных">Типы данных</h3> + +<p>Последний стандарт ECMAScript определяет семь типов данных:</p> + +<ul> + <li>Шесть типов данных, которые являются {{Glossary("Primitive", "примитивами")}}: + <ul> + <li>{{Glossary("Boolean")}}. <code>true</code> и <code>false</code>.</li> + <li>{{Glossary("null")}}. Специальное ключевое слово, обозначающее нулевое или «пустое» значение. Поскольку JavaScript чувствителен к регистру, <code>null</code> не то же самое, что <code>Null</code>, <code>NULL</code> или любой другой вариант.</li> + <li>{{Glossary("undefined")}}. Свойство глобального объекта; переменная, не имеющая присвоенного значения, обладает типом <code style="font-style: normal;">undefined</code>.</li> + <li>{{Glossary("Number")}}. <code>42</code> или <code>3.14159</code>.</li> + <li>{{Glossary("String")}}. "Howdy".</li> + <li>{{Glossary("Symbol")}} (ECMAScript 6)</li> + </ul> + </li> + <li>и {{Glossary("Object")}}</li> +</ul> + +<p>Хотя типов данных относительно немного, но они позволяют вам выполнять полезные функции в ваших приложениях. {{jsxref("Object", "Объекты")}} и {{jsxref("Function", "функции")}} являются другими фундаментальными элементами языка. Вы можете думать об объектах как об именованных контейнерах для значений и о функциях как о процедурах, которые ваше приложение может исполнять.</p> + +<h3 id="Преобразование_типов_данных">Преобразование типов данных</h3> + +<p>JavaScript — это динамически типизированный язык. Это означает, что вам не нужно указывать тип данных переменной, когда вы ее объявляете, типы данных преобразуются автоматически по мере необходимости во время выполнения скрипта. Так, например, вы можете определить переменную следующим образом:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> answer <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="number token" style="color: #990055;">42</span><span class="punctuation token" style="color: #999999;">;</span></code></pre> + +<p>А позже вы можете присвоить этой переменной строковое значение, например:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;">answer <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="string token" style="color: #669900;">"Thanks for all the fish..."</span><span class="punctuation token" style="color: #999999;">;</span></code></pre> + +<p>Поскольку JavaScript является динамически типизированным, это присваивание не вызовет сообщения об ошибке.</p> + +<p>В выражениях, включающих числовые и строковые значения с оператором <code>+</code>, JavaScript преобразует числовые значения в строковые. Например:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;">x <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="string token" style="color: #669900;">"The answer is "</span> <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> <span class="number token" style="color: #990055;">42</span><span class="comment token" style="color: #708090;"> // "The answer is 42" +</span>y <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="number token" style="color: #990055;">42</span> <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> <span class="string token" style="color: #669900;">" is the answer"</span><span class="comment token" style="color: #708090;"> // "42 is the answer"</span></code></pre> + +<p>В выражениях с другими операторами JavaScript не преобразует числовые значения в строковые. Например:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="string token" style="color: #669900;">"37"</span> <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">-</span> <span class="number token" style="color: #990055;">7</span><span class="comment token" style="color: #708090;"> // 30 +</span><span class="string token" style="color: #669900;">"37"</span> <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> <span class="number token" style="color: #990055;">7</span><span class="comment token" style="color: #708090;"> // "377"</span></code></pre> + +<h3 id="Преобразование_строк_в_числа">Преобразование строк в числа</h3> + +<p>В том случае, если значение, представляющее число, хранится в памяти как строка, можно использовать методы для преобразования строк в числа:</p> + +<ul> + <li id="parseInt()_and_parseFloat()">{{jsxref("parseInt", "parseInt(numString, [radix])")}}</li> + <li>{{jsxref("parseFloat", "parseFloat(numString)")}}</li> +</ul> + +<p><code>parseInt</code> преобразует строку в целочисленное значение. Хорошей практикой является всегда указывать основание системы счисления (параметр <code>radix</code>).</p> + +<p>Альтернативным способом для получения числа из строки является использование оператора "унарный плюс":</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="string token" style="color: #669900;">"1.1"</span> <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> <span class="string token" style="color: #669900;">"1.1"</span> <span class="comment token" style="color: #708090;">// "1.11.1"</span> +<span class="punctuation token" style="color: #999999;">(</span><span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span><span class="string token" style="color: #669900;">"1.1"</span><span class="punctuation token" style="color: #999999;">)</span> <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> <span class="punctuation token" style="color: #999999;">(</span><span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span><span class="string token" style="color: #669900;">"1.1"</span><span class="punctuation token" style="color: #999999;">)</span> </code><code class="language-js" style="direction: ltr; white-space: pre;"><span class="comment token" style="color: #708090;">// 2.2</span></code><code class="language-js" style="direction: ltr; white-space: pre;"><span class="comment token" style="color: #708090;"> +// Обратите внимание на то, что скобки не являются обязательными и используются для ясности.</span></code></pre> + +<h2 id="Литералы">Литералы</h2> + +<p>Литералы используются для представления значений в JavaScript. Они являются фиксированными значениями, а не переменными. В данной секции рассматриваются следующие типы литералов:</p> + +<ul> + <li>{{anch("Литерал массива")}}</li> + <li>{{anch("Логический литерал")}}</li> + <li>{{anch("Литерал целого числа")}}</li> + <li>{{anch("Литерал числа с плавающей точкой")}}</li> + <li>{{anch("Литерал объекта")}}</li> + <li>{{anch("RegExp литерал")}}</li> + <li>{{anch("Литерал строки")}}</li> +</ul> + +<h3 id="Литерал_массива">Литерал массива</h3> + +<p>Литерал массива — это список из нуля или более выражений, каждое из которых представляет элемент массива, заключенный в квадратные скобки ( <code>[]</code> ). Когда вы создаете массив, используя литерал массива, он инициализируется с помощью переданных значений, которые будут являться его элементами, длина массива будет равна числу переданных аргументов.</p> + +<p>В следующем примере создается массив <code>coffees</code> с тремя элементам и длиной, равной трем:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> coffees <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="punctuation token" style="color: #999999;">[</span><span class="string token" style="color: #669900;">"French Roast"</span><span class="punctuation token" style="color: #999999;">,</span> <span class="string token" style="color: #669900;">"Colombian"</span><span class="punctuation token" style="color: #999999;">,</span> <span class="string token" style="color: #669900;">"Kona"</span><span class="punctuation token" style="color: #999999;">]</span><span class="punctuation token" style="color: #999999;">;</span></code> +</pre> + +<div class="note"> +<p><strong>Замечание :</strong> Обратите внимание на то, что литерал массива является инициализатором объекта. Чтобы получить более подробную информацию, прочитайте <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Working_with_Objects#.D0.98.D1.81.D0.BF.D0.BE.D0.BB.D1.8C.D0.B7.D0.BE.D0.B2.D0.B0.D0.BD.D0.B8.D0.B5_.D0.B8.D0.BD.D0.B8.D1.86.D0.B8.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.BE.D0.B2_.D0.BE.D0.B1.D1.8A.D0.B5.D0.BA.D1.82.D0.B0">Использование инициализаторов объекта</a>.</p> +</div> + +<p>Если массив создается с помощью литерала в скрипте верхнего уровня, то JavaScript интерпретирует массив каждый раз, когда вычисляет выражение, содержащее литерал. Кроме того, литерал, используемый в функции, создается каждый раз, когда вызывается функция.</p> + +<p>Литералы массива также являются объектами <code>Array</code>. Чтобы получить более подробную информацию, прочитайте {{jsxref("Array")}} и <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Indexed_collections">упорядоченные наборы данных</a>.</p> + +<h4 id="Лишние_запятые_в_литералах_array">Лишние запятые в литералах array</h4> + +<p>Не обязательно указывать все элементы в литерале array. Если вы поставите две запятые подряд, то пропущенные элементы будут иметь значение <code>undefined</code>. Например:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> fish <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="punctuation token" style="color: #999999;">[</span><span class="string token" style="color: #669900;">"Lion"</span><span class="punctuation token" style="color: #999999;">,</span> <span class="punctuation token" style="color: #999999;">,</span> <span class="string token" style="color: #669900;">"Angel"</span><span class="punctuation token" style="color: #999999;">]</span><span class="punctuation token" style="color: #999999;">; </span></code><code class="language-js" style="direction: ltr; white-space: pre;"><span class="comment token" style="color: #708090;">// ["Lion", undefined, "Angel"]</span></code></pre> + +<p>У этого массива есть 2 элемента со значениям и один пустой (<code>fish[0]</code> - "Lion", <code>fish[1]</code> - <code>undefined</code>, а <code>fish[2]</code> - "Angel").</p> + +<p>Если вы поставите запятую в конце списка элементов, то она будет проигнорирована. В следующем примере, длина массива равна 3. Нет <code>myList[3]</code>. Все другие запятые в списке говорят о новом элементе.</p> + +<div class="note"> +<p><strong>Замечание :</strong> Лишние запятые могут вызывать ошибки в старых версиях браузеров, поэтому лучше избегать их использования.</p> +</div> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> myList <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="punctuation token" style="color: #999999;">[</span><span class="string token" style="color: #669900;">'home'</span><span class="punctuation token" style="color: #999999;">,</span> <span class="punctuation token" style="color: #999999;">,</span> <span class="string token" style="color: #669900;">'school'</span><span class="punctuation token" style="color: #999999;">,</span> <span class="punctuation token" style="color: #999999;">]</span><span class="punctuation token" style="color: #999999;">; </span><span class="comment token" style="color: #708090;">// ["home", undefined, "school"]</span></code> +</pre> + +<p>В следующем примере длина массива равна четырем, элементы <code>myList[0]</code> и <code>myList[2]</code> имеют значение <code>undefined</code>:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> myList <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="punctuation token" style="color: #999999;">[</span> <span class="punctuation token" style="color: #999999;">,</span> <span class="string token" style="color: #669900;">'home'</span><span class="punctuation token" style="color: #999999;">,</span> <span class="punctuation token" style="color: #999999;">,</span> <span class="string token" style="color: #669900;">'school'</span><span class="punctuation token" style="color: #999999;">]</span><span class="punctuation token" style="color: #999999;">; </span></code><code class="language-js" style="direction: ltr; white-space: pre;"><span class="comment token" style="color: #708090;">// [undefined, "home", undefined, "school"]</span></code></pre> + +<p>В следующем примере длина массива равна четырем, элементы <code>myList[1]</code> и <code>myList[3]</code> имеют значение <code>undefined</code>. Игнорируется только последняя запятая.</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> myList <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="punctuation token" style="color: #999999;">[</span><span class="string token" style="color: #669900;">'home'</span><span class="punctuation token" style="color: #999999;">,</span> <span class="punctuation token" style="color: #999999;">,</span> <span class="string token" style="color: #669900;">'school'</span><span class="punctuation token" style="color: #999999;">,</span> <span class="punctuation token" style="color: #999999;">,</span> <span class="punctuation token" style="color: #999999;">]</span><span class="punctuation token" style="color: #999999;">; </span></code><code class="language-js" style="direction: ltr; white-space: pre;"><span class="comment token" style="color: #708090;">// ["home", undefined, "school", undefined]</span></code></pre> + +<p>Понимание поведения лишних запятых важно для понимания JavaScript как языка. Однако, когда будете писать свой собственный код, то имейте в виду, что явное объявление отсутствующих элементов как <code>undefined</code> улучшает ясность кода и лёгкость его поддержки.</p> + +<h3 id="Логические_литералы">Логические литералы</h3> + +<p>Логический (Boolean) тип имеет два литеральных значения: <code>true</code> и <code>false</code>.</p> + +<p>Не путайте примитивные логические значения <code>true</code> и <code>false</code> со значениями true и false объекта Boolean. Объект Boolean является объектом-обёрткой над примитивом логического типа. Чтобы получить более подробную информацию, прочитайте {{jsxref("Boolean")}}.</p> + +<h3 id="Литерал_целого_числа">Литерал целого числа</h3> + +<p>Целые числа могут быть записаны в десятичной, шестнадцатеричной, восьмеричной и двоичной системах счисления.</p> + +<ul> + <li>Десятичный целочисленный литерал состоит из последовательности цифр без ведущего нуля.</li> + <li>Ведущий ноль в целочисленном литерале указывает на то, что он записан в восьмеричной системе счисления. Восьмеричные целые числа состоят только из цифр 0-7.</li> + <li>Ведущие символы 0x (или 0X) указывают на то, что число шестнадцатеричное. Шестнадцатеричные целые числа могут состоять из цифр 0-9 и букв a-f и A-F. </li> + <li>Ведущие символы 0b (или 0B) указывают на то, что число двоичное. Двоичные числа могут включать в себя только цифры 0 и 1.</li> +</ul> + +<p>Несколько примеров целочисленных литералов:</p> + +<pre class="eval language-html" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-html" style="direction: ltr; white-space: pre;">0, 117 и -345 (десятичная система счисления) +015, 0001 и -077 (восьмеричная система счисления) +0x1123, 0x00111 и -0xF1A7 (</code>шестнадцатеричная система счисления<code class="language-html" style="direction: ltr; white-space: pre;">) +0b11, 0b0011 и -0b11 (двоичная система счисления)</code> +</pre> + +<p>Для дополнительной информации смотрите <a href="/ru/docs/Web/JavaScript/Reference/Lexical_grammar">числовые литералы в лексической грамматике</a>.</p> + +<h3 id="Литерал_числа_с_плавающей_точкой">Литерал числа с плавающей точкой</h3> + +<p>Числа с плавающей точкой могут состоять из следующих частей:</p> + +<ul> + <li>Десятичное целое число, которое может иметь знак (символ "+" или "-", стоящий перед числом),</li> + <li>Десятичная точка ("."),</li> + <li>Дробная часть (другое десятичное число),</li> + <li>Экспонента.</li> +</ul> + +<p>Экспонента состоит из символа "e" или "E", за которым следует целое число, которое может иметь знак. Число с плавающей точкой должно состоять по крайней мере из одной цифры и либо десятичной точки, либо символа "e" (или "E").</p> + +<p>В более сжатой форме синтаксис выглядит следующим образом:</p> + +<pre class="eval language-html" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-html" style="direction: ltr; white-space: pre;">[(+|-)][digits][.digits][(E|e)[(+|-)]digits]</code></pre> + +<p>Примеры:</p> + +<pre class="eval language-html" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-html" style="direction: ltr; white-space: pre;">3.14 +-3.1E+12 +-.3333333333333333333 +.1e-23 +</code></pre> + +<h3 id="Литерал_объекта">Литерал объекта</h3> + +<p>Литерал объекта — это список из нуля или более пар, состоящих из имен свойств и связанных с ними значений, заключенный в фигурные скобки ( <code>{}</code> ). Вам не следует использовать литерал объекта в начале выражения, т.к. это приведет к ошибке или к поведению, которого вы не ожидаете, потому что символ "{" будет интерпретироваться как начало блока.</p> + +<p>В следующем примере свойству <code>myCar</code> объекта <code>car</code> присваивается строка <code>"Saturn"</code>, свойству <code>getCar</code> — результат вызова функции <code>CarTypes("Honda")</code>, свойству <code>special</code> — значение переменной <code>Sales</code>:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> Sales <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="string token" style="color: #669900;">"Toyota"</span><span class="punctuation token" style="color: #999999;">;</span> + +<span class="keyword token" style="color: #0077aa;">function</span> <span class="function token" style="color: #dd4a68;">CarTypes<span class="punctuation token" style="color: #999999;">(</span></span>name<span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">if</span> <span class="punctuation token" style="color: #999999;">(</span>name <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">==</span> <span class="string token" style="color: #669900;">"Honda"</span><span class="punctuation token" style="color: #999999;">)</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">return</span> name<span class="punctuation token" style="color: #999999;">;</span> + <span class="punctuation token" style="color: #999999;">}</span> <span class="keyword token" style="color: #0077aa;">else</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="keyword token" style="color: #0077aa;">return</span> <span class="string token" style="color: #669900;">"Извините, мы не продаём "</span> <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> name <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">+</span> <span class="string token" style="color: #669900;">"."</span><span class="punctuation token" style="color: #999999;">;</span> + <span class="punctuation token" style="color: #999999;">}</span> +<span class="punctuation token" style="color: #999999;">}</span> + +<span class="keyword token" style="color: #0077aa;">var</span> car <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="punctuation token" style="color: #999999;">{</span> myCar<span class="punctuation token" style="color: #999999;">:</span> <span class="string token" style="color: #669900;">"Saturn"</span><span class="punctuation token" style="color: #999999;">,</span> getCar<span class="punctuation token" style="color: #999999;">:</span> <span class="function token" style="color: #dd4a68;">CarTypes<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">"Honda"</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">,</span> special<span class="punctuation token" style="color: #999999;">:</span> Sales <span class="punctuation token" style="color: #999999;">}</span><span class="punctuation token" style="color: #999999;">;</span> + +console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>car<span class="punctuation token" style="color: #999999;">.</span>myCar<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> <span class="comment token" style="color: #708090;"> // Saturn +</span>console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>car<span class="punctuation token" style="color: #999999;">.</span>getCar<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> <span class="comment token" style="color: #708090;"> // Honda +</span>console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>car<span class="punctuation token" style="color: #999999;">.</span>special<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // Toyota</span></code></pre> + +<p>Кроме того, вы можете использовать числовой или строковой литералы в именах свойств или вкладывать один объект в другой. Например:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> car <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="punctuation token" style="color: #999999;">{</span> manyCars<span class="punctuation token" style="color: #999999;">:</span> <span class="punctuation token" style="color: #999999;">{</span>a<span class="punctuation token" style="color: #999999;">:</span> <span class="string token" style="color: #669900;">"Saab"</span><span class="punctuation token" style="color: #999999;">,</span> <span class="string token" style="color: #669900;">"b"</span><span class="punctuation token" style="color: #999999;">:</span> <span class="string token" style="color: #669900;">"Jeep"</span><span class="punctuation token" style="color: #999999;">}</span><span class="punctuation token" style="color: #999999;">,</span> <span class="number token" style="color: #990055;">7</span><span class="punctuation token" style="color: #999999;">:</span> <span class="string token" style="color: #669900;">"Mazda"</span> <span class="punctuation token" style="color: #999999;">}</span><span class="punctuation token" style="color: #999999;">;</span> + +console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>car<span class="punctuation token" style="color: #999999;">.</span>manyCars<span class="punctuation token" style="color: #999999;">.</span>b<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">; </span><span class="comment token" style="color: #708090;">// Jeep +</span>console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>car<span class="punctuation token" style="color: #999999;">[</span><span class="number token" style="color: #990055;">7</span><span class="punctuation token" style="color: #999999;">]</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // Mazda</span></code></pre> + +<p>Именем свойства объекта может быть любая строка, в том числе пустая строка. Если имя свойства не является корректным JavaScript идентификатором, то оно должно быть заключено в кавычки. Для обращения к таким именам следует использовать квадратные скобки ( <code>[]</code> ), а не точку ( <code>.</code> ):</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> unusualPropertyNames <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="punctuation token" style="color: #999999;">{</span> + <span class="string token" style="color: #669900;">""</span><span class="punctuation token" style="color: #999999;">:</span> <span class="string token" style="color: #669900;">"An empty string"</span><span class="punctuation token" style="color: #999999;">,</span> + <span class="string token" style="color: #669900;">"!"</span><span class="punctuation token" style="color: #999999;">:</span> <span class="string token" style="color: #669900;">"Bang!"</span> +<span class="punctuation token" style="color: #999999;">}</span> +console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>unusualPropertyNames<span class="punctuation token" style="color: #999999;">.</span><span class="string token" style="color: #669900;">""</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> <span class="comment token" style="color: #708090;"> // SyntaxError: Unexpected string +</span>console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>unusualPropertyNames<span class="punctuation token" style="color: #999999;">[</span><span class="string token" style="color: #669900;">""</span><span class="punctuation token" style="color: #999999;">]</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> <span class="comment token" style="color: #708090;"> // "An empty string" +</span>console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>unusualPropertyNames<span class="punctuation token" style="color: #999999;">.</span><span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">!</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> <span class="comment token" style="color: #708090;"> // SyntaxError: Unexpected token ! +</span>console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>unusualPropertyNames<span class="punctuation token" style="color: #999999;">[</span><span class="string token" style="color: #669900;">"!"</span><span class="punctuation token" style="color: #999999;">]</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // "Bang!"</span></code> +</pre> + +<p>В ES2015 литералы объектов расширены до поддержки установки прототипа в конструкции короткой записи для <code>foo: </code>задание <code>foo</code>, определение методов, создание супер вызовов и вычисление имён свойств в выражениях. Вместе, они делают похожими объектные литералы и объявления классов, а также позволяют объектному дизайну получать выгоду одинаковых возможностей.</p> + +<pre class="brush: js">var obj = { + // __proto__ + __proto__: theProtoObj, + // Короткая запись для ‘handler: handler’ + handler, + // Методы + toString() { + // Супер вызовы + return "d " + super.toString(); + }, + // Динамическое вычисление имён свойств + [ 'prop_' + (() => 42)() ]: 42 +};</pre> + +<p>Обратите внимание на следующий пример:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> foo <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="punctuation token" style="color: #999999;">{</span>a<span class="punctuation token" style="color: #999999;">:</span> <span class="string token" style="color: #669900;">"alpha"</span><span class="punctuation token" style="color: #999999;">,</span> <span class="number token" style="color: #990055;">2</span><span class="punctuation token" style="color: #999999;">:</span> <span class="string token" style="color: #669900;">"two"</span><span class="punctuation token" style="color: #999999;">}</span><span class="punctuation token" style="color: #999999;">;</span> +console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>foo<span class="punctuation token" style="color: #999999;">.</span>a<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> <span class="comment token" style="color: #708090;"> // alpha +</span>console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>foo<span class="punctuation token" style="color: #999999;">[</span><span class="number token" style="color: #990055;">2</span><span class="punctuation token" style="color: #999999;">]</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span> <span class="comment token" style="color: #708090;"> // two +</span><span class="comment token" style="color: #708090;">// console.log(foo.2); // SyntaxError: Unexpected number +</span><span class="comment token" style="color: #708090;">// console.log(foo[a]); // ReferenceError: a is not defined +</span>console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>foo<span class="punctuation token" style="color: #999999;">[</span><span class="string token" style="color: #669900;">"a"</span><span class="punctuation token" style="color: #999999;">]</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // alpha +</span>console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>foo<span class="punctuation token" style="color: #999999;">[</span><span class="string token" style="color: #669900;">"2"</span><span class="punctuation token" style="color: #999999;">]</span><span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="comment token" style="color: #708090;"> // two</span></code></pre> + +<h3 id="RegExp_литерал">RegExp литерал</h3> + +<p>Литерал regexp - шаблон между слешами. Следующий пример литерал regex:</p> + +<pre class="brush: js">var re = /ab+c/;</pre> + +<h3 id="Строковый_литерал">Строковый литерал</h3> + +<p>Строковый литерал — это ноль или более символов, заключенных в двойные ( <code>"</code> ) или одинарные ( <code>'</code> ) кавычки. Строка должна быть ограничена кавычками одного типа, т.е. либо обе одинарные, либо обе двойные. Например:</p> + +<pre><code>"foo"</code> +<code>'bar'</code> +<code>"1234"</code> +<code>"one line \n another line"</code> +<code>"John's cat"</code></pre> + +<p><code></code>Вы можете вызвать любой из методов объекта <code>String</code> для строкового литерала: JavaScript автоматически преобразует строковой литерал во временный объект <code>String</code>, вызовет метод, а затем уничтожит временный объект <code>String</code>. Вы также можете использовать свойство <code>String.length</code> со строковым литералом:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;">console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span><span class="string token" style="color: #669900;">"John's cat"</span><span class="punctuation token" style="color: #999999;">.</span>length<span class="punctuation token" style="color: #999999;">);</span><span class="comment token" style="color: #708090;"> +// Число символов в строке, включая пробел. +</span><span class="comment token" style="color: #708090;">// В данном случае длина строки равна 10.</span></code></pre> + +<p>В ES2015 также доступны шаблоны строк. Шаблоны строк представляют собой синтаксический сахар для конструирования строк. Это похоже на возможности интерполяции строк в Perl, Python и других. Дополнительно, может быть добавлен тег, позволяющий настраивать конструирование строк, избегая атак внедрения и построения структур данных высокого уровня из содержимого строки.</p> + +<pre class="brush: js">// Простое создание строки через литерал string +`In JavaScript '\n' is a line-feed.` + +// Мультистроковые строки +`In JavaScript this is + not legal.` + +// Интерполяция строк +var name = "Бобби", time = "сегодня"; +`Привет ${name}, как ты ${time}?` + +// Строим префикс HTTP запроса, используемый для интерпретации замен и конструирования +POST`http://foo.org/bar?a=${a}&b=${b} + Content-Type: application/json + X-Credentials: ${credentials} + { "foo": ${foo}, + "bar": ${bar}}`(myOnReadyStateChangeHandler); +</pre> + +<p>Вам следует использовать строковые литералы до тех пор, пока вам специально не понадобится объект <code>String</code>. Чтобы получить более подробную информацию об объекте <code>String</code>, прочитайте {{jsxref("String")}}.</p> + +<h4 id="Использование_специальных_символов_в_строках">Использование специальных символов в строках</h4> + +<p>Кроме обычных символов вы также можете включать специальные символы в строки.</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="string token" style="color: #669900;">"one line \n another line"</span></code></pre> + +<p>В следующей таблице перечислены специальные символы, которые вы можете использовать.</p> + +<table class="standard-table"> + <caption>Специальные символы в JavaScript</caption> + <thead> + <tr> + <th scope="col">Символ</th> + <th scope="col">Значение</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>\b</code></td> + <td>Возврат (Backspace)</td> + </tr> + <tr> + <td><code>\f</code></td> + <td>Перевод или прогон страницы (Form feed)</td> + </tr> + <tr> + <td><code>\n</code></td> + <td>Перевод строки (New line)</td> + </tr> + <tr> + <td><code>\r</code></td> + <td>Возврат каретки (Carriage return)</td> + </tr> + <tr> + <td><code>\t</code></td> + <td>Табуляция (Tab)</td> + </tr> + <tr> + <td><code>\v</code></td> + <td>Вертикальная табуляция (Vertical tab)</td> + </tr> + <tr> + <td><code>\'</code></td> + <td>Апостроф или одинарная кавычка</td> + </tr> + <tr> + <td><code>\"</code></td> + <td>Двойная кавычка</td> + </tr> + <tr> + <td><code>\\</code></td> + <td>Обратная косая черта (Backslash)</td> + </tr> + <tr> + <td><code>\<em>XXX</em></code></td> + <td> + <p>Символ в кодировке Latin-1, представленный тремя восьмеричными числами <em>XXX</em> от 0 до 377. Например, \251 (символ ©).</p> + </td> + </tr> + <tr> + <td><code>\x<em>XX</em></code></td> + <td> + <p>Символ в кодировке Latin-1, представленный двумя шестнадцатеричными числами <em>XX</em> от 00 до FF. Например, \xA9 (символ ©).</p> + </td> + </tr> + <tr> + <td><code>\u<em>XXXX</em></code></td> + <td> + <p>Символ в Unicode, представленный четырьмя шестнадцатеричными числами <em>XXXX</em>. Например, \u00A9 (<span style="background-color: rgba(212, 221, 228, 0.14902);">символ ©).</span></p> + </td> + </tr> + <tr> + <td><code>\u<em>{XXXXX}</em></code></td> + <td>Символ в UTF-32BE. Например, \u{2F804} обозначает то же, что обычная запись \uD87E\uDC04.</td> + </tr> + </tbody> +</table> + +<h4 id="Экранирующие_символы">Экранирующие символы</h4> + +<p>Для символов, не перечисленных в вышеприведенной таблице, предваряющая обратная косая черта игнорируется. Такое использование не является рекомендованным (deprecated) и вам следует избегать его.</p> + +<p>Вы можете вставить кавычку в строку, если поставите перед ней обратную косую черту. Это называется экранированием кавычек. Например:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> quote <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="string token" style="color: #669900;">"He read \"The Cremation of Sam McGee\" by R.W. Service."</span><span class="punctuation token" style="color: #999999;">;</span> +console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>quote<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">; </span></code><code class="language-js" style="direction: ltr; white-space: pre;"><span class="comment token" style="color: #708090;">// He read "The Cremation of Sam McGee" by R.W. Service.</span></code></pre> + +<p>Чтобы включить обратную косую черту в строку, перед ней нужно поставить еще одну обратную косую черту. Например:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> home <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> <span class="string token" style="color: #669900;">"c:\\temp"</span><span class="punctuation token" style="color: #999999;">; </span></code><code class="language-js" style="direction: ltr; white-space: pre;"><span class="comment token" style="color: #708090;">// c:\temp</span></code></pre> + +<p>Вы также можете экранировать перевод строки. Обратная косая черта и перевод строки будут удалены из содержимого строки. Например:</p> + +<pre class="brush: js language-js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> str <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> "<span class="keyword token" style="color: #0077aa;">this</span> string \ +is broken \ +across multiple\ +lines<span class="punctuation token" style="color: #999999;">.</span>" +console<span class="punctuation token" style="color: #999999;">.</span><span class="function token" style="color: #dd4a68;">log<span class="punctuation token" style="color: #999999;">(</span></span>str<span class="punctuation token" style="color: #999999;">)</span><span class="punctuation token" style="color: #999999;">;</span><span class="punctuation token"> </span><span class="comment token" style="color: #708090;">// this string is broken across multiplelines.</span></code></pre> + +<p>Хотя JavaScript не поддерживает синтаксис "heredoc" (форматированный текст в одной строковой переменной), но вы можете эмулировать его, добавив перевод строки и обратную косую черту в конец каждой строки:</p> + +<pre class="brush: js" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal;"><code class="language-js" style="direction: ltr; white-space: pre;"><span class="keyword token" style="color: #0077aa;">var</span> poem <span class="operator token" style="background: rgba(255, 255, 255, 0.498039); color: #a67f59;">=</span> +"Roses are red<span class="punctuation token" style="color: #999999;">,</span>\n\ +Violets are blue<span class="punctuation token" style="color: #999999;">.</span>\n\ +I'm schizophrenic<span class="punctuation token" style="color: #999999;">,</span>\n\ +And so am I<span class="punctuation token" style="color: #999999;">.</span>"</code></pre> + +<h2 id="Дополнительная_информация">Дополнительная информация</h2> + +<p>Данная глава сфокусирована на базовом синтаксисе для объявлений и типов. Чтобы получить более подробную информацию о конструкциях JavaScript, прочитайте:</p> + +<ul> + <li><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Statements">Порядок выполнения и обработка ошибок</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Loops_and_iteration">Циклы и итерация</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Functions">Функции</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Expressions_and_Operators">Выражения и операторы</a></li> +</ul> + +<p>В следующей главе рассматриваются управляющие конструкции и обработка ошибок.</p> + +<p>{{PreviousNext("Web/JavaScript/Guide/Introduction", "Web/JavaScript/Guide/Control_flow_and_error_handling")}}</p> diff --git a/files/ru/web/javascript/guide/index.html b/files/ru/web/javascript/guide/index.html new file mode 100644 index 0000000000..fcd22de953 --- /dev/null +++ b/files/ru/web/javascript/guide/index.html @@ -0,0 +1,131 @@ +--- +title: Руководство JavaScript +slug: Web/JavaScript/Guide +tags: + - Guide + - JavaScript + - 'l10n:priority' +translation_of: Web/JavaScript/Guide +--- +<div>{{jsSidebar("JavaScript Guide")}}</div> + +<p class="summary">"Руководство по JavaScript" покажет вам как использовать <a href="/ru/docs/Web/JavaScript">JavaScript</a> и даст общее представление о языке. Если вам нужна исчерпывающая информация о возможностях языка, посмотрите <a href="/ru/docs/Web/JavaScript/Reference">руководство JavaScript</a>.</p> + +<h2 id="Главы">Главы</h2> + +<p>Это руководство разделено на несколько глав:</p> + +<ul class="card-grid"> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Введение_в_JavaScript">Введение</a></span> + + <p><a href="/ru/docs/Web/JavaScript/Guide/Введение_в_JavaScript#Где_можно_найти_информацию_о_JavaScript">Об этом руководстве</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Введение_в_JavaScript#Что_такое_JavaScript">О JavaScript</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Введение_в_JavaScript#JavaScript_и_Java">JavaScript и Java</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Введение_в_JavaScript#JavaScript_и_спецификация_ECMAScript">ECMAScript</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Введение_в_JavaScript#Начинаем_знакомство_с_JavaScript">Инструменты</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Введение_в_JavaScript#Hello_world">Hello World</a></p> + </li> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Grammar_and_types">Грамматика и типы</a></span> + <p><a href="/ru/docs/Web/JavaScript/Guide/Grammar_and_types#Основы">Базовый синтаксис и комментарии</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Grammar_and_types#Объявления">Объявления</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Grammar_and_types#Область_видимости_переменных">Область видимости переменных</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Grammar_and_types#Поднятие_переменных">Поднятие переменных</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Grammar_and_types#Структуры_и_типы_данных">Структуры и типы данных</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Grammar_and_types#Литералы">Литералы</a></p> + </li> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Control_flow_and_error_handling">Порядок выполнения и обработка ошибок</a></span> + <p><code><a href="/ru/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#Инструкция_if...else">if...else</a></code><br> + <code><a href="/ru/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#Инструкция_switch">switch</a></code><br> + <a href="/ru/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#Инструкции_обработки_исключений"><code>try</code>/<code>catch</code>/<code>throw</code></a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#Использование_объекта_Error">Объекты <code>Error</code></a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#Объект_Promise">Объект <code>Promise</code></a></p> + </li> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Циклы_и_итерации">Циклы и итерации</a></span> + <p><code><a href="/ru/docs/Web/JavaScript/Guide/Циклы_и_итерации#Цикл_for">for</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Циклы_и_итерации#Цикл_while">while</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Циклы_и_итерации#Цикл_do...while">do...while</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Циклы_и_итерации#break">break</a>/<a href="/ru/docs/Web/JavaScript/Guide/Циклы_и_итерации#continue">continue</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Циклы_и_итерации#for...in">for..in</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Циклы_и_итерации#for...of">for..of</a></code></p> + </li> +</ul> + +<ul class="card-grid"> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Functions">Функции</a></span> + + <p><a href="/ru/docs/Web/JavaScript/Guide/Functions#Объявление_функций">Объявление функций</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Functions#Вызов_функций">Вызов функций</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Functions#Область_видимости_функций">Область видимости функций</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Functions#Замыкания">Замыкания</a><br> + <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Functions#%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%B0_arguments">Аргументы</a> и <a href="/ru/docs/Web/JavaScript/Guide/Functions#Параметры_функции">параметры</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Functions#Стрелочные_функции">Стрелочные функции</a></p> + </li> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Expressions_and_Operators">Выражения и операторы</a></span> + <p><a href="/ru/docs/Web/JavaScript/Guide/Expressions_and_Operators#Операторы_присваивания">Присваивание</a> и <a href="/ru/docs/Web/JavaScript/Guide/Expressions_and_Operators#Операторы_сравнения">Сравнение</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Expressions_and_Operators#Арифметические_операторы">Арифметические операторы</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Expressions_and_Operators#Битовые_(поразрядные)_операторы">Побитовые операторы</a> и <a href="/ru/docs/Web/JavaScript/Guide/Expressions_and_Operators#Логические_операторы">логические операторы</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Expressions_and_Operators#Условный_(тернарный)_оператор">Условный (тернарный) операторы</a></p> + </li> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Numbers_and_dates">Числа и даты</a> </span><a href="/ru/docs/Web/JavaScript/Guide/Numbers_and_dates#Numbers">Числовые литералы</a> + <p><a href="/ru/docs/Web/JavaScript/Guide/Numbers_and_dates#Объект_Number">Объект <code>Number</code></a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Numbers_and_dates#Объект_Math">Объект <code>Math</code></a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Numbers_and_dates#Объект_Date">Объект <code>Date</code></a></p> + </li> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Text_formatting">Форматирование текста</a></span> + <p><a href="/ru/docs/Web/JavaScript/Guide/Text_formatting#Строковые_литералы">Строковые литералы</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Text_formatting#Объекты_String">Объект <code>String</code></a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Text_formatting#Многострочные_шаблонные_строки">Шаблонные литералы </a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Text_formatting#Интернационализация">Интернационализация</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Regular_Expressions#Работа_с_Регулярными_Выражениями">Регулярные выражения</a></p> + </li> +</ul> + +<ul class="card-grid"> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Indexed_collections">Индексированные коллекции</a></span> + + <p><a href="/ru/docs/Web/JavaScript/Guide/Indexed_collections#Array_объект">Массивы</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Indexed_collections#Типизированные_массивы">Типизированные массивы</a></p> + </li> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Keyed_collections">Коллекции</a></span> + <p><code><a href="/ru/docs/Web/JavaScript/Guide/Keyed_collections#Тип_Map">Map</a></code><br> + <code><a href="/ru/docs/Web/JavaScript/Guide/Keyed_collections#Тип_WeakMap">WeakMap</a></code><br> + <code><a href="/ru/docs/Web/JavaScript/Guide/Keyed_collections#Тип_Set">Set</a></code><br> + <code><a href="/ru/docs/Web/JavaScript/Guide/Keyed_collections#Тип_WeakSet">WeakSet</a></code></p> + </li> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Working_with_Objects">Работа с объектами</a></span> + <p><a href="/ru/docs/Web/JavaScript/Guide/Working_with_Objects#Объекты_и_свойства">Объекты и свойства</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Working_with_Objects#Создание_новых_объектов">Создание объектов</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Working_with_Objects#Определение_методов">Определение методов</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Working_with_Objects#Определение_геттеров_и_сеттеров">Геттеры и Сеттеры</a></p> + </li> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Details_of_the_Object_Model">Подробнее про объектную модель</a></span> + <p><a href="/ru/docs/Web/JavaScript/Guide/Details_of_the_Object_Model#Языки_основанные_на_классах_против_Прототипно-ориентированных_языков">Прототипно-ориентированное ООП</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Details_of_the_Object_Model#Создание_иерархии">Создание иерархии объектов</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Details_of_the_Object_Model#Наследование_свойств">Наследование</a></p> + </li> +</ul> + +<ul class="card-grid"> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Ispolzovanie_promisov">Промисы</a></span> + + <p><a href="/ru/docs/Web/JavaScript/Guide/Ispolzovanie_promisov#Гарантии">Гарантии</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Ispolzovanie_promisov#Цепочка_вызовов">Цепочка вызовов</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Ispolzovanie_promisov#Распространение_ошибки">Распространенные ошибки</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Ispolzovanie_promisov#Композиция">Композиция</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Ispolzovanie_promisov#Порядок_выполнения">Порядок выполнения</a></p> + </li> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Iterators_and_Generators">Итераторы и Генераторы</a></span> + <p><a href="/ru/docs/Web/JavaScript/Guide/Iterators_and_Generators#Итераторы">Итераторы</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Iterators_and_Generators#Итерируемые_объекты">Итерируемые объекты</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Iterators_and_Generators#Генераторы">Генераторы</a></p> + </li> + <li><span><a href="/ru/docs/Web/JavaScript/Guide/Meta_programming">Мета<br> + программирование</a></span> + <p><a href="/ru/docs/Web/JavaScript/Guide/Meta_programming#Объекты_Proxy">Объект <code>Proxy</code></a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Meta_programming#Обработчики_и_ловушки">Обработчики и ловушки</a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Meta_programming#Отзываемый_Proxy">Отзываемый <code>Proxy</code></a><br> + <a href="/ru/docs/Web/JavaScript/Guide/Meta_programming#Рефлексия">Рефлексия</a></p> + </li> +</ul> + +<p>{{Next("Web/JavaScript/Guide/Introduction")}}</p> diff --git a/files/ru/web/javascript/guide/indexed_collections/index.html b/files/ru/web/javascript/guide/indexed_collections/index.html new file mode 100644 index 0000000000..96ea922455 --- /dev/null +++ b/files/ru/web/javascript/guide/indexed_collections/index.html @@ -0,0 +1,441 @@ +--- +title: Упорядоченные наборы данных +slug: Web/JavaScript/Guide/Indexed_collections +translation_of: Web/JavaScript/Guide/Indexed_collections +--- +<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Regular_Expressions", "Web/JavaScript/Guide/Keyed_Collections")}}</div> + +<p class="summary">Данная глава знакомит читателя с массивами - коллекциями элементов, упорядоченных по индексу. Глава включает в себя описание массивов и массивоподобных структур, таких как {{jsxref("Array")}} и {{jsxref("TypedArray")}}.</p> + +<h2 id="Array_объект"><code>Array</code> объект</h2> + +<p><em>Массив</em> представляется собой упорядоченный набор значений, к которому вы ссылаетесь по имени и индексу. Допустим, у вас есть массив с именем <code>emp,</code> содержащий имена сотрудников и упорядоченный по номеру сотрудников. Следовательно, <code>emp[1]</code> будет представлять собой имя сотрудника номер один, <code>emp[2]</code> -- имя сотрудника номер два, и т.д.</p> + +<p>Язык JavaScript не содержит явного типа данных "массив". Тем не менее, возможно использовать предопределенный объект <code>Array</code> и его методы для работы с массивами в создаваемых приложениях. Объект <code>Array</code> содержит методы для работы с массивами самыми различными способами, например, есть методы для объединения, переворачивания и сортировки. Объект содержит свойство для определения длины массива, а также свойства для работы с регулярными выражениями.</p> + +<h3 id="Создание_массива">Создание массива</h3> + +<p>Следующие выражения создают одинаковые массивы:</p> + +<pre class="brush: js">var arr = new Array(element0, element1, ..., elementN); +var arr = Array(element0, element1, ..., elementN); +var arr = [element0, element1, ..., elementN]; +</pre> + +<p><code>element0, element1, ..., elementN</code> - список значений элементов массива. Если значения заданы, то эти значения будут являться элементами массива после его инициализации. Свойство <code>length</code> у массива будет равно количеству аргументов.</p> + +<p>Синтаксис с использованием квадратных скобок называется "литерал массива" (array literal) или "инициализатор массива". Такая запись короче, чем другие способы создания массива, и, как правило, более предпочтительна. Cм. <a href="/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Array_literals" title="en-US/docs/JavaScript/Guide/Values, Variables, and Literals#Array Literals">Array literals</a>.</p> + +<p>Для создания массива без элементов, но ненулевой длины, возможно использовать одно из следующих выражений:</p> + +<pre class="brush: js">var arr = new Array(arrayLength); +var arr = Array(arrayLength); + +// Точно такой же эффект +var arr = []; +arr.length = arrayLength; +</pre> + +<div class="note"> +<p><strong>Замечание</strong>: в примере выше <code>arrayLength</code> должно иметь числовой тип <code>Number</code>. В противном случае будет создан массив с единственным элементом (указанное значение). Вызванная функция <code>arr.length</code> вернет значение <code>arrayLength</code>, но на самом деле массив будет содержать пустые элементы (undefined). Использование цикла<a href="/en-US/docs/Web/JavaScript/Reference/Statements/for...in"> </a> {{jsxref("Statements/for...in","for...in")}} для обработки значений массива не вернет ни одного элемента.</p> +</div> + +<p>Массивы могут быть присвоены свойству нового или уже существующего объекта, как показано ниже:</p> + +<pre class="brush: js">var obj = {}; +// ... +obj.prop = [element0, element1, ..., elementN]; + +// OR +var obj = {prop: [element0, element1, ...., elementN]} +</pre> + +<p>Если вы хотите инициализировать массив одним элементом и этим элементом является число типа Number, то вы должны использовать квадратные скобки. Если вы создаёте массив с помощью Array (конструктора или функции), а единственным элементом этого массива будет число типа Number, то число это интерпретируется как длина массива (arrayLength), а не как элемент типа Number.</p> + +<pre class="brush: js">var arr = [42]; // Создаёт массив с одним элементом +var arr = Array(42); // Создаёт массив без элементов, + // но устанавлявает длину массива arr.length в 42 + +// Это эквивалентно следующему +var arr = []; +arr.length = 42; +</pre> + +<p>Вызов Array(N) выбросит RangeError, если N не целое значение, чья дробная часть не ноль. Следующий пример иллюстрирует это.</p> + +<pre class="brush: js">var arr = Array(9.3); // RangeError: Invalid array length +</pre> + +<p>Если ваш код нуждается в создании массива с одним элементом произвольного типа данных, то безопасней использовать литеральную запись. Или создайте пустой массив, а затем добавьте необходимый элемент.</p> + +<h3 id="Заполнение_массива">Заполнение массива</h3> + +<p>Вы можете заполнить массив путём присвоения значений его элементам. Для примера:</p> + +<pre class="brush: js">var emp = []; +emp[0] = "Casey Jones"; +emp[1] = "Phil Lesh"; +emp[2] = "August West"; +</pre> + +<div class="note"> +<p><strong>Замечание:</strong> Если вы используете нецелое значение в операторе [] обращения к элементу массива, то будет создано соответствующее свойство в объекте, представляющем массив, вместо элемента массива (так как массивы в JavaScript являются объектами).</p> +</div> + +<pre class="brush: js">var arr = []; +arr[3.4] = "Oranges"; +console.log(arr.length); // 0 +console.log(arr.hasOwnProperty(3.4)); // true +</pre> + +<p>Вы можете заполнить массив во время создания:</p> + +<pre class="brush: js">var myArray = new Array("Hello", myVar, 3.14159); +var myArray = ["Mango", "Apple", "Orange"] +</pre> + +<h3 id="Работа_с_элементами_массива">Работа с элементами массива</h3> + +<p>Вы можете ссылаться на элементы массива путём использования их порядковых номеров. Для примера, предположим, что вы определили следующий массив:</p> + +<pre class="brush: js">var myArray = ["Wind", "Rain", "Fire"]; +</pre> + +<p>Затем вы сослались на первый элемент массива как myArray[0] и второй элемент массива как myArray[1]. Индексация элементов массива начинается с <strong>нуля</strong>.</p> + +<div class="note"> +<p><strong>Замечание: </strong>оператор обращения к элементу массива (квадратные скобки []) также используется для доступа к свойствам массива (массивы также являются объектами в JavaScript). Например:</p> +</div> + +<pre class="brush: js">var arr = ["one", "two", "three"]; +arr[2]; // three +arr["length"]; // Вернёт число 3, так как это свойство - длина массива +</pre> + +<h3 id="Понимание_length">Понимание <code>length</code></h3> + +<p>На уровне реализации, массивы в JavaScript хранят свои элементы как стандартные свойства объекта, используя индекс в качестве имени свойства. Специальное свойство <code>length</code> всегда возвращает индекс посленего элемента плюс один (в примере ниже, элемент 'Dusty' размещается под индексом 30, по этому cats.length возвращает 30 + 1). Особо следует запомнить, что в JavaScript массивы индексируются с нуля: отсчет ведется с 0, а не с 1. Из этого и следует, что свойство <code><code>length</code></code> всегда на единицу больше, чем наибольший индекс хранящийся в массиве:</p> + +<pre class="brush: js">var cats = []; +cats[30] = ['Dusty']; +console.log(cats.length); // 31 +</pre> + +<p>Также, вы можете задавать значение для <code>length</code>. Установка значения меньшего, чем количество хранящихся в массиве элементов, обрезает массив с конца; установка <code>length</code> равным 0 очищает массив полностью:</p> + +<pre class="brush: js">var cats = ['Dusty', 'Misty', 'Twiggy']; +console.log(cats.length); // 3 + +cats.length = 2; +console.log(cats); // выводит в консоль "Dusty,Misty" - элемент "Twiggy" был удален + +cats.length = 0; +console.log(cats); // выводит пустую строку; массив cats пуст + +cats.length = 3; +console.log(cats); // выводит [undefined, undefined, undefined] +</pre> + +<h3 id="Перебор_содержимого_массивов">Перебор содержимого массивов</h3> + +<p>Очень распространенная задача - это перебор всех элементов массива и обработка каждого элемента некоторой операцией. Вот наипростейший способ сделать это:</p> + +<pre class="brush: js">var colors = ['red', 'green', 'blue']; +for (var i = 0; i < colors.length; i++) { + console.log(colors[i]); +} +</pre> + +<p>Если вам заранее известно, что ни один элемент массива не будет расценен как <code>false</code> при приведении к boolean — например, каждый элемент массива является <a href="/en-US/docs/DOM" title="en-US/docs/DOM">DOM</a> узлом, тогда вы можете блеснуть чуть более эффективным оборотом:</p> + +<pre class="brush: js">var divs = document.getElementsByTagName('div'); +for (var i = 0, div; div = divs[i]; i++) { + /* Обработать div некоторой операцией */ +} +</pre> + +<p>Подход в примере выше, позволяет избежать проверки длинны массива при каждой итерации, и лишь убеждается, что переменной <code>div</code> присвоен существующий текущий элемент массива при каждом прохождении цикла.</p> + +<p>Метод {{jsxref("Array.forEach", "forEach()")}} предоставляет другой способ перебора элементов:</p> + +<pre class="brush: js">var colors = ['red', 'green', 'blue']; +colors.forEach(function(color) { + console.log(color); +}); +</pre> + +<p>Как вариант, вы можете сократить код программы, используя стрелочные функции из ES6:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">var</span> colors <span class="operator token">=</span> <span class="punctuation token">[</span><span class="string token">'red'</span><span class="punctuation token">,</span> <span class="string token">'green'</span><span class="punctuation token">,</span> <span class="string token">'blue'</span><span class="punctuation token">]</span><span class="punctuation token">;</span> +colors<span class="punctuation token">.</span><span class="function token">forEach</span><span class="punctuation token">(</span>color <span class="operator token">=</span><span class="operator token">></span> console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>color<span class="punctuation token">)</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="comment token">// red</span> +<span class="comment token">// green</span> +<span class="comment token">// blue</span></code></pre> + +<p>Функция, переданная в метод <code>forEach</code>, будет выполнена по одному разу для каждого элемента массива, при этом сам элемент массива будет передан как аргумент в эту функцию. Элементы, значения которым не присвоены, не обрабатываются <code>forEach</code> циклом.</p> + +<p>Заметьте, что элементы, пропущенные при создании массива не обрабатываются методом <code>forEach</code>, однако, <code>undefined</code> элемент обрабатывается в том случае, когда он присвоен ячейке массива вручную:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">var</span> array <span class="operator token">=</span> <span class="punctuation token">[</span><span class="string token">'first'</span><span class="punctuation token">,</span> <span class="string token">'second'</span><span class="punctuation token">,</span> <span class="punctuation token">,</span> <span class="string token">'fourth'</span><span class="punctuation token">]</span><span class="punctuation token">;</span> + +array<span class="punctuation token">.</span><span class="function token">forEach</span><span class="punctuation token">(</span><span class="keyword token">function</span><span class="punctuation token">(</span>element<span class="punctuation token">)</span> <span class="punctuation token">{</span> + console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>element<span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="comment token">// first</span> +<span class="comment token">// second</span> +<span class="comment token">// fourth</span> + +<span class="keyword token">if</span> <span class="punctuation token">(</span>array<span class="punctuation token">[</span><span class="number token">2</span><span class="punctuation token">]</span> <span class="operator token">===</span> undefined<span class="punctuation token">)</span> <span class="punctuation token">{</span> + console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="string token">'array[2] is undefined'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="comment token">// true</span> +<span class="punctuation token">}</span> + +array <span class="operator token">=</span> <span class="punctuation token">[</span><span class="string token">'first'</span><span class="punctuation token">,</span> <span class="string token">'second'</span><span class="punctuation token">,</span> undefined<span class="punctuation token">,</span> <span class="string token">'fourth'</span><span class="punctuation token">]</span><span class="punctuation token">;</span> + +array<span class="punctuation token">.</span><span class="function token">forEach</span><span class="punctuation token">(</span><span class="keyword token">function</span><span class="punctuation token">(</span>element<span class="punctuation token">)</span> <span class="punctuation token">{</span> + console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>element<span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="comment token">// first</span> +<span class="comment token">// second</span> +<span class="comment token">// undefined</span> +<span class="comment token">// fourth</span></code></pre> + +<p>Так как в JavaScript элементы массива хранятся как обычные свойства объекта, использование {{jsxref("Statements/for...in","for...in")}} циклов для перебора элементов массива нежелательно, потому что будут обработаны не только элементы массива, но и все перечисляемые свойства массива.</p> + +<h3 id="Методы_Array">Методы Array</h3> + +<p>Объект {{jsxref("Array")}} имеет следующие методы:</p> + +<p>{{jsxref("Array.concat", "concat()")}} объединяет два массива и возвращает новый массив.</p> + +<pre>var myArray = new Array("1", "2", "3"); +myArray = myArray.concat("a", "b", "c"); +// myArray = ["1", "2", "3", "a", "b", "c"] +</pre> + +<p>{{jsxref("Array.join", "join(deliminator = ',')")}} объединяет элементы массива в текстовую строку.</p> + +<pre>var myArray = new Array("Wind", "Rain", "Fire"); +var list = myArray.join(" - "); // list = "Wind - Rain - Fire" +</pre> + +<p>{{jsxref("Array.push", "push()")}} добавляет один или несколько элементов в конец массива и возвращает результирующую длину.</p> + +<pre>var myArray = new Array("1", "2"); +myArray.push("3"); // myArray =["1", "2", "3"] +</pre> + +<p>{{jsxref("Array.pop", "pop()")}} удаляет из массива последний элемент и возвращает его.</p> + +<pre>var myArray = new Array("1", "2", "3"); +var last = myArray.pop(); +// myArray =["1", "2"], last = "3" +</pre> + +<p>{{jsxref("Array.shift", "shift()")}} удаляет из массива первый элемент и возвращает его.</p> + +<pre>var myArray = new Array ("1", "2", "3"); +var first = myArray.shift(); +// myArray = ["2", "3"], first = "1" +</pre> + +<p>{{jsxref("Array.shift", "unshift()")}} добавляет один или несколько элементов в начало массива и возвращает его новую длинну.</p> + +<pre class="brush: js">var myArray = new Array ("1", "2", "3"); +myArray.unshift("4", "5"); +// myArray becomes ["4", "5", "1", "2", "3"]</pre> + +<p>{{jsxref("Array.slice", "slice(start_index, upto_index)")}} возвращает секцию массива как новый массив.</p> + +<pre class="brush: js">var myArray = new Array ("a", "b", "c", "d", "e"); +myArray = myArray.slice(1, 4); // начиная с индекса 1 извлекаются элементы вплоть до индекса 3 + // myArray = [ "b", "c", "d"] +</pre> + +<p>{{jsxref("Array.splice", "splice(index, count_to_remove, addElement1, addElement2, ...)")}} удаляет часть элементов из массива и (опционально) заменяет их. Возвращает удалённые элементы.</p> + +<pre class="brush: js">var myArray = new Array ("1", "2", "3", "4", "5"); +myArray.splice(1, 3, "a", "b", "c", "d"); +// myArray = ["1", "a", "b", "c", "d", "5"] +// Этот код, начиная с ячейки под индексом 1 (в которой находилось значение "2"), +// удаляет 3 элемента, и вставляет на их место +// элеметны, переданные в качестве последующих параметров. +</pre> + +<p>{{jsxref("Array.reverse", "reverse()")}} переставляет элементы массива в обратном порядке: первый элемент становится последним, а последний - первым.</p> + +<pre class="brush: js">var myArray = new Array ("1", "2", "3"); +myArray.reverse(); +// элементы переставлены myArray = [ "3", "2", "1" ] +</pre> + +<p>{{jsxref("Array.sort", "sort()")}} сортирует элементы массива.</p> + +<pre class="brush: js">var myArray = new Array("Wind", "Rain", "Fire"); +myArray.sort(); +// массив отсортирован myArray = [ "Fire", "Rain", "Wind" ] +</pre> + +<p><code>Метод sort()</code> может принимать в качестве аргумента <code>callback</code>-функцию, которая определяет каким образом сравнивать элементы массива при сортировке. Функция сравнивает два значения, и возвращает одно из трех значений (список вариантов значений смотрите после примера):</p> + +<p>Пример. Следующий код сортирует массив по последнему символу в строке:</p> + +<pre class="brush: js">var sortFn = function(a, b){ + if (a[a.length - 1] < b[b.length - 1]) return -1; + if (a[a.length - 1] > b[b.length - 1]) return 1; + if (a[a.length - 1] == b[b.length - 1]) return 0; +} +myArray.sort(sortFn); +// массив отсортирован myArray = ["Wind","Fire","Rain"]</pre> + +<ul> + <li>если <code>a</code> меньше чем <code>b</code> в выбранной системе сравнения, возвращаем <em>-1 (или любое отрицательное число)</em></li> + <li>если <code>a</code> больше чем <code>b</code> в выбранной системе сравнения, возвращаем <em>1 (или любое положительное число)</em></li> + <li>если <code>a</code> и <code>b</code> считаются равными, возвращаем <em>0</em>.</li> +</ul> + +<p>{{jsxref("Array.indexOf", "indexOf(searchElement[, fromIndex])")}} ищет в массиве элемент со значением <code>searchElement</code> и возвращает индекс первого совпадения.</p> + +<pre class="brush: js">var a = ['a', 'b', 'a', 'b', 'a']; +console.log(a.indexOf('b')); // выводит 1 +// Попробуем еще раз, начиная с индекса последнего совпадения +console.log(a.indexOf('b', 2)); // выводит 3 +console.log(a.indexOf('z')); // выводит -1, потому что 'z' не найдено +</pre> + +<p>{{jsxref("Array.lastIndexOf", "lastIndexOf(searchElement[, fromIndex])")}} тоже самое, что и <code>indexOf</code>, но поиск ведется в обратном порядке, с конца массива.</p> + +<pre class="brush: js">var a = ['a', 'b', 'c', 'd', 'a', 'b']; +console.log(a.lastIndexOf('b')); // выводит 5 +// Попробуем еще раз, начиная с индекса, предшествующего индексу последнего совпадения +console.log(a.lastIndexOf('b', 4)); // выводит 1 +console.log(a.lastIndexOf('z')); // выводит -1 +</pre> + +<p>{{jsxref("Array.forEach", "forEach(callback[, thisObject])")}} выполняет <code>callback</code>-функцию по каждому элементу массива.</p> + +<pre class="brush: js">var a = ['a', 'b', 'c']; +a.forEach(function(element) { console.log(element);} ); +// выводит в консоль каждый элемент массива по порядку +</pre> + +<p>{{jsxref("Array.map", "map(callback[, thisObject])")}} возвращает новый массив, содержащий результаты вызова <code>callback</code>-функции для каждого элемента исходного массива.</p> + +<pre class="brush: js">var a1 = ['a', 'b', 'c']; +var a2 = a1.map(function(item) { return item.toUpperCase(); }); +console.log(a2); // выводит A,B,C +</pre> + +<p>{{jsxref("Array.filter", "filter(callback[, thisObject])")}} возвращает новый массив, содержащийт только те элементы исходного массива, для которых вызов <code>callback</code>-функции вернул true.</p> + +<pre class="brush: js">var a1 = ['a', 10, 'b', 20, 'c', 30]; +var a2 = a1.filter(function(item) { return typeof item == 'number'; }); +console.log(a2); // выводит 10,20,30 +</pre> + +<p>{{jsxref("Array.every", "every(callback[, thisObject])")}} возвращает true, если вызов <code>callback</code>-функции вернул true для всех элементов массива.</p> + +<pre class="brush: js">function isNumber(value){ + return typeof value == 'number'; +} +var a1 = [1, 2, 3]; +console.log(a1.every(isNumber)); // выводит true +var a2 = [1, '2', 3]; +console.log(a2.every(isNumber)); // выводит false +</pre> + +<p>{{jsxref("Array.some", "some(callback[, thisObject])")}} возвращает true, если вызов <code>callback</code>-функции вернет true хотя бы для одного элемента.</p> + +<pre class="brush: js">function isNumber(value){ + return typeof value == 'number'; +} +var a1 = [1, 2, 3]; +console.log(a1.some(isNumber)); // выводит true +var a2 = [1, '2', 3]; +console.log(a2.some(isNumber)); // выводит true +var a3 = ['1', '2', '3']; +console.log(a3.some(isNumber)); // выводит false +</pre> + +<p>Те из методов выше, что принимают <code>callback</code>-функцию в качестве аргумента, известны как методы итерации (<em>iterative methods)</em>, потому что определенным образом проходятся по всем элементам массива. Каждый из таких методов принимает второй, опциональный элемент, называемый <code>thisObject</code>. Если этот аргумент присутствует, то его значение присваивается ключевому слову <code>this</code> в теле <code>callback</code>-функции. Иначе, как и в любом другом случае вызова функции вне явного контекста, <code>this</code> будет ссылаться на глобальный объект ({{domxref("window")}}).</p> + +<p>В действительности <code>callback</code>-функция вызывается с тремя аргументами. Первый аргумент - текущий элемен массива, второй - индекс этого элемента, и третий - ссылка на сам массив. Однако, в JavaScript, функции игнорируют любые аргументы, которые не перечислены в списке аргументов. Таким образом, нет ничего страшного в использовании функции с одним аргументом, такой как <code>alert</code>.</p> + +<p>{{jsxref("Array.reduce", "reduce(callback[, initialValue])")}} последовательно применяет <code>callback</code>-функцию <code>callback(firstValue, secondValue)</code> для того, чтобы свести все элементы массива к одному значению. В первый параметр функции передаётся предыдущий результат работы функции или первый элемент, а во второй - текущий элемент. Третьим параметром передаётся индекс текущего элемента.</p> + +<pre class="brush: js">var a = [10, 20, 30]; +var total = a.reduce(function(first, second, index) { return first + second; }, 0); +console.log(total) // выводит 60 +</pre> + +<p>{{jsxref("Array.reduceRight", "reduceRight(callback[, initalvalue])")}} работает так же как и <code>reduce()</code>, но порядок обхода ведется от конца к началу.</p> + +<p><code>Методы reduce</code> и <code>reduceRight</code> являются наименее очевидными методами объекта Array. Они должны использоваться в алгоритмах, которые рекурсивно совмещают два элемента массива, для сведения всей последовательности к одному значению.</p> + +<h3 id="Многомерные_массивы">Многомерные массивы</h3> + +<p>Массивы могут быть вложенными, то есть массив может содержать массивы в элементах. Используя эту возможность массивов JavaScript, можно построить многомерные массивы.</p> + +<p>Следующий код создает двумерный массив:</p> + +<pre class="brush: js">var a = new Array(4); +for (i = 0; i < 4; i++) { + a[i] = new Array(4); + for (j = 0; j < 4; j++) { + a[i][j] = "[" + i + "," + j + "]"; + } +} +</pre> + +<p>В этом примере создается массив со следующим содержимым:</p> + +<pre>Ряд 0: [0,0] [0,1] [0,2] [0,3] +Ряд 1: [1,0] [1,1] [1,2] [1,3] +Ряд 2: [2,0] [2,1] [2,2] [2,3] +Ряд 3: [3,0] [3,1] [3,2] [3,3] +</pre> + +<h3 id="Массивы_и_регулярные_выражения">Массивы и регулярные выражения</h3> + +<p>Когда массив является результатом вычислений регулярного выражения над строкой, он содержит свойтсва и элементы с информацией о совпадениях. Массив возвращается функциями {{jsxref("Global_Objects/RegExp/exec","RegExp.exec()")}}, {{jsxref("Global_Objects/String/match","String.match()")}} и {{jsxref("Global_Objects/String/split","String.split()")}} Подробнее о том, как использовать массивы с регулярными выражениями смотрите в <a href="/en-US/docs/Web/JavaScript/Guide/Regular_Expressions" title="en-US/docs/JavaScript/Guide/Regular Expressions">Regular Expressions</a>.</p> + +<h3 id="Работа_с_массивоподобными_объектами">Работа с массивоподобными объектами</h3> + +<p>Некоторые объекты в JavaScript, такие как {{domxref("NodeList")}}, возвращаемые методом {{domxref("document.getElementsByTagName()")}}, или специальный объект {{jsxref("Functions/arguments","arguments")}}, доступный внутри функции, выглядят и ведут себя как обычные массивы, однако не имеет всех присущих массиву методов. Так например, объект <code>arguments</code> имеет свойство {{jsxref("Global_Objects/Function/length","length")}}, но не имеет метода {{jsxref("Array.forEach", "forEach()")}}.</p> + +<p>Методы из прототипа Array, могут быть вызваны для массивоподобных объектов. Например:</p> + +<pre><code>function printArguments() { + Array.prototype.forEach.call(arguments, function(item) { + console.log(item); + }); +}</code></pre> + +<p>Также методы из прототипа Array могут быть применены и к строкам, потому как строки предоставляют доступ к своим символам сходным образом:</p> + +<pre class="brush: js"><code>Array.prototype.forEach.call</code>("a string", function(chr) { + console.log(chr); +});</pre> + +<h2 id="Типизированные_массивы">Типизированные массивы</h2> + +<p><a href="/en-US/docs/Web/JavaScript/Typed_arrays">JavaScript typed arrays</a> (типизированные массивы) являются массивоподобными объектами, которые предоставляют механизм доступа к сырым бинарным данным. Как вы уже знаете, {{jsxref("Array")}} массивы динамически растут, сокращаются и могут содержать значения любых типов JavaScript. Движки JavaScript производят оптимизации, благодаря чему, эти операции происходят быстро. Однако, веб приложения становятся все более мощными, добавляются возможности манипуляции со звуковыми и видеоданными, доступ к сырым данным <a href="/en-US/docs/WebSockets">WebSockets</a>, и тому подобное. Становится очевидным, что возможность быстрой и эффективной работы с двоичными данными в JavaScript будет очень полезной. Для чего типизированные массивы и предназначены.</p> + +<h3 id="Буферы_и_представления_архитектура_типизированных_массивов">Буферы и представления: архитектура типизированных массивов</h3> + +<p>Для достижения максимальной гибкости и производительности, реализация типизированных массивов в JavaScript разделена на <strong>буферы</strong> и <strong>представления</strong>. Буфер ({{jsxref("ArrayBuffer")}}) это объект, представляющий из себя блок данных; он не имеет формата и не предоставляет возможности доступа к своему содержимому. Для доступа к памяти буфера вам нужно использовать представление. Представление являет собой контекст, имеющий тип данных, начальную позицию в буфере, и количество элементов — это позволяет представить данные в виде актуального типизированного массива.</p> + +<p><img alt="Typed arrays in an ArrayBuffer" src="https://mdn.mozillademos.org/files/8629/typed_arrays.png" style="height: 278px; width: 666px;"></p> + +<h3 id="ArrayBuffer">ArrayBuffer</h3> + +<p>Объект {{jsxref("ArrayBuffer")}} это стандартный набор бинарных данных с фиксированной длиной. Вы не можете манипулировать содержимым <code>ArrayBuffer</code> напрямую. Вместо этого необходимо создать типизированное представление {{jsxref("DataView")}}, которое будет отображать буфер в определенном формате, и даст доступ на запись и чтение его содержимого.</p> + +<h3 id="Типизированные_представления">Типизированные представления</h3> + +<p>Название типизированного представления массива говорит само за себя. Оно представляет массив в распространенных числовых форматах, таких как <code>Int8</code>, <code>Uint32</code>, <code>Float64</code> и так далее. Среди прочих существует специальное представление <code>Uint8ClampedArray</code>. Оно ограничивает значения интервалом от 0 до 255. Это полезно, например, при <a href="/en-US/docs/Web/API/ImageData">Обработке данных изображения в Canvas</a>.</p> + +<p>{{page("en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray", "TypedArray_objects")}}</p> + +<p>Для получения подробных сведений смотрите <a href="/en-US/docs/Web/JavaScript/Typed_arrays">Типизированные массивы JavaScript</a> и справочную документацию для {{jsxref("TypedArray")}}.</p> + +<p>{{PreviousNext("Web/JavaScript/Guide/Regular_Expressions", "Web/JavaScript/Guide/Keyed_Collections")}}</p> diff --git a/files/ru/web/javascript/guide/ispolzovanie_promisov/index.html b/files/ru/web/javascript/guide/ispolzovanie_promisov/index.html new file mode 100644 index 0000000000..a910dfca09 --- /dev/null +++ b/files/ru/web/javascript/guide/ispolzovanie_promisov/index.html @@ -0,0 +1,321 @@ +--- +title: Использование промисов +slug: Web/JavaScript/Guide/Ispolzovanie_promisov +tags: + - JavaScript + - Асинхронность + - Гайд + - промис +translation_of: Web/JavaScript/Guide/Using_promises +--- +<div> +<p>{{jsSidebar("Руководство по JavaScript")}}{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Iterators_and_Generators")}}</p> +</div> + +<p class="summary">{{jsxref("Promise")}} (промис, англ. "обещание") - это объект, представляющий результат успешного или неудачного завершения асинхронной операции. Так как большинство людей пользуются уже созданными промисами, это руководство начнем с объяснения использования вернувшихся промисов до объяснения принципов создания. </p> + +<p>В сущности, промис - это возвращаемый объект, в который вы записываете два коллбэка вместо того, чтобы передать их функции.</p> + +<p>Например, вместо старомодной функции, которая принимает два коллбэка и вызывает один из них в зависимости от успешного или неудачного завершения операции:</p> + +<pre class="brush: js line-numbers language-js">function doSomethingOldStyle(successCallback, failureCallback) { + console.log("Готово."); + // Успех в половине случаев. + if (Math.random() > .5) { + successCallback("Успех") + } else { + failureCallback("Ошибка") + } +} + +function successCallback(result) { + console.log("Успешно завершено с результатом " + result); +} + +function failureCallback(error) { + console.log("Завершено с ошибкой " + error); +} + +doSomethingOldStyle(successCallback, failureCallback); +</pre> + +<p>…современные функции возвращают промис, в который вы записываете ваши коллбэки:</p> + +<pre class="brush: js line-numbers language-js">function doSomething() { + return new Promise((resolve, reject) => { + console.log("Готово."); + // Успех в половине случаев. + if (Math.random() > .5) { + resolve("Успех") + } else { + reject("Ошибка") + } + }) +} + +const promise = doSomething(); +promise.then(successCallback, failureCallback);</pre> + +<p>…или просто:</p> + +<pre class="brush: js line-numbers language-js">doSomething().then(successCallback, failureCallback);</pre> + +<p>Мы называем это <em>асинхронным вызовом функции</em>. У этого соглашения есть несколько преимуществ. Давайте рассмотрим их.</p> + +<h2 id="Гарантии">Гарантии</h2> + +<p>В отличие от старомодных переданных коллбэков промис дает некоторые гарантии:</p> + +<ul> + <li>Коллбэки никогда не будут вызваны до <a href="/ru/docs/Web/JavaScript/EventLoop#Никогда_не_блокируется">завершения обработки текущего события</a> в событийном цикле JavaScript.</li> + <li>Коллбеки, добавленные через .then даже <em>после </em>успешного или неудачного завершения асинхронной операции, будут также вызваны.</li> + <li>Несколько коллбэков может быть добавлено вызовом .then нужное количество раз, и они будут выполняться независимо в порядке добавления.</li> +</ul> + +<p>Но наиболее непосредственная польза от промисов - цепочка вызовов (<em>chaining</em>).</p> + +<h2 id="Цепочка_вызовов">Цепочка вызовов</h2> + +<p>Общая нужда - выполнять две или более асинхронных операции одна за другой, причём каждая следующая начинается при успешном завершении предыдущей и использует результат её выполнения. Мы реализуем это, создавая цепочку вызовов промисов (<em>promise chain</em>).</p> + +<p>Вот в чём магия: функция <code>then</code> возвращает новый промис, отличающийся от первоначального:</p> + +<pre class="brush: js">let promise = doSomething(); +let promise2 = promise.then(successCallback, failureCallback); +</pre> + +<p>или</p> + +<pre class="brush: js">let promise2 = doSomething().then(successCallback, failureCallback); +</pre> + +<p>Второй промис представляет завершение не только <code>doSomething()</code>, но и функций <code>successCallback</code> или <code>failureCallback</code>, переданных Вами, а они тоже могут быть асинхронными функциями, возвращающими промис. В этом случае все коллбэки, добавленные к <code>promise2</code> будут поставлены в очередь за промисом, возвращаемым <code>successCallback</code> или <code>failureCallback</code>.</p> + +<p>По сути, каждый вызванный промис означает успешное завершение предыдущих шагов в цепочке.</p> + +<p>Раньше выполнение нескольких асинхронных операций друг за другом приводило к классической "Вавилонской башне" коллбэков:</p> + +<pre class="brush: js">doSomething(function(result) { + doSomethingElse(result, function(newResult) { + doThirdThing(newResult, function(finalResult) { + console.log('Итоговый результат: ' + finalResult); + }, failureCallback); + }, failureCallback); +}, failureCallback); +</pre> + +<p>В современных функциях мы записываем коллбэки в возвращаемые промисы - формируем цепочку промисов:</p> + +<pre class="brush: js">doSomething().then(function(result) { + return doSomethingElse(result); +}) +.then(function(newResult) { + return doThirdThing(newResult); +}) +.then(function(finalResult) { + console.log('Итоговый результат: ' + finalResult); +}) +.catch(failureCallback); +</pre> + +<p>Аргументы <code>then</code> необязательны, а <code>catch(failureCallback)</code> - это сокращение для <code>then(null, failureCallback)</code>. Вот как это выражено с помощью <a href="/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions">стрелочных функций</a>:</p> + +<pre class="brush: js">doSomething() +.then(result => doSomethingElse(result)) +.then(newResult => doThirdThing(newResult)) +.then(finalResult => { + console.log(`Итоговый результат: ${finalResult}`); +}) +.catch(failureCallback); +</pre> + +<p><strong>Важно:</strong> Всегда возвращайте промисы в return, иначе коллбэки не будут сцеплены и ошибки могут быть не пойманы (стрелочные функции неявно возвращают результат, если скобки {} вокруг тела функции опущены).</p> + +<h3 id="Цепочка_вызовов_после_catch">Цепочка вызовов после catch</h3> + +<p>Можно продолжить цепочку вызовов <em>после </em>ошибки, т. е. после <code>catch</code>, что полезно для выполнения новых действий даже после того, как действие вернет ошибку в цепочке вызовов. Ниже приведен пример:</p> + +<pre class="syntaxbox"><code class="language-js"><span class="keyword token">new</span> <span class="class-name token">Promise</span><span class="punctuation token">(</span><span class="punctuation token">(</span>resolve<span class="punctuation token">,</span> reject<span class="punctuation token">)</span> <span class="operator token">=</span><span class="operator token">></span> <span class="punctuation token">{</span> + console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="string token">'</span></code>Начало<code class="language-js"><span class="string token">'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +</code> + resolve(); +}) +.then(() => { + throw new Error('Где-то произошла ошибка'); + + console.log('Выведи это'); +}) +.catch(() => { + console.log('Выведи то'); +}) +.then(() => { + console.log('Выведи это, несмотря ни на что'); +});</pre> + +<p>В результате выведется данный текст:</p> + +<pre>Начало +Выведи то +Выведи это, несмотря ни на что</pre> + +<p>Заметьте, что текст "Выведи это" не вывелся, потому что "Где то произошла ошибка" привела к отказу</p> + +<h2 id="Распространение_ошибки">Распространение ошибки</h2> + +<p>Вы могли ранее заметить, что <code>failureCallback</code> повторяется три раза в <strong>"pyramid of doom", </strong>а в цепочке промисов всего лишь один раз:</p> + +<pre><code>doSomething() +.then(result => doSomethingElse(result)) +.then(newResult => doThirdThing(newResult)) +.then(finalResult => console.log(`</code>Итоговый результат<code>: ${finalResult}`)) +.catch(failureCallback);</code></pre> + +<p>В основном, цепочка промисов останавливает выполнение кода, если где-либо произошла ошибка, и вместо этого ищет далее по цепочке обработчики ошибок. Это очень похоже на то, как работает синхронный код:</p> + +<pre><code>try { + let result = syncDoSomething(); + let newResult = syncDoSomethingElse(result); + let finalResult = syncDoThirdThing(newResult); + console.log(`</code>Итоговый результат<code>: ${finalResult}`); +} catch(error) { + failureCallback(error); +}</code> +</pre> + +<p>Эта симметрия с синхронным кодом лучше всего показывает себя в синтаксическом сахаре <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function"><code>async</code>/<code>await</code></a> в ECMAScript 2017:</p> + +<pre><code>async function foo() { + try { + let result = await doSomething(); + let newResult = await doSomethingElse(result); + let finalResult = await doThirdThing(newResult); + console.log(`</code>Итоговый результат<code>: ${finalResult}`); + } catch(error) { + failureCallback(error); + } +}</code> +</pre> + +<p>Работа данного кода основана на промисах. Для примера здесь используется функция <code>doSomething()</code>, которая встречалась ранее. Вы можете прочитать больше о синтаксисе <a href="https://developers.google.com/web/fundamentals/getting-started/primers/async-functions">здесь</a></p> + +<p>Примисы решают основную проблему пирамид, обработку всех ошибок, даже вызовов исключений и программных ошибок. Это основа для функционального построения асинхронных операций.</p> + +<h2 id="Создание_промиса_вокруг_старого_коллбэка">Создание промиса вокруг старого коллбэка</h2> + +<p>{{jsxref("Promise")}} может быть создан с помощью конструктора. Это может понадобится только для старых API.</p> + +<p>В идеале, все асинхронные функции уже должны возвращать промис. Но увы, некоторые APIs до сих пор ожидают успешного или неудачного коллбека переданных по старинке. Типичный пример: {{domxref("WindowTimers.setTimeout", "setTimeout()")}} функция:</p> + +<pre><code>setTimeout(() => saySomething("10 seconds passed"), 10000);</code></pre> + +<p>Смешивание старого коллбэк-стиля и промисов проблематично. В случае неудачного завершения <code>saySomething</code> или программной ошибки, нельзя обработать ошибку.</p> + +<p>К с частью мы можем обернуть функцию в промис. Хороший тон оборачивать проблематичные функции на самом низком возможном уровне, и больше никогда их не вызывать на прямую:</p> + +<pre><code>const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); + +wait(10000).then(() => saySomething("10 seconds")).catch(failureCallback);</code></pre> + +<p>В сущности, конструктор промиса становится исполнителем функции, который позволяет нам резолвить или режектить промис вручную. Так как <code>setTimeout</code> всегда успешен, мы опустили reject в этом случае.</p> + +<h2 id="Композиция">Композиция</h2> + +<p>{{jsxref("Promise.resolve()")}} и {{jsxref("Promise.reject()")}} короткий способ создать уже успешные или отклоненные промисы соответственно. Это иногда бывает полезно.</p> + +<p>{{jsxref("Promise.all()")}} и {{jsxref("Promise.race()")}} - два метода запустить асинхронные операции параллельно.</p> + +<p>Последовательное выполнение композиции возможно при помощи хитрости JavaScript:</p> + +<pre><code>[func1, func2].reduce((p, f) => p.then(f), Promise.resolve());</code></pre> + +<p>Фактически, мы превращаем массив асинхронных функций в цепочку промисов равносильно: <code>Promise.resolve().then(func1).then(func2);</code></p> + +<p>Это также можно сделать, объеденив композицию в функцию, в функциональном стиле программирования:</p> + +<pre><code>const applyAsync = (acc,val) => acc.then(val); +const composeAsync = (...funcs) => x => funcs.reduce(applyAsync, Promise.resolve(x));</code></pre> + +<p><code>composeAsync</code> функция примет любое количество функций в качестве аргументов и вернет новую функцию которая примет в параметрах начальное значение, переданное по цепочке. Это удобно, потому что некоторые или все функции могут быть либо асинхронными либо синхронными, и они гарантированно выполнятся в правильной последовательности:</p> + +<pre><code>const transformData = composeAsync(func1, asyncFunc1, asyncFunc2, func2); +transformData(data);</code></pre> + +<p>В ECMAScript 2017, последовательные композиции могут быть выполненны более простым способом с помощью async/await:</p> + +<pre><code>for (const f of [func1, func2]) { + await f(); +}</code></pre> + +<h2 id="Порядок_выполнения">Порядок выполнения</h2> + +<p>Чтобы избежать сюрпризов, функции, переданные в <code>then</code> никогда не будут вызванны синхронно, даже с уже разрешенным промисом:</p> + +<pre><code>Promise.resolve().then(() => console.log(2)); +console.log(1); // 1, 2</code></pre> + +<p>Вместо немедленного выполнения, переданная функция встанет в очередь микрозадач, а значит выполнится, когда очередь будет пустой в конце текущего вызова JavaScript цикла событий (event loop), т.е. очень скоро:</p> + +<pre><code>const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); + +wait().then(() => console.log(4)); +Promise.resolve().then(() => console.log(2)).then(() => console.log(3)); +console.log(1); // 1, 2, 3, 4</code></pre> + +<h2 id="Вложенность">Вложенность</h2> + +<p>Простые цепочки promise лучше оставлять без вложений, так как вложеность может быть результатом небрежной структуры. Смотрите <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Ispolzovanie_promisov$edit#Common_mistakes">распространенные ошибки</a>.</p> + +<p>Вложенность - это управляющая структура, ограничивающая область действия операторов catch. В частности, вложенный catch только перехватывает сбои в своей области и ниже, а не ошибки выше в цепочке за пределами вложенной области. При правильном использовании это дает большую точность в извлечение ошибок:</p> + +<pre><code>doSomethingCritical() +.then(result => doSomethingOptional() + .then(optionalResult => doSomethingExtraNice(optionalResult)) + .catch(e => {})) // Игнорируется если необязательные параметр не выкинул исключение +.then(() => moreCriticalStuff()) +.catch(e => console.log("Критическая ошибка: " + e.message));</code></pre> + +<p>Обратите внимание, что необязательный шаги здесь выделены отступом.</p> + +<p>Внутренний оператор catch нейтрализует и перехватывает ошибки только от doSomethingOptional() и doSomethingExtraNice(), после чего код возобновляется с помощью moreCriticalStuff(). Важно, что в случае сбоя doSomethingCritical() его ошибка перехватывается только последним (внешним) catch.</p> + +<h2 id="Частые_ошибки">Частые ошибки</h2> + +<p>В этом разделе собраны частые ошибки, возникающие при создании цепочек обещаний. Несколько таких ошибок можно увидеть в следующем примере:</p> + +<pre><code>// Плохой пример! Три ошибки! + +doSomething().then(function(result) { + doSomethingElse(result) // Забыл вернуть обещание из внутренней цепочки + неуместное влаживание + .then(newResult => doThirdThing(newResult)); +}).then(() => doFourthThing()); +// Забыл закончить цепочку методом catch</code></pre> + +<p>Первая ошибка это неправильно сцепить вещи между собой. Такое происходит когда мы создаем промис но забываем вернуть его. Как следствие, цепочка сломана, но правильнее было бы сказать что теперь у нас есть две независимые цепочки, соревнующиеся за право разрешится первой. Это означает <code>doFourthThing()</code> не будет ждать <code>doSomethingElse()</code> или <code>doThirdThing()</code> пока тот закончится, и будет исполнятся параллельно с ними, это ,вероятно, не то что хотел разработчик. Отдельные цепочки также имеют отдельную обработку ошибок, что приводит к необработанным ошибкам.</p> + +<p>Вторая ошибка это излишняя вложенность, включая первую ошибку. Вложенность также ограничивает область видимости внутренних обработчиков ошибок, если это не то чего хотел разработчик, это может привести к необработанным ошибкам. Примером этого является <a href="https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it">пример как не нужно создавать обещания</a>, который комбинирует вложенность с чрезмерным использованием конструктора обещаний для оборачивания кода который уже использует промисы.</p> + +<p>Третяя ошибка это забыть закончить цепочку ключевым словом <code>catch</code>. Незаконченные цепочки приводят к необработанным отторжениям обещаний в большинстве браузеров.</p> + +<p>Хорошим примером является всегда либо возвращать либо заканчивать цепочки обещаний, и как только вы получаете новое обещание, возвращайте его сразу же, чтобы не усложнять код излишней вложенностью:</p> + +<pre><code>doSomething() +.then(function(result) { + return doSomethingElse(result); +}) +.then(newResult => doThirdThing(newResult)) +.then(() => doFourthThing()) +.catch(error => console.log(error));</code></pre> + +<p>Обратите внимание что <code>() => x</code> это сокращенная форма <code>() => { return x; }</code>.</p> + +<p>Теперь у нас имеется единственная определенная цепочка с правильной обработкой ошибок.</p> + +<p>Использование <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function"><code>async</code>/<code>await</code></a> предотвращает большинство, если не все вышеуказанные ошибки—но взамен появляется другая частая ошибка—забыть ключевое слово <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function"><code>await</code></a>.</p> + +<h2 id="Смотрите_также">Смотрите также</h2> + +<ul> + <li>{{jsxref("Promise.then()")}}</li> + <li><a href="http://promisesaplus.com/">Спецификация Promises/A+ (EN)</a></li> + <li><a href="http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html">Нолан Лоусон (Nolan Lawson): У нас проблемы с промисами - распространенные ошибки (EN)</a></li> +</ul> diff --git a/files/ru/web/javascript/guide/iterators_and_generators/index.html b/files/ru/web/javascript/guide/iterators_and_generators/index.html new file mode 100644 index 0000000000..a04e4b6384 --- /dev/null +++ b/files/ru/web/javascript/guide/iterators_and_generators/index.html @@ -0,0 +1,159 @@ +--- +title: Итераторы и генераторы +slug: Web/JavaScript/Guide/Iterators_and_Generators +tags: + - yield + - Генераторы + - Итераторы +translation_of: Web/JavaScript/Guide/Iterators_and_Generators +--- +<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Meta_programming")}}</div> + +<p class="summary">Обработка каждого элемента коллекции является весьма распространенной операцией. JavaScript предоставляет несколько способов перебора коллекции, от простого цикла <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/for" title="en/Core_JavaScript_1.5_Reference/Statements/for">for</a></code> до <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" title="en/Core_JavaScript_1.5_Reference/Global_Objects/Array/map">map()</a></code>, <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter" title="en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter">filter()</a></code> и <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Array_comprehensions" title="en/JavaScript/Guide/Predefined Core Objects#Array comprehensions">array comprehensions</a>. Итераторы и генераторы внедряют концепцию перебора непосредственно в ядро языка и обеспечивают механизм настройки поведения <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/for...of" title="en/Core_JavaScript_1.5_Reference/Statements/for...in">for...of</a></code> циклов.</p> + +<p>Подробнее см. также:</p> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Iteration_protocols">Iteration protocols</a></li> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/for...of">for...of</a></code></li> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/function*">function*</a></code> и {{jsxref("Generator")}}</li> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/yield">yield</a></code> и <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/yield*">yield*</a></code></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Generator_comprehensions">Generator comprehensions</a> {{experimental_inline}}</li> +</ul> + +<h2 id="Итераторы">Итераторы</h2> + +<p>Объект является итератором, если он умеет обращаться к элементам коллекции по одному за раз, при этом отслеживая свое текущее положение внутри этой последовательности. В JavaScript итератор - это объект, который предоставляет метод next(), возвращающий следующий элемент последовательности. Этот метод возвращает объект с двумя свойствами: done и value.</p> + +<p>После создания, объект-итератор может быть явно использован, с помощью вызовов метода next().</p> + +<pre class="brush: js">function makeIterator(array){ + var nextIndex = 0; + + return { + next: function(){ + return nextIndex < array.length ? + {value: array[nextIndex++], done: false} : + {done: true}; + } + } +}</pre> + +<p>После инициализации, метод next() может быть вызван для поочередного доступа к парам ключ-значение в объекте:</p> + +<pre class="brush: js">var it = makeIterator(['yo', 'ya']); +console.log(it.next().value); // 'yo' +console.log(it.next().value); // 'ya' +console.log(it.next().done); // true</pre> + +<h2 id="Генераторы">Генераторы</h2> + +<p>В то время как пользовательские итераторы могут быть весьма полезны, при их программировании требуется уделять серьезное внимание поддержке внутреннего состояния. <strong>{{jsxref("Global_Objects/Generator","Генераторы","","true")}}</strong> предоставляют мощную альтернативу: они позволяют определить алгоритм перебора, написав единственную функцию, которая умеет поддерживать собственное состояние.</p> + +<p>Генераторы - это специальный тип функции, который работает как фабрика итераторов. Функция становится генератором, если содержит один или более {{jsxref("Operators/yield","yield")}} операторов и использует {{jsxref("Statements/function*","function*")}} синтаксис.</p> + +<pre class="brush: js">function* idMaker(){ + var index = 0; + while(true) + yield index++; +} + +var it = idMaker(); + +console.log(it.next().value); // 0 +console.log(it.next().value); // 1 +console.log(it.next().value); // 2 +// ...</pre> + +<h2 id="Итерируемые_объекты">Итерируемые объекты</h2> + +<p>Объект является итерируемым, если в нем определен способ перебора значений, то есть, например, как значения перебираются в конструкции {{jsxref("Statements/for...of", "for..of")}}. Некоторые встроенные типы, такие как {{jsxref("Array")}} или {{jsxref("Map")}}, по умолчанию являются итерируемыми, в то время как другие типы, как, например, {{jsxref("Object")}}, таковыми не являются.</p> + +<p>Чтобы быть итерируемым, объект обязан реализовать метод <strong>@@iterator</strong>, что означает, что он (или один из объектов выше по <a href="/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain">цепочке прототипов</a>) обязан иметь свойство с именем {{jsxref("Symbol.iterator")}}:</p> + +<h3 id="Пользовательские_итерируемые_объекты">Пользовательские итерируемые объекты</h3> + +<p>Мы можем создать свои собственные итерируемые объекты так:</p> + +<pre class="brush: js">var myIterable = {} +myIterable[Symbol.iterator] = function* () { + yield 1; + yield 2; + yield 3; +}; +[...myIterable] // [1, 2, 3] +</pre> + +<h3 id="Встроенные_итерируемые_объекты">Встроенные итерируемые объекты</h3> + +<p>Объекты {{jsxref("String")}}, {{jsxref("Array")}}, {{jsxref("TypedArray")}}, {{jsxref("Map")}} и {{jsxref("Set")}} являются итерируемыми, потому что их прототипы содержат метод {{jsxref("Symbol.iterator")}}.</p> + +<h3 id="Синтаксис_для_итерируемых_объектов">Синтаксис для итерируемых объектов</h3> + +<p>Некоторые выражения работают с итерируемыми объектами, например, <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of">for-of</a></code> циклы, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator">spread operator</a>, <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/yield*">yield*</a></code>, и <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">destructuring assignment</a>.</p> + +<pre class="brush: js">for(let value of ["a", "b", "c"]){ + console.log(value) +} +// "a" +// "b" +// "c" + +[..."abc"] // ["a", "b", "c"] + +function* gen(){ + yield* ["a", "b", "c"] +} + +gen().next() // { value:"a", done:false } + +[a, b, c] = new Set(["a", "b", "c"]) +a // "a" + +</pre> + +<h2 id="Продвинутые_генераторы">Продвинутые генераторы</h2> + +<p>Генераторы вычисляют результаты своих yield выражений по требованию, что позволяет им эффективно работать с последовательностями с высокой вычислительной сложностью, или даже с бесконечными последовательностями, как продемонстрировано выше.</p> + +<p><code>Метод</code> {{jsxref("Global_Objects/Generator/next","next()")}} также принимает значение, которое может использоваться для изменения внутреннего состояния генератора. Значение, переданное в next(), будет рассматриваться как результат последнего yield выражения, которое приостановило генератор.</p> + +<p>Вот генератор чисел Фибоначи, использующий <code>next(x)</code> для перезапуска последовательности:</p> + +<pre class="brush: js">function* fibonacci(){ + var fn1 = 1; + var fn2 = 1; + while (true){ + var current = fn2; + fn2 = fn1; + fn1 = fn1 + current; + var reset = yield current; + if (reset){ + fn1 = 1; + fn2 = 1; + } + } +} + +var sequence = fibonacci(); +console.log(sequence.next().value); // 1 +console.log(sequence.next().value); // 1 +console.log(sequence.next().value); // 2 +console.log(sequence.next().value); // 3 +console.log(sequence.next().value); // 5 +console.log(sequence.next().value); // 8 +console.log(sequence.next().value); // 13 +console.log(sequence.next(true).value); // 1 +console.log(sequence.next().value); // 1 +console.log(sequence.next().value); // 2 +console.log(sequence.next().value); // 3</pre> + +<div class="note"><strong>Примечание:</strong> Интересно, что вызов <code>next(undefined)</code> равносилен вызову <code>next()</code>. При этом вызов next() для нового генератора с любым аргументом, кроме undefined, спровоцирует исключение <code>TypeError</code>.</div> + +<p>Можно заставить генератор выбросить исключение, вызвав его метод {{jsxref("Global_Objects/Generator/throw","throw()")}} и передав в качестве параметра значение исключения, которое должно быть выброшено. Это исключение будет выброшено из текущего приостановленного контекста генератора так, будто текущий приостановленный <code>yield</code> оператор являлся <code>throw</code> оператором.</p> + +<p>Если <code>yield</code> оператор не встречается во время обработки выброшенного исключения, то исключение передается выше через вызов <code>throw()</code>, и результатом последующих вызовов <code>next()</code> будет свойство <code>done</code> равное <code>true</code>.</p> + +<p>У генераторов есть метод {{jsxref("Global_Objects/Generator/return","return(value)")}}, который возвращает заданное значение и останавливает работу генератора.</p> + +<p>{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Meta_programming")}}</p> diff --git a/files/ru/web/javascript/guide/javascript_overview/index.html b/files/ru/web/javascript/guide/javascript_overview/index.html new file mode 100644 index 0000000000..ab3e38c0f6 --- /dev/null +++ b/files/ru/web/javascript/guide/javascript_overview/index.html @@ -0,0 +1,141 @@ +--- +title: Обзор JavaScript +slug: Web/JavaScript/Guide/JavaScript_Overview +translation_of: Web/JavaScript/Guide/Introduction +--- +<p>Эта глава является введением в JavaScript и описывает некоторые из базовых понятий.</p> + +<h3 id="What_is_JavaScript.3F" name="What_is_JavaScript.3F">Что такое JavaScript?</h3> + +<p>JavaScript это кросс-платформенный, объектно-ориентированный, скриптовый язык. JavaScript - это маленький и легковесный язык; он спроектирован не для создания законченных, полноценных приложений, а для легкого встраивания в другие продукты и приложения, например, в веб браузеры. Внутри основного приложения, JavaScript может соединяться с объектами этого приложения и осуществлять программный контроль над ними.</p> + +<p>Ядро JavaScript содержит набор базовых объектов, например Array, Date и Math, и набор элементов языка: операторов, управляющих структур, и выражений. Ядро JavaScript может быть расширено для различных целей с помощью дополнений, например:</p> + +<ul> + <li><em>Client-side JavaScript</em> расширяет ядро языка предоставляя объекты управления браузером (Navigator или другой веб-браузер) и его Document Object Model (DOM). Например, клиентские расширения позволяют приложению размещать элементы в HTML-форме и реагировать на пользовательские события, такие как щелчок мыши, ввод данных в форму и навигация по страницам.</li> + <li><em>Server-side JavaScript</em> расширяет ядро языка предоставляя объекты для запуска JavaScript на сервере. Например, server-side расширения позволяют приложению соединяться с реляционной базой данных, обеспечивать непрерывность информации между вызовами приложения, или выполнять операции над файлами на сервере.</li> +</ul> + +<p>Используя функции JavaScript LiveConnect, Вы можете позволить коду на Java и JavaScript общаться между собой. Вы можете создать экземпляр объекта Java из JavaScript и получить доступ к его публичным методам и свойствам. Из Java, Вы можете получить доступ к объектам, свойствам и методам JavaScript.</p> + +<p>Впервые JavaScript был использован в браузерах Netscape.</p> + +<h3 id="JavaScript_and_Java" name="JavaScript_and_Java">JavaScript и Java</h3> + +<p>JavaScript и Java схожи в некоторых отношениях, но принципиально отличаются в других. Язык JavaScript напоминает Java, но не имеет статической типизации и строгой проверки типов. В основном, JavaScript следует большей части синтакса Java в выражениях, именованиях и основного потока управления конструкциями, что стало причиной, почему он был переименован из LiveScript в JavaScript.</p> + +<p>В отличии от системы компилированных классов в Java, построенной на объявлениях, JavaScript поддерживает систему исполнения, основанную на небольшом количестве типов данных, представляющих числовые, логические и строковые значения. JavaScript обладает моделью объектов на базе прототипов вместо более общей модели объектов на базе классов. Модель объектов на базе прототипов делает возможным динамическое наследование; то есть, то, что унаследовано, может различаться для отдельных объектов. JavaScript также поддерживает функции без каких-либо специальных декларативных требований. Функции могут быть свойствами объектов, выполняться как слабо типизированные методы.</p> + +<p>По сравнению с Java, JavaScript - это язык с очень свободной формой языка. Вам не надо объявлять переменные, классы или методы. Вы не должны беспокоиться, является ли метод public, private или protected, Вам не надо реализовывать интерфейсы. Переменные, параметры и возвращаемые функциями типы не являются явно типизированными.</p> + +<p>Java - язык программирования на основе классов, предназначенный для быстрого выполнения и безопасности типов. Безопасность типов означает, например, что Вы не можете взять тип Java integer и привести его к типу object reference или получить доступ к закрытой памяти изменяя байт-код Java. Ориентированная на классы модель Java означает, что программы состоят исключительно из классов и их методов. Наследование классов и строгая типизация в Java обычно тербуют тесно связанную иерархию объектов. Эти требования делают программирование на Java более сложным чем на JavaScript.</p> + +<p>По духу JavaScript происходит от нескольких небольших, динамически типизированных языков программирования, таких как HyperTalk и dBASE. Эти скриптовые языки предлагают инструменты программирования для гораздо более широкой аудитории благодаря более простому синтаксису, специальной встроенной функциональности и минимальным требованиям для создания объектов.</p> + +<table class="standard-table"> + <caption>Таблица 1.1 Сравнение JavaScript и Java</caption> + <thead> + <tr> + <th scope="col">JavaScript</th> + <th scope="col">Java</th> + </tr> + </thead> + <tbody> + <tr> + <td>Объектно-ориентированный. Нет различий между типами объектов. Наследование реализовано через механизм прототипов, свойства и методы могут быть динамически добавлены к любому объекту.</td> + <td>На базе классов. Объекты делятся на классы и экземпляры с наследованием через иерархию классов. Классы и экземпляры не могут иметь динамически добавленные свойства и методы.</td> + </tr> + <tr> + <td>Типы данных переменных не объявлены (динамическая типизация).</td> + <td>Типы данных переменных должны быть объявлены (статическая типизация).</td> + </tr> + <tr> + <td>Не может автоматически записывать на жесткий диск.</td> + <td>Может автоматически записывать на жесткий диск.</td> + </tr> + </tbody> +</table> + +<p>Для получения дополнительной информации о различиях между JavaScript и Java, см. раздел <a href="/en/JavaScript/Guide/Details_of_the_Object_Model" title="en/JavaScript/Guide/Details of the Object Model">Details of the Object Model</a>.</p> + +<h3 id="JavaScript_and_the_ECMAScript_Specification" name="JavaScript_and_the_ECMAScript_Specification">JavaScript and the ECMAScript Specification</h3> + +<p>Netscape invented JavaScript, and JavaScript was first used in Netscape browsers. However, Netscape is working with <a class="external" href="http://www.ecma-international.org/">Ecma International</a> — the European association for standardizing information and communication systems (ECMA was formerly an acronym for the European Computer Manufacturers Association) to deliver a standardized, international programming language based on core JavaScript. This standardized version of JavaScript, called ECMAScript, behaves the same way in all applications that support the standard. Companies can use the open standard language to develop their implementation of JavaScript. The ECMAScript standard is documented in the ECMA-262 specification.</p> + +<p>The ECMA-262 standard is also approved by the <a class="external" href="http://www.iso.ch/">ISO</a> (International Organization for Standardization) as ISO-16262. You can find a <a class="external" href="http://www-archive.mozilla.org/js/language/E262-3.pdf" title="http://www-archive.mozilla.org/js/language/E262-3.pdf">PDF version of ECMA-262</a> (outdated version) at the Mozilla website. You can also find the specification on <a class="external" href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">the Ecma International website</a>. The ECMAScript specification does not describe the Document Object Model (DOM), which is standardized by the <a class="external" href="http://www.w3.org/">World Wide Web Consortium (W3C)</a>. The DOM defines the way in which HTML document objects are exposed to your script.</p> + +<h4 id="Relationship_between_JavaScript_Versions_and_ECMAScript_Editions" name="Relationship_between_JavaScript_Versions_and_ECMAScript_Editions">Relationship between JavaScript Versions and ECMAScript Editions</h4> + +<p>Netscape worked closely with Ecma International to produce the ECMAScript Specification (ECMA-262). The following table describes the relationship between JavaScript versions and ECMAScript editions.</p> + +<table class="standard-table"> + <caption>Table 1.2 JavaScript versions and ECMAScript editions</caption> + <thead> + <tr> + <th scope="row">JavaScript version</th> + <th scope="col">Relationship to ECMAScript edition</th> + </tr> + </thead> + <tbody> + <tr> + <td>JavaScript 1.1</td> + <td>ECMA-262, Edition 1 is based on JavaScript 1.1.</td> + </tr> + <tr> + <td>JavaScript 1.2</td> + <td>ECMA-262 was not complete when JavaScript 1.2 was released. JavaScript 1.2 is not fully compatible with ECMA-262, Edition 1, for the following reasons: + <ul> + <li>Netscape developed additional features in JavaScript 1.2 that were not considered for ECMA-262.</li> + <li>ECMA-262 adds two new features: internationalization using Unicode, and uniform behavior across all platforms. Several features of JavaScript 1.2, such as the <code>Date</code> object, were platform-dependent and used platform-specific behavior.</li> + </ul> + </td> + </tr> + <tr> + <td> + <p>JavaScript 1.3</p> + </td> + <td> + <p>JavaScript 1.3 is fully compatible with ECMA-262, Edition 1.</p> + + <p>JavaScript 1.3 resolved the inconsistencies that JavaScript 1.2 had with ECMA-262, while keeping all the additional features of JavaScript 1.2 except == and !=, which were changed to conform with ECMA-262.</p> + </td> + </tr> + <tr> + <td> + <p>JavaScript 1.4</p> + </td> + <td> + <p>JavaScript 1.4 is fully compatible with ECMA-262, Edition 1.</p> + + <p>The third version of the ECMAScript specification was not finalized when JavaScript 1.4 was released.</p> + </td> + </tr> + <tr> + <td>JavaScript 1.5</td> + <td>JavaScript 1.5 is fully compatible with ECMA-262, Edition 3.</td> + </tr> + </tbody> +</table> + +<div class="note"><strong>Note</strong>: ECMA-262, Edition 2 consisted of minor editorial changes and bug fixes to the Edition 1 specification. The current release by the TC39 working group of Ecma International is ECMAScript Edition 5.1</div> + +<p>The <a href="/en/JavaScript/Reference" title="en/JavaScript/Reference">JavaScript Reference</a> indicates which features of the language are ECMAScript-compliant.</p> + +<p>JavaScript will always include features that are not part of the ECMAScript Specification; JavaScript is compatible with ECMAScript, while providing additional features.</p> + +<h4 id="JavaScript_Documentation_versus_the_ECMAScript_Specification" name="JavaScript_Documentation_versus_the_ECMAScript_Specification">JavaScript Documentation versus the ECMAScript Specification</h4> + +<p>The ECMAScript specification is a set of requirements for implementing ECMAScript; it is useful if you want to determine whether a JavaScript feature is supported in other ECMAScript implementations. If you plan to write JavaScript code that uses only features supported by ECMAScript, then you may need to review the ECMAScript specification.</p> + +<p>The ECMAScript document is not intended to help script programmers; use the JavaScript documentation for information on writing scripts.</p> + +<h4 id="JavaScript_and_ECMAScript_Terminology">JavaScript and ECMAScript Terminology</h4> + +<p>The ECMAScript specification uses terminology and syntax that may be unfamiliar to a JavaScript programmer. Although the description of the language may differ in ECMAScript, the language itself remains the same. JavaScript supports all functionality outlined in the ECMAScript specification.</p> + +<p>The JavaScript documentation describes aspects of the language that are appropriate for a JavaScript programmer. For example:</p> + +<ul> + <li>The Global Object is not discussed in the JavaScript documentation because you do not use it directly. The methods and properties of the Global Object, which you do use, are discussed in the JavaScript documentation but are called top-level functions and properties.</li> + <li>The no parameter (zero-argument) constructor with the <code>Number</code> and <code>String</code> objects is not discussed in the JavaScript documentation, because what is generated is of little use. A <code>Number</code> constructor without an argument returns +0, and a <code>String</code> constructor without an argument returns "" (an empty string).</li> +</ul> diff --git a/files/ru/web/javascript/guide/keyed_collections/index.html b/files/ru/web/javascript/guide/keyed_collections/index.html new file mode 100644 index 0000000000..2b2d128801 --- /dev/null +++ b/files/ru/web/javascript/guide/keyed_collections/index.html @@ -0,0 +1,172 @@ +--- +title: Коллекции +slug: Web/JavaScript/Guide/Keyed_collections +tags: + - коллекции + - словари + - структура данных +translation_of: Web/JavaScript/Guide/Keyed_collections +--- +<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Indexed_Collections", "Web/JavaScript/Guide/Working_with_Objects")}}</div> + +<p class="summary">Этот раздел содержит обзор коллекций {{jsxref("Set")}} и словарей {{jsxref("Map")}} - встроенных {{Glossary("Data_structure","структур данных")}} с доступом по ключу.</p> + +<h2 id="Словари">Словари</h2> + +<h3 id="Тип_Map"><code>Тип Map</code> </h3> + +<p>{{jsxref("Map")}} - реализация простого ассоциативного массива (словаря). Он содержит данные в виде набора пар ключ/значение(ключи уникальны) и предоставляет методы для доступа и манипулирования этими данными. </p> + +<p>Также как и {{jsxref("Object", "объект", "", 1)}}, словарь позволяет</p> + +<ul> + <li>получать значение по ключу, а также проверять наличие ключа</li> + <li>добавлять/удалять пары ключ/значение</li> + <li>перезаписывать значение по ключу (ключи уникальны).</li> + <li>итерироваться по ключам</li> +</ul> + +<p>Словари, как специализированная структура данных, имеют существенные преимущества по сравнению с объектами<font face="Consolas, Liberation Mono, Courier, monospace">:</font></p> + +<ul> + <li>Ключи словаря могут быть любого типа (а не только строки).</li> + <li>Словарь хранит свой размер (не надо вычислять).</li> + <li>Натуральный порядок обхода элементов ( в порядке добавления) с помощью {{jsxref("Statements/for...of","for...of")}}.</li> + <li>Словарь не подмешивает ключи из прототипа (в отличие от объекта).</li> +</ul> + +<p>В следующем примере приведены основные операции со словарём:</p> + +<pre class="brush: js">var sayings = new Map(); +sayings.set("dog", "woof"); +sayings.set("cat", "meow").set("elephant", "toot"); +//вызов функции .set возвращает Map, поэтому set можно объединять в цепочки + +sayings.set("dog", "гав-гав"); // заменить значение по ключу + +sayings.size; // 3 +sayings.get("fox"); // undefined +sayings.has("bird"); // false +sayings.delete("dog"); + +for (var [key, value] of sayings) { + console.log(key + " goes " + value); +} +// "cat goes meow" +// "elephant goes toot" +</pre> + +<p>Больше примеров и полное описание на странице справочника {{jsxref("Map")}} .</p> + +<h3 id="Тип_WeakMap"><code>Тип WeakMap</code> </h3> + +<p>{{jsxref("WeakMap")}} это специальный вид словаря, <strong>ключами которого могут быть только объекты</strong>, причём ссылки на них в WeakMap являются <em>слабыми </em>(не учитываются сборщиком мусора (garbage collector GC)).</p> + +<div class="note"> +<p>Интерфейс <code>WeakMap</code> совпадает с <code>Map</code>, единственное отличие - <strong>ключи <code>WeakMap</code> нельзя итерировать</strong> (т.e. нельзя получить список ключей). Это понятно, поскольку в таком случае возникла бы неопределённость с достоверностью этого списка в зависимости от состояния garbage collection.</p> +</div> + +<p>Больше примеров, полное описание, а также обсуждение "Зачем <s>козе баян</s> <em>WeakMap</em>?" на странице справочника {{jsxref("WeakMap")}}.</p> + +<p>Отметим, что <code>WeakMap,</code> в частности, может элегантно использоваться для упаковки приватных данных или деталей реализации. Следующий пример из статьи Nick Fitzgerald <a href="http://fitzgeraldnick.com/weblog/53/">"Hiding Implementation Details with ECMAScript 6 WeakMaps"</a>. Приватная часть сохраняется как значение в <code>privates</code> и имеет время жизни такое же как и сущность класса. Сам класс и его методы публичны; прочее недоступно извне модуля:</p> + +<pre class="brush: js">const privates = new WeakMap(); + +export class Public() { + + constructor() { + const me = { + // Приватные данные идут здесь + }; + // 'me' будет освобождён вместе с 'this' !!! + privates.set(this, me); + } + + method () { + const me = privates.get(this); + // Сделайте что-нибудь с приватными данными в 'me'... + } +} +</pre> + +<h2 id="Коллекции">Коллекции</h2> + +<h3 id="Тип_Set"><code>Тип Set</code> </h3> + +<p>{{jsxref("Set")}} реализация коллекции - структура данных, которая содержит список уникальных элементов в порядке их добавления. </p> + +<p>В следующем примере приведены основные операции по работе с коллекцией <code>Set:</code></p> + +<pre class="brush: js">var mySet = new Set(); +mySet.add(1); +mySet.add("some text"); +mySet.add("foo"); + +mySet.has(1); // true +mySet.delete("foo"); +mySet.size; // 2 + +for (let item of mySet) console.log(item); +// 1 +// "some text" +</pre> + +<p>Больше примеров и полное описание на странице справочника {{jsxref("Set")}}</p> + +<h4 id="Преобразования_между_Array_и_Set">Преобразования между Array и Set</h4> + +<p>Можно создать {{jsxref("Array")}} из Set с помощью {{jsxref("Array.from")}} или используя <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator">spread operator</a>.</p> + +<p>В свою очередь, конструктор <code>Set</code> может принимать <code>Array</code> в качестве аргумента.</p> + +<div class="note"> +<p>Поскольку <code>Set</code> структура работает с уникальными значениями, любые повторяющиеся элементы из Array будут проигнорированы.</p> +</div> + +<pre class="brush: js">Array.from(mySet); +[...mySet2]; + +mySet2 = new Set([1,2,3,4]); +</pre> + +<h4 id="Сравнение_Array_и_Set"><code>Сравнение Array</code> и <code>Set</code> </h4> + +<p>Словари, как специализированная структура данных, имеют существенные отличия по сравнению с массивами:</p> + +<ul> + <li>{{jsxref("Set.has")}} работает быстрее чем {{jsxref("Array.indexOf")}}.</li> + <li><font face="Consolas, Liberation Mono, Courier, monospace">можно удалять элементы по значению (а не по индексу как массивах)</font>.</li> + <li>{{jsxref("NaN")}} обрабатывается корректно.</li> + <li><font face="Consolas, Liberation Mono, Courier, monospace">поддерживается уникальность значений</font>.</li> +</ul> + +<h3 id="Тип_WeakSet"><code>Тип WeakSet</code> </h3> + +<p>{{jsxref("WeakSet")}} это специальный вид коллекции, элементами которой могут быть только объекты. Ссылки на эти объекты в WeakSet являютя <em>слабыми </em>(не учитываются сборщиком мусора (garbage collector GC)).</p> + +<div class="note"> +<p>Элементы <code>WeakSet</code> уникальны и могут быть добавлены только один раз, также как и в {{jsxref("Set")}}. </p> +</div> + +<p>Основные отличия от {{jsxref("Set")}}:</p> + +<ul> + <li><code>WeakSet</code> это коллекция <em>объектов</em> ( примитивные значения не могут быть добавлены).</li> + <li><code>WeakSet</code> <em>нельзя итерировать</em>. А также нельзя получить список (итератор) элементов.</li> +</ul> + +<p>Использование <code>WeakSet</code> достаточно специфическое. Пользуясь тем, что они не могут создавать утечек памяти, в них можно, например, безопасно помещать ссылки на DOM элементы.</p> + +<p>Больше примеров и полное описание на странице справочника {{jsxref("WeakSet")}}</p> + +<h2 id="Проверка_на_равенство_в_Map_и_Set">Проверка на равенство в <code>Map</code> и <code>Set</code></h2> + +<p>Сравнение на равенство ключей в <code>Map</code> objects или объектов в <code>Set</code> основано на "<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero">same-value-zero algorithm</a>":</p> + +<ul> + <li>алгоритм сравнения в целом совпадает с оператором <code>===</code>.</li> + <li><code>-0</code> и <code>+0</code> считаются равными (в отличие от <code>===</code>).</li> + <li>{{jsxref("NaN")}} считается равным самому себе (в отличие от <code>===</code>).</li> +</ul> + +<p>{{PreviousNext("Web/JavaScript/Guide/Indexed_Collections", "Web/JavaScript/Guide/Working_with_Objects")}}</p> diff --git a/files/ru/web/javascript/guide/liveconnect_overview/index.html b/files/ru/web/javascript/guide/liveconnect_overview/index.html new file mode 100644 index 0000000000..baf6f2577c --- /dev/null +++ b/files/ru/web/javascript/guide/liveconnect_overview/index.html @@ -0,0 +1,795 @@ +--- +title: LiveConnect Overview +slug: Web/JavaScript/Guide/LiveConnect_Overview +translation_of: Archive/Web/LiveConnect/LiveConnect_Overview +--- +<p>Эта глава описывает технолонию <a href="/en-US/docs/LiveConnect" title="en-US/docs/LiveConnect">LiveConnect</a> которая позволяет Java и JavaScript взаимодейстовать между собой. В этой главе полагается что вы имеет представление о языке программирования Java.</p> + +<h2 id="Working_with_Wrappers">Working with Wrappers</h2> + +<p>В JavaScript, <em>обертка </em>это объект s an object of the target language data type that encloses an object of the source language. When programming in JavaScript, you can use a wrapper object to access methods and fields of the Java object; calling a method or accessing a property on the wrapper results in a call on the Java object. On the Java side, JavaScript objects are wrapped in an instance of the class <code>netscape.javascript.JSObject</code> and passed to Java.</p> + +<p>When a JavaScript object is sent to Java, the runtime engine creates a Java wrapper of type <code>JSObject</code>; when a <code>JSObject</code> is sent from Java to JavaScript, the runtime engine unwraps it to its original JavaScript object type. The <code>JSObject</code> class provides an interface for invoking JavaScript methods and examining JavaScript properties.</p> + +<h2 id="JavaScript_to_Java_Communication">JavaScript to Java Communication</h2> + +<p>When you refer to a Java package or class, or work with a Java object or array, you use one of the special LiveConnect objects. All JavaScript access to Java takes place with these objects, which are summarized in the following table.</p> + +<table class="standard-table"> + <caption>Table 9.1 The LiveConnect Objects</caption> + <thead> + <tr> + <th scope="col">Object</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>JavaArray</code></td> + <td>A wrapped Java array, accessed from within JavaScript code.</td> + </tr> + <tr> + <td><code>JavaClass</code></td> + <td>A JavaScript reference to a Java class.</td> + </tr> + <tr> + <td><code>JavaObject</code></td> + <td>A wrapped Java object, accessed from within JavaScript code.</td> + </tr> + <tr> + <td><code>JavaPackage</code></td> + <td>A JavaScript reference to a Java package.</td> + </tr> + </tbody> +</table> + +<p><strong>Note:</strong> Because Java is a strongly typed language and JavaScript is weakly typed, the JavaScript runtime engine converts argument values into the appropriate data types for the other language when you use LiveConnect. See <a href="/en-US/docs/JavaScript/Guide/Values,_Variables,_and_Literals#Data_Type_Conversion" title="en-US/docs/JavaScript/Guide/Values, Variables, and Literals#Data Type Conversion">Data Type Conversion</a> for complete information.</p> + +<p>In some ways, the existence of the LiveConnect objects is transparent, because you interact with Java in a fairly intuitive way. For example, you can create a Java <code>String</code> object and assign it to the JavaScript variable <code>myString</code> by using the <code>new</code> operator with the Java constructor, as follows:</p> + +<pre class="brush: js">var myString = new java.lang.String("Hello world"); +</pre> + +<p>In the previous example, the variable <code>myString</code> is a <code>JavaObject</code> because it holds an instance of the Java object <code>String</code>. As a <code>JavaObject</code>, <code>myString</code> has access to the public instance methods of <code>java.lang.String</code> and its superclass, <code>java.lang.Object</code>. These Java methods are available in JavaScript as methods of the <code>JavaObject</code>, and you can call them as follows:</p> + +<pre class="brush: js">myString.length(); // returns 11 +</pre> + +<p>Static members can be called directly on the JavaClass object.</p> + +<pre class="brush: js">alert(java.lang.Integer.MAX_VALUE); //alerts 2147483647 +</pre> + +<h3 id="The_Packages_Object">The Packages Object</h3> + +<p>If a Java class is not part of the <code>java</code>, <code>sun</code>, or <code>netscape</code> packages, you access it with the <code>Packages</code> object. For example, suppose the Redwood corporation uses a Java package called <code>redwood</code> to contain various Java classes that it implements. To create an instance of the <code>HelloWorld</code> class in <code>redwood</code>, you access the constructor of the class as follows:</p> + +<pre class="brush: js">var red = new Packages.redwood.HelloWorld(); +</pre> + +<p>You can also access classes in the default package (that is, classes that don't explicitly name a package). For example, if the HelloWorld class is directly in the <code>CLASSPATH</code> and not in a package, you can access it as follows:</p> + +<pre class="brush: js">var red = new Packages.HelloWorld(); +</pre> + +<p>The LiveConnect <code>java</code>, <code>sun</code>, and <code>netscape</code> objects provide shortcuts for commonly used Java packages. For example, you can use the following:</p> + +<pre class="brush: js">var myString = new java.lang.String("Hello world"); +</pre> + +<p>instead of the longer version:</p> + +<pre class="brush: js">var myString = new Packages.java.lang.String("Hello world"); +</pre> + +<h3 id="Working_with_Java_Arrays">Working with Java Arrays</h3> + +<p>When any Java method creates an array and you reference that array in JavaScript, you are working with a <code>JavaArray</code>. For example, the following code creates the <code>JavaArray x</code> with ten elements of type int:</p> + +<pre class="brush: js">var x = java.lang.reflect.Array.newInstance(java.lang.Integer, 10); +</pre> + +<p>Like the JavaScript <code>Array</code> object, <code>JavaArray</code> has a <code>length</code> property which returns the number of elements in the array. Unlike <code>Array.length</code>, <code>JavaArray.length</code> is a read-only property, because the number of elements in a Java array are fixed at the time of creation.</p> + +<h3 id="Package_and_Class_References">Package and Class References</h3> + +<p>Simple references to Java packages and classes from JavaScript create the <code>JavaPackage</code> and <code>JavaClass</code> objects. In the earlier example about the Redwood corporation, for example, the reference Packages.redwood is a JavaPackage object. Similarly, a reference such as <code>java.lang.String</code> is a <code>JavaClass</code> object.</p> + +<p>Most of the time, you don't have to worry about the <code>JavaPackage</code> and <code>JavaClass</code> objects—you just work with Java packages and classes, and LiveConnect creates these objects transparently. There are cases where LiveConnect will fail to load a class, and you will need to manually load it like this:</p> + +<pre class="brush: js">var Widgetry = java.lang.Thread.currentThread().getContextClassLoader().loadClass("org.mywidgets.Widgetry"); +</pre> + +<p>In JavaScript 1.3 and earlier, <code>JavaClass</code> objects are not automatically converted to instances of <code>java.lang.Class</code> when you pass them as parameters to Java methods—you must create a wrapper around an instance of <code>java.lang.Class</code>. In the following example, the <code>forName</code> method creates a wrapper object <code>theClass</code>, which is then passed to the <code>newInstance</code> method to create an array.</p> + +<pre class="brush: js">// JavaScript 1.3 +var theClass = java.lang.Class.forName("java.lang.String"); +var theArray = java.lang.reflect.Array.newInstance(theClass, 5); +</pre> + +<p>In JavaScript 1.4 and later, you can pass a <code>JavaClass</code> object directly to a method, as shown in the following example:</p> + +<pre class="brush: js">// JavaScript 1.4 +var theArray = java.lang.reflect.Array.newInstance(java.lang.String, 5); +</pre> + +<h3 id="Arguments_of_Type_char">Arguments of Type char</h3> + +<p>In JavaScript 1.4 and later, you can pass a one-character string to a Java method which requires an argument of type <code>char</code>. For example, you can pass the string "H" to the <code>Character</code> constructor as follows:</p> + +<pre class="brush: js">var c = new java.lang.Character("H"); +</pre> + +<p>In JavaScript 1.3 and earlier, you must pass such methods an integer which corresponds to the Unicode value of the character. For example, the following code also assigns the value "H" to the variable <code>c</code>:</p> + +<pre class="brush: js">var c = new java.lang.Character(72); +</pre> + +<h3 id="Handling_Java_Exceptions_in_JavaScript">Handling Java Exceptions in JavaScript</h3> + +<p>When Java code fails at run time, it throws an exception. If your JavaScript code accesses a Java data member or method and fails, the Java exception is passed on to JavaScript for you to handle. Beginning with JavaScript 1.4, you can catch this exception in a <code>try...catch</code> statement. (Although this functionality (along with some others) had been broken in Gecko 1.9 (see {{ bug("391642") }}) as the Mozilla-specific LiveConnect code had not been maintained inside Mozilla, with Java 6 update 11 and 12 building support for reliance on Mozilla's implementation of the generic (and cross-browser) <a href="/en-US/docs/Plugins" title="en-US/docs/Plugins">NPAPI</a> plugin code, this has again been fixed.)</p> + +<p>For example, suppose you are using the Java <code>forName</code> method to assign the name of a Java class to a variable called <code>theClass</code>. The <code>forName</code> method throws an exception if the value you pass it does not evaluate to the name of a Java class. Place the <code>forName</code> assignment statement in a <code>try</code> block to handle the exception, as follows:</p> + +<pre class="brush: js">function getClass(javaClassName) { + try { + var theClass = java.lang.Class.forName(javaClassName); + } catch (e) { + return ("The Java exception is " + e); + } + return theClass; +} +</pre> + +<p>In this example, if <code>javaClassName</code> evaluates to a legal class name, such as "java.lang.String", the assignment succeeds. If <code>javaClassName</code> evaluates to an invalid class name, such as "String", the <code>getClass</code> function catches the exception and returns something similar to the following:</p> + +<pre>The Java exception is java.lang.ClassNotFoundException: String +</pre> + +<p>For specialized handling based on the exception type, use the <code>instanceof</code> operator:</p> + +<pre class="brush: js">try { + // ... +} catch (e) { + if (e instanceof java.io.FileNotFound) { + // handling for FileNotFound + } else { + throw e; + } +} +</pre> + +<p>See <a href="/en-US/docs/JavaScript/Guide/Statements#Exception_Handling_Statements" title="en-US/docs/JavaScript/Guide/Statements#Exception Handling Statements">Exception Handling Statements</a> for more information about JavaScript exceptions.</p> + +<h2 id="Java_to_JavaScript_Communication">Java to JavaScript Communication</h2> + +<p>If you want to use JavaScript objects in Java, you must import the <code>netscape.javascript</code> package into your Java file. This package defines the following classes:</p> + +<ul> + <li><code><a href="/en-US/docs/JavaScript/Reference/LiveConnect/JSObject" title="en-US/docs/JavaScript/Reference/LiveConnect/JSObject">netscape.javascript.JSObject</a></code> allows Java code to access JavaScript methods and properties.</li> + <li><code><a href="/en-US/docs/JavaScript/Reference/LiveConnect/JSException" title="en-US/docs/JavaScript/Reference/LiveConnect/JSException">netscape.javascript.JSException</a></code> allows Java code to handle JavaScript errors.</li> +</ul> + +<p>See the <a href="/en-US/docs/JavaScript/Reference" title="en-US/docs/JavaScript/Reference">JavaScript Reference</a> for more information about these classes.</p> + +<h3 id="Locating_the_LiveConnect_classes" name="Locating_the_LiveConnect_classes">Locating the LiveConnect classes</h3> + +<p>In older versions of the Netscape browser, these classes were distributed along with the browser. Starting with JavaScript 1.2, these classes are delivered in a .jar file; in previous versions of JavaScript, these classes are delivered in a .zip file. For example, with Netscape Navigator 4 for Windows NT, the classes are delivered in the <code>java40.jar</code> file in the <code>Program\Java\Classes</code> directory beneath the Navigator directory.</p> + +<p>More recently, the classes have been distributed with Sun's Java Runtime; initially in the file "jaws.jar" in the "jre/lib" directory of the runtime distribution (for JRE 1.3), then in "plugin.jar" in the same location (JRE 1.4 and up).</p> + +<h3 id="Using_the_LiveConnect_classes_with_the_JDK" name="Using_the_LiveConnect_classes_with_the_JDK">Using the LiveConnect classes with the JDK</h3> + +<p>To access the LiveConnect classes, place the .jar or .zip file in the <code>CLASSPATH</code> of the JDK compiler in either of the following ways:</p> + +<ul> + <li>Create a <code>CLASSPATH</code> environment variable to specify the path and name of .jar or .zip file.</li> + <li>Specify the location of .jar or .zip file when you compile by using the <code>-classpath</code> command line parameter.</li> +</ul> + +<p>You can specify an environment variable in Windows NT by double-clicking the System icon in the Control Panel and creating a user environment variable called <code>CLASSPATH</code> with a value similar to the following:</p> + +<pre class="eval">C:\Program Files\Java\jre1.4.1\lib\plugin.jar +</pre> + +<p>See the Sun JDK documentation for more information about <code>CLASSPATH</code>.</p> + +<p><strong>Note:</strong> Because Java is a strongly typed language and JavaScript is weakly typed, the JavaScript runtime engine converts argument values into the appropriate data types for the other language when you use LiveConnect. See <a href="#Data_Type_Conversions">Data Type Conversions</a> for complete information.</p> + +<h3 id="Using_the_LiveConnect_Classes">Using the LiveConnect Classes</h3> + +<p>All JavaScript objects appear within Java code as instances of <code>netscape.javascript.JSObject</code>. When you call a method in your Java code, you can pass it a JavaScript object as one of its argument. To do so, you must define the corresponding formal parameter of the method to be of type <code>JSObject</code>.</p> + +<p>Also, any time you use JavaScript objects in your Java code, you should put the call to the JavaScript object inside a <code>try...catch</code> statement which handles exceptions of type <code>netscape.javascript.JSException</code>. This allows your Java code to handle errors in JavaScript code execution which appear in Java as exceptions of type <code>JSException</code>.</p> + +<h4 id="Accessing_JavaScript_with_JSObject" name="Accessing_JavaScript_with_JSObject">Accessing JavaScript with JSObject</h4> + +<p>For example, suppose you are working with the Java class called <code>JavaDog</code>. As shown in the following code, the <code>JavaDog</code> constructor takes the JavaScript object <code>jsDog</code>, which is defined as type <code>JSObject</code>, as an argument:</p> + +<pre class="brush: java">import netscape.javascript.*; + +public class JavaDog{ + public String dogBreed; + public String dogColor; + public String dogSex; + + // define the class constructor + public JavaDog(JSObject jsDog){ + // use try...catch to handle JSExceptions here + this.dogBreed = (String)jsDog.getMember("breed"); + this.dogColor = (String)jsDog.getMember("color"); + this.dogSex = (String)jsDog.getMember("sex"); + } +} +</pre> + +<p>Notice that the <code>getMember</code> method of <code>JSObject</code> is used to access the properties of the JavaScript object. The previous example uses <code>getMember</code> to assign the value of the JavaScript property <code>jsDog.breed</code> to the Java data member <code>JavaDog.dogBreed</code>.</p> + +<p><strong>Note:</strong> A more realistic example would place the call to <code>getMember</code> inside a <code>try...catch</code> statement to handle errors of type <code>JSException</code>. See Handling JavaScript Exceptions in Java for more information.</p> + +<p>To get a better sense of how <code>getMember</code> works, look at the definition of the custom JavaScript object <code>Dog</code>:</p> + +<pre class="brush: js">function Dog(breed,color,sex){ + this.breed = breed; + this.color = color; + this.sex = sex; +} +</pre> + +<p>You can create a JavaScript instance of <code>Dog</code> called <code>gabby</code> as follows:</p> + +<pre class="brush: js">var gabby = new Dog("lab", "chocolate", "female"); +</pre> + +<p>If you evaluate <code>gabby.color</code>, you can see that it has the value "chocolate". Now suppose you create an instance of <code>JavaDog</code> in your JavaScript code by passing the <code>gabby</code> object to the constructor as follows:</p> + +<pre class="brush: js">var javaDog = new Packages.JavaDog(gabby); +</pre> + +<p>If you evaluate <code>javaDog.dogColor</code>, you can see that it also has the value "chocolate", because the <code>getMember</code> method in the Java constructor assigns <code>dogColor</code> the value of <code>gabby.color</code>.</p> + +<h4 id="Handling_JavaScript_Exceptions_in_Java" name="Handling_JavaScript_Exceptions_in_Java">Handling JavaScript Exceptions in Java</h4> + +<p>When JavaScript code called from Java fails at run time, it throws an exception. If you are calling the JavaScript code from Java, you can catch this exception in a <code>try...catch</code> statement. The JavaScript exception is available to your Java code as an instance of <code>netscape.javascript.JSException</code>.</p> + +<p><code>JSException</code> is a Java wrapper around any exception type thrown by JavaScript, similar to the way that instances of <code>JSObject</code> are wrappers for JavaScript objects. Use <code>JSException</code> when you are evaluating JavaScript code in Java.</p> + +<p>When you are evaluating JavaScript code in Java, the following situations can cause run-time errors:</p> + +<ul> + <li>The JavaScript code is not evaluated, either due to a JavaScript compilation error or to some other error that occurred at run time. The JavaScript interpreter generates an error message that is converted into an instance of <code>JSException</code>.</li> + <li>Java successfully evaluates the JavaScript code, but the JavaScript code executes an unhandled <code>throw</code> statement. JavaScript throws an exception that is wrapped as an instance of <code>JSException</code>. Use the <code>getWrappedException</code> method of <code>JSException</code> to unwrap this exception in Java.</li> +</ul> + +<p>For example, suppose the Java object <code>eTest</code> evaluates the string <code>jsCode</code> that you pass to it. You can respond to either type of run-time error the evaluation causes by implementing an exception handler such as the following:</p> + +<pre class="brush: java">import netscape.javascript.JSObject; +import netscape.javascript.JSException; + +public class eTest { + public static Object doit(JSObject obj, String jsCode) { + try { + obj.eval(jsCode); + } catch (JSException e) { + if (e.getWrappedException() == null) + return e; + return e.getWrappedException(); + } + return null; + } +} +</pre> + +<p>In this example, the code in the <code>try</code> block attempts to evaluate the string <code>jsCode</code> that you pass to it. Let's say you pass the string "<code>myFunction()</code>" as the value of <code>jsCode</code>. If <code>myFunction</code> is not defined as a JavaScript function, the JavaScript interpreter cannot evaluate <code>jsCode</code>. The interpreter generates an error message, the Java handler catches the message, and the <code>doit</code> method returns an instance of <code>netscape.javascript.JSException</code>.</p> + +<p>However, suppose <code>myFunction</code> is defined in JavaScript as follows:</p> + +<pre class="brush: js">function myFunction() { + try { + if (theCondition == true) { + return "Everything's ok"; + } else { + throw "JavaScript error occurred"; + } + } catch (e) { + if (canHandle == true) { + handleIt(); + } else { + throw e; + } + } +} +</pre> + +<p>If <code>theCondition</code> is false, the function throws an exception. The exception is caught in the JavaScript code, and if <code>canHandle</code> is true, JavaScript handles it. If <code>canHandle</code> is false, the exception is rethrown, the Java handler catches it, and the <code>doit</code> method returns a Java string:</p> + +<pre>JavaScript error occurred +</pre> + +<p>See <a href="/en-US/docs/JavaScript/Guide/Statements#Exception_Handling_Statements" title="en-US/docs/JavaScript/Guide/Statements#Exception Handling Statements">Exception Handling Statements</a> for complete information about JavaScript exceptions.</p> + +<h4 id="Backward_Compatibility" name="Backward_Compatibility">Backward Compatibility</h4> + +<p>In JavaScript 1.3 and earlier versions, the <code>JSException</code> class had three public constructors which optionally took a string argument, specifying the detail message or other information for the exception. The <code>getWrappedException</code> method was not available.</p> + +<p>Use a <code>try...catch</code> statement such as the following to handle LiveConnect exceptions in JavaScript 1.3 and earlier versions:</p> + +<pre class="brush: js">try { + global.eval("foo.bar = 999;"); +} catch (Exception e) { + if (e instanceof JSException) { + jsCodeFailed(); + } else { + otherCodeFailed(); + } +} +</pre> + +<p>In this example, the <code>eval</code> statement fails if <code>foo</code> is not defined. The <code>catch</code> block executes the <code>jsCodeFailed</code> method if the <code>eval</code> statement in the <code>try</code> block throws a <code>JSException</code>; the <code>otherCodeFailed</code> method executes if the <code>try</code> block throws any other error.</p> + +<h2 id="Data_Type_Conversions">Data Type Conversions</h2> + +<p>Because Java is a strongly typed language and JavaScript is weakly typed, the JavaScript runtime engine converts argument values into the appropriate data types for the other language when you use LiveConnect. These conversions are described in the following sections:</p> + +<ul> + <li><a href="#JavaScript_to_Java_Conversions">JavaScript to Java Conversions</a></li> + <li><a href="#Java_to_JavaScript_Conversions">Java to JavaScript Conversions</a></li> +</ul> + +<h3 id="JavaScript_to_Java_Conversions">JavaScript to Java Conversions</h3> + +<p>When you call a Java method and pass it parameters from JavaScript, the data types of the parameters you pass in are converted according to the rules described in the following sections:</p> + +<ul> + <li><a href="#Number_Values">Number Values</a></li> + <li><a href="#Boolean_Values">Boolean Values</a></li> + <li><a href="#String_Values">String Values</a></li> + <li><a href="#Undefined_Values">Undefined Values</a></li> + <li><a href="#Null_Values">Null Values</a></li> + <li><a href="#JavaArray_and_JavaObject_objects">JavaArray and JavaObject objects</a></li> + <li><a href="#JavaClass_objects">JavaClass objects</a></li> + <li><a href="#Other_JavaScript_objects">Other JavaScript objects</a></li> +</ul> + +<p>The return values of methods of <code>netscape.javascript.JSObject</code> are always converted to instances of <code>java.lang.Object</code>. The rules for converting these return values are also described in these sections.</p> + +<p>For example, if <code>JSObject.eval</code> returns a JavaScript number, you can find the rules for converting this number to an instance of <code>java.lang.Object</code> in <a href="#Number_Values">Number Values</a>.</p> + +<h4 id="Number_Values" name="Number_Values">Number Values</h4> + +<p>When you pass JavaScript number types as parameters to Java methods, Java converts the values according to the rules described in the following table:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Java parameter type</th> + <th scope="col">Conversion rules</th> + </tr> + </thead> + <tbody> + <tr> + <td>double</td> + <td> + <ul> + <li>The exact value is transferred to Java without rounding and without a loss of magnitude or sign.</li> + <li><code>NaN</code> is converted to NaN.</li> + </ul> + </td> + </tr> + <tr> + <td>java.lang.Double<br> + java.lang.Object</td> + <td>A new instance of <code>java.lang.Double</code> is created, and the exact value is transferred to Java without rounding and without a loss of magnitude or sign.</td> + </tr> + <tr> + <td>float</td> + <td> + <ul> + <li>Values are rounded to float precision.</li> + <li>Values which are too large or small to be represented are rounded to +infinity or -infinity.</li> + <li><code>NaN</code> is converted to <code>NaN</code>.</li> + </ul> + </td> + </tr> + <tr> + <td>byte + <p>char<br> + int<br> + long</p> + short</td> + <td> + <ul> + <li>Values are rounded using round-to-negative-infinity mode.</li> + <li>Values which are too large or small to be represented result in a run-time error.</li> + <li><code>NaN</code> can not be converted and results in a run-time error.</li> + </ul> + </td> + </tr> + <tr> + <td><code>java.lang.String</code></td> + <td>Values are converted to strings. For example: + <ul> + <li>237 becomes "237"</li> + </ul> + </td> + </tr> + <tr> + <td>boolean</td> + <td> + <ul> + <li>0 and <code>NaN</code> values are converted to false.</li> + <li>Other values are converted to true.</li> + </ul> + </td> + </tr> + </tbody> +</table> + +<p>When a JavaScript number is passed as a parameter to a Java method which expects an instance of <code>java.lang.String</code>, the number is converted to a string. Use the <code>equals()</code> method to compare the result of this conversion with other string values.</p> + +<h4 id="Boolean_Values" name="Boolean_Values">Boolean Values</h4> + +<p>When you pass JavaScript Boolean types as parameters to Java methods, Java converts the values according to the rules described in the following table:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Java parameter type</th> + <th scope="col">Conversion rules</th> + </tr> + </thead> + <tbody> + <tr> + <td>boolean</td> + <td>All values are converted directly to the Java equivalents.</td> + </tr> + <tr> + <td><code>java.lang.Boolean</code><br> + <code>java.lang.Object</code></td> + <td>A new instance of <code>java.lang.Boolean</code> is created. Each parameter creates a new instance, not one instance with the same primitive value.</td> + </tr> + <tr> + <td><code>java.lang.String</code></td> + <td>Values are converted to strings. For example: + <ul> + <li>true becomes "true"</li> + <li>false becomes "false"</li> + </ul> + </td> + </tr> + <tr> + <td>byte + <p>char<br> + double<br> + float<br> + int<br> + long</p> + short</td> + <td> + <ul> + <li>true becomes 1</li> + <li>false becomes 0</li> + </ul> + </td> + </tr> + </tbody> +</table> + +<p>When a JavaScript Boolean is passed as a parameter to a Java method which expects an instance of <code>java.lang.String</code>, the Boolean is converted to a string. Use the == operator to compare the result of this conversion with other string values.</p> + +<h4 id="String_Values" name="String_Values">String Values</h4> + +<p>When you pass JavaScript string types as parameters to Java methods, Java converts the values according to the rules described in the following table:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Java parameter type</th> + <th scope="col">Conversion rules</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>java.lang.String</code><br> + <code>java.lang.Object</code></td> + <td>JavaScript 1.4: + <ul> + <li>A JavaScript string is converted to an instance of <code>java.lang.String</code> with a Unicode value.</li> + </ul> + + <p>JavaScript 1.3 and earlier:</p> + + <ul> + <li>A JavaScript string is converted to an instance of <code>java.lang.String</code> with an ASCII value.</li> + </ul> + </td> + </tr> + <tr> + <td>byte + <p>double<br> + float<br> + int<br> + long</p> + short</td> + <td>All values are converted to numbers as described in ECMA-262. The JavaScript string value is converted to a number according to the rules described in ECMA-262.</td> + </tr> + <tr> + <td>char</td> + <td>JavaScript 1.4: + <ul> + <li>One-character strings are converted to Unicode characters.</li> + <li>All other values are converted to numbers.</li> + </ul> + + <p>JavaScript 1.3 and earlier:</p> + + <ul> + <li>All values are converted to numbers.</li> + </ul> + </td> + </tr> + <tr> + <td>boolean</td> + <td> + <ul> + <li>The empty string becomes false.</li> + <li>All other values become true.</li> + </ul> + </td> + </tr> + </tbody> +</table> + +<h4 id="Undefined_Values" name="Undefined_Values">Undefined Values</h4> + +<p>When you pass undefined JavaScript values as parameters to Java methods, Java converts the values according to the rules described in the following table:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Java parameter type</th> + <th scope="col">Conversion rules</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>java.lang.String</code><br> + <code>java.lang.Object</code></td> + <td>The value is converted to an instance of java.lang.String whose value is the string "undefined".</td> + </tr> + <tr> + <td>boolean</td> + <td>The value becomes false.</td> + </tr> + <tr> + <td>double<br> + float</td> + <td>The value becomes <code>NaN</code>.</td> + </tr> + <tr> + <td>byte + <p>char<br> + int<br> + long</p> + short</td> + <td>The value becomes 0.</td> + </tr> + </tbody> +</table> + +<p>The undefined value conversion is possible in JavaScript 1.3 and later versions only. Earlier versions of JavaScript do not support undefined values.</p> + +<p>When a JavaScript undefined value is passed as a parameter to a Java method which expects an instance of <code>java.lang.String</code>, the undefined value is converted to a string. Use the == operator to compare the result of this conversion with other string values.</p> + +<h4 id="Null_Values" name="Null_Values">Null Values</h4> + +<p>When you pass null JavaScript values as parameters to Java methods, Java converts the values according to the rules described in the following table:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Java parameter type</th> + <th scope="col">Conversion rules</th> + </tr> + </thead> + <tbody> + <tr> + <td>Any class<br> + Any interface type</td> + <td>The value becomes null.</td> + </tr> + <tr> + <td>byte + <p>char<br> + double<br> + float<br> + int<br> + long</p> + short</td> + <td>The value becomes 0.</td> + </tr> + <tr> + <td>boolean</td> + <td>The value becomes false.</td> + </tr> + </tbody> +</table> + +<h4 id="JavaArray_and_JavaObject_objects" name="JavaArray_and_JavaObject_objects">JavaArray and JavaObject objects</h4> + +<p>In most situations, when you pass a JavaScript <code>JavaArray</code> or <code>JavaObject</code> as a parameter to a Java method, Java simply unwraps the object; in a few situations, the object is coerced into another data type according to the rules described in the following table:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Java parameter type</th> + <th scope="col">Conversion rules</th> + </tr> + </thead> + <tbody> + <tr> + <td>Any interface or class that is assignment-compatible with the unwrapped object.</td> + <td>The object is unwrapped.</td> + </tr> + <tr> + <td><code>java.lang.String</code></td> + <td>The object is unwrapped, the <code>toString</code> method of the unwrapped Java object is called, and the result is returned as a new instance of <code>java.lang.String</code>.</td> + </tr> + <tr> + <td>byte + <p>char<br> + double<br> + float<br> + int<br> + long</p> + short</td> + <td>The object is unwrapped, and either of the following situations occur: + <ul> + <li>If the unwrapped Java object has a <code>doubleValue</code> method, the <code>JavaArray</code> or <code>JavaObject</code> is converted to the value returned by this method.</li> + <li>If the unwrapped Java object does not have a <code>doubleValue</code> method, an error occurs.</li> + </ul> + </td> + </tr> + <tr> + <td>boolean</td> + <td>In JavaScript 1.3 and later versions, the object is unwrapped and either of the following situations occur: + <ul> + <li>If the object is null, it is converted to false.</li> + <li>If the object has any other value, it is converted to true.</li> + </ul> + + <p>In JavaScript 1.2 and earlier versions, the object is unwrapped and either of the following situations occur:</p> + + <ul> + <li>If the unwrapped object has a booleanValue method, the source object is converted to the return value.</li> + <li>If the object does not have a booleanValue method, the conversion fails.</li> + </ul> + </td> + </tr> + </tbody> +</table> + +<p>An interface or class is assignment-compatible with an unwrapped object if the unwrapped object is an instance of the Java parameter type. That is, the following statement must return true:</p> + +<pre class="brush: js">unwrappedObject instanceof parameterType; +</pre> + +<h4 id="JavaClass_objects" name="JavaClass_objects">JavaClass objects</h4> + +<p>When you pass a JavaScript <code>JavaClass</code> object as a parameter to a Java method, Java converts the object according to the rules described in the following table:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Java parameter type</th> + <th scope="col">Conversion rules</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>java.lang.Class</code></td> + <td>The object is unwrapped.</td> + </tr> + <tr> + <td><code>netscape.javascript.JSObject</code><br> + <code>java.lang.Object</code></td> + <td>The <code>JavaClass</code> object is wrapped in a new instance of <code>netscape.javascript.JSObject</code>.</td> + </tr> + <tr> + <td><code>java.lang.String</code></td> + <td>The object is unwrapped, the <code>toString</code> method of the unwrapped Java object is called, and the result is returned as a new instance of <code>java.lang.String</code>.</td> + </tr> + <tr> + <td>boolean</td> + <td>In JavaScript 1.3 and later versions, the object is unwrapped and either of the following situations occur: + <ul> + <li>If the object is null, it is converted to false.</li> + <li>If the object has any other value, it is converted to true.</li> + </ul> + + <p>In JavaScript 1.2 and earlier versions, the object is unwrapped and either of the following situations occur:</p> + + <ul> + <li>If the unwrapped object has a booleanValue method, the source object is converted to the return value.</li> + <li>If the object does not have a booleanValue method, the conversion fails.</li> + </ul> + </td> + </tr> + </tbody> +</table> + +<h4 id="Other_JavaScript_objects" name="Other_JavaScript_objects">Other JavaScript objects</h4> + +<p>When you pass any other JavaScript object as a parameter to a Java method, Java converts the object according to the rules described in the following table:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Java parameter type</th> + <th scope="col">Conversion rules</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>netscape.javascript.JSObject</code><br> + <code>java.lang.Object</code></td> + <td>The object is wrapped in a new instance of <code>netscape.javascript.JSObject</code>.</td> + </tr> + <tr> + <td><code>java.lang.String</code></td> + <td>The object is unwrapped, the <code>toString</code> method of the unwrapped object is called, and the result is returned as a new instance of <code>java.lang.String</code>.</td> + </tr> + <tr> + <td>byte + <p>char<br> + double<br> + float<br> + int<br> + long</p> + short</td> + <td>The object is converted to a value using the logic of the <code>ToPrimitive</code> operator described in ECMA-262. The <em>PreferredType</em> hint used with this operator is Number.</td> + </tr> + <tr> + <td>boolean</td> + <td>In JavaScript 1.3 and later versions, the object is unwrapped and either of the following situations occur: + <ul> + <li>If the object is null, it is converted to false.</li> + <li>If the object has any other value, it is converted to true.</li> + </ul> + + <p>In JavaScript 1.2 and earlier versions, the object is unwrapped and either of the following situations occur:</p> + + <ul> + <li>If the unwrapped object has a booleanValue method, the source object is converted to the return value.</li> + <li>If the object does not have a booleanValue method, the conversion fails.</li> + </ul> + </td> + </tr> + </tbody> +</table> + +<h3 id="Java_to_JavaScript_Conversions">Java to JavaScript Conversions</h3> + +<p>Values passed from Java to JavaScript are converted as follows:</p> + +<ul> + <li>Java byte, char, short, int, long, float, and double are converted to JavaScript numbers.</li> + <li>A Java boolean is converted to a JavaScript boolean.</li> + <li>An object of class <code>netscape.javascript.JSObject</code> is converted to the original JavaScript object.</li> + <li>Java arrays are converted to a JavaScript pseudo-Array object; this object behaves just like a JavaScript <code>Array</code> object: you can access it with the syntax <code>arrayName[index]</code> (where <code>index</code> is an integer), and determine its length with <code>arrayName.length</code>.</li> + <li>A Java object of any other class is converted to a JavaScript wrapper, which can be used to access methods and fields of the Java object: + <ul> + <li>Converting this wrapper to a string calls the <code>toString</code> method on the original object.</li> + <li>Converting to a number calls the <code>doubleValue</code> method, if possible, and fails otherwise.</li> + <li>Converting to a boolean in JavaScript 1.3 and later versions returns false if the object is null, and true otherwise.</li> + <li>Converting to a boolean in JavaScript 1.2 and earlier versions calls the <code>booleanValue</code> method, if possible, and fails otherwise.</li> + </ul> + </li> +</ul> + +<p>Note that instances of java.lang.Double and java.lang.Integer are converted to JavaScript objects, not to JavaScript numbers. Similarly, instances of java.lang.String are also converted to JavaScript objects, not to JavaScript strings.</p> + +<p>Java <code>String</code> objects also correspond to JavaScript wrappers. If you call a JavaScript method that requires a JavaScript string and pass it this wrapper, you'll get an error. Instead, convert the wrapper to a JavaScript string by appending the empty string to it, as shown here:</p> + +<pre class="brush: js">var JavaString = JavaObj.methodThatReturnsAString(); +var JavaScriptString = JavaString + "";</pre> diff --git a/files/ru/web/javascript/guide/meta_programming/index.html b/files/ru/web/javascript/guide/meta_programming/index.html new file mode 100644 index 0000000000..7ab4762677 --- /dev/null +++ b/files/ru/web/javascript/guide/meta_programming/index.html @@ -0,0 +1,265 @@ +--- +title: Мета-программирование +slug: Web/JavaScript/Guide/Meta_programming +tags: + - Guide + - JavaScript + - Meta + - Meta programming + - Proxy + - Reflect + - Метапрограммирование +translation_of: Web/JavaScript/Guide/Meta_programming +--- +<div>{{jsSidebar("JavaScript Guide")}} {{Previous("Web/JavaScript/Guide/Iterators_and_Generators")}}</div> + +<p class="summary">С приходом ECMAScript 2015, в JavaScript введены объекты {{jsxref("Proxy")}} и {{jsxref("Reflect")}}, позволяющие перехватить и переопределить поведение фундаментальных процессов языка (таких как поиск свойств, присвоение, итерирование, вызов функций и так далее). С помощью этих двух объектов Вы можете программировать на мета уровне JavaScript.</p> + +<h2 id="Объекты_Proxy">Объекты Proxy</h2> + +<p>Введенный в ECMAScript 6, объект {{jsxref("Proxy")}} позволяет перехватить и определить пользовательское поведение для определенных операций. Например, получение свойства объекта:</p> + +<pre class="brush: js">var handler = { + get: function(target, name) { + return name in target ? target[name] : 42; +}}; +var p = new Proxy({}, handler); +p.a = 1; +console.log(p.a, p.b); // 1, 42 +</pre> + +<p>Объект <code>Proxy</code> определяет <em>target</em> (в данном случае новый пустой объект) и <em>handler</em> - объект в котором реализована особая <em>функция-ловушка</em> <code>get</code>. "Проксированный" таким образом объект, при доступе к его несуществующему свойству вернет не <code>undefined,</code> а числовое значение 42.</p> + +<p>Дополнительные примеры доступны в справочнике {{jsxref("Proxy")}}.</p> + +<h3 id="Терминология">Терминология</h3> + +<p>В разговоре о функциях объекта <code>Proxy</code> применимы следующие термины:</p> + +<dl> + <dt>{{jsxref("Global_Objects/Proxy/handler","handler","","true")}} (обработчик)</dt> + <dd>Объект - обертка, содержащий в себе функции-ловушки.</dd> + <dt>ловушки (traps)</dt> + <dd>Методы, реализующие доступ к свойствам. В своей концепции они аналогичны методам перехвата(hooking) в операционных системах.</dd> + <dt>цель (target)</dt> + <dd>Объект, который оборачивается в Proxy. Часто используется лишь как внутреннее хранилище для Proxy объекта. Проверка на нарушение ограничений (invariants), связанных с нерасширяемостью объекта или неконфигурируемыми свойствами объекта производится для конкретной <strong>цели</strong>. </dd> + <dt>неизменяемые ограничения (дословно Invariants - те что остаются неизменными)</dt> + <dd>Некоторые особенности поведения объекта, которые должны быть сохранены при реализации пользовательского поведения названы invariants. Если в обработчике нарушены такие ограничения, будет выброшена ошибка {{jsxref("TypeError")}}.</dd> +</dl> + +<h2 id="Обработчики_и_ловушки">Обработчики и ловушки</h2> + +<p>В следующей таблице перечислены ловушки, доступные для использования в объекте <code>Proxy</code>. Смотрите подробные объяснения и примеры в <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler">документации</a>.</p> + +<table class="standard-table"> + <thead> + <tr> + <th>Обработчик / ловушка</th> + <th>Перехватываемые методы</th> + <th>Неизменяемые ограничения</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/getPrototypeOf", "handler.getPrototypeOf()")}}</td> + <td>{{jsxref("Object.getPrototypeOf()")}}<br> + {{jsxref("Reflect.getPrototypeOf()")}}<br> + {{jsxref("Object/proto", "__proto__")}}<br> + {{jsxref("Object.prototype.isPrototypeOf()")}}<br> + {{jsxref("Operators/instanceof", "instanceof")}}</td> + <td> + <ul> + <li><code>метод getPrototypeOf</code> должен вернуть object или <code>null</code>.</li> + <li>если целевой объект <code>target</code> нерасширяем, метод <code>Object.getPrototypeOf(proxy)</code> должен возвращать тот же результат что и <code>Object.getPrototypeOf(target)</code>.</li> + </ul> + </td> + </tr> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/setPrototypeOf", "handler.setPrototypeOf()")}}</td> + <td>{{jsxref("Object.setPrototypeOf()")}}<br> + {{jsxref("Reflect.setPrototypeOf()")}}</td> + <td>если целевой объект <code>target</code> нерасширяем, значение параметра <code>prototype</code> должно быть равным значению возвращаемому методом <code>Object.getPrototypeOf(target)</code>.</td> + </tr> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/isExtensible", "handler.isExtensible()")}}</td> + <td>{{jsxref("Object.isExtensible()")}}<br> + {{jsxref("Reflect.isExtensible()")}}</td> + <td><code>Object.isExtensible(proxy)</code> должно возвращать тоже значение, что и <code>Object.isExtensible(target)</code>.</td> + </tr> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/preventExtensions", "handler.preventExtensions()")}}</td> + <td>{{jsxref("Object.preventExtensions()")}}<br> + {{jsxref("Reflect.preventExtensions()")}}</td> + <td><code>Object.preventExtensions(proxy)</code> возвращает <code>true</code> только в том случае, если <code>Object.isExtensible(proxy)</code> равно <code>false</code>.</td> + </tr> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/getOwnPropertyDescriptor", "handler.getOwnPropertyDescriptor()")}}</td> + <td>{{jsxref("Object.getOwnPropertyDescriptor()")}}<br> + {{jsxref("Reflect.getOwnPropertyDescriptor()")}}</td> + <td> + <ul> + <li><code>метод getOwnPropertyDescriptor</code> должен возвращать object или <code>undefined</code>.</li> + <li>Свойство не может быть описано как несуществующее, если оно существует и является некофигурируемым, собственным свойством целевого объекта <code>target</code>.</li> + <li>Свойство не может быть описано как несуществующее, если оно существует как собственное свойство целевого объекта <code>target</code> и <code>target</code> не расширяем.</li> + <li>Свойство не может быть описано как существующее, если оно не существует как собственное свойство целевого объекта <code>target</code> и <code>target</code> не расширяем.</li> + <li>Свойство не может быть описано как неизменяемое, если оно не существует как собственное свойство целевого объекта <code>target</code> или если оно существует и является изменяемым, собственным свойством целевого объекта <code>target</code>.</li> + <li>Значение возвращенное методом <code>Object.getOwnPropertyDescriptor(target)</code> может быть применено к целевому объекту через метод <code>Object.defineProperty и э</code>то не вызовет ошибки.</li> + </ul> + </td> + </tr> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/defineProperty", "handler.defineProperty()")}}</td> + <td>{{jsxref("Object.defineProperty()")}}<br> + {{jsxref("Reflect.defineProperty()")}}</td> + <td> + <ul> + <li>Новое свойство не может быть добавлено, если целевой объект не расширяем.</li> + <li>Нельзя добавить новое конфигурируемое свойство, или преобразовать существующее свойство в конфигурируемое, если оно не существует как собственное свойство целевого объекта или не является конфигурируемым.</li> + <li>Свойство не может быть неконфигурируемым, если целевой объект имеет соответствующее собственное, конфигурируемое свойство.</li> + <li>Если объект имеет свойство соответствующее создаваемому свойству, то <code>Object.defineProperty(target, prop, descriptor)</code> не вызовет ошибки.</li> + <li>В строгом режиме ("use strict";), если обработчик <code>defineProperty</code> вернет <code>false</code>, это вызовет ошибку {{jsxref("TypeError")}}.</li> + </ul> + </td> + </tr> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/has", "handler.has()")}}</td> + <td>Property query: <code>foo in proxy</code><br> + Inherited property query: <code>foo in Object.create(proxy)</code><br> + {{jsxref("Reflect.has()")}}</td> + <td> + <ul> + <li>Свойство не может быть описано как несуществующее, если оно существует как собственное неконфигурируемое свойство целевого объекта.</li> + <li>Свойство не может быть описано как несуществующее, если оно существует как собственное свойство целевого объекта, и целевой объект является нерасширяемым.</li> + </ul> + </td> + </tr> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/get", "handler.get()")}}</td> + <td>Property access: <code>proxy[foo]</code>and <code>proxy.bar</code><br> + Inherited property access: <code>Object.create(proxy)[foo]</code><br> + {{jsxref("Reflect.get()")}}</td> + <td> + <ul> + <li>Значение, возвращаемое для свойства, должно равняться значению соответствующего свойства целевого объекта, если это свойство является доступным только для чтения, неконфигурируемым.</li> + <li>Значение, возвращаемое для свойства, должно равняться <code>undefined,</code> если соответствующее свойство целевого объекта является неконфигурируемым и обернуто в геттер и сеттер, где сеттер равен <code>undefined</code>.</li> + </ul> + </td> + </tr> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/set", "handler.set()")}}</td> + <td>Property assignment: <code>proxy[foo] = bar</code> and <code>proxy.foo = bar</code><br> + Inherited property assignment: <code>Object.create(proxy)[foo] = bar</code><br> + {{jsxref("Reflect.set()")}}</td> + <td> + <ul> + <li>Нельзя изменить значение свойства на значение, отличное от значения соответствующего свойства целевого объекта, если это свойство целевого объекта доступно только для чтения, и является неконфигурируемым.</li> + <li>Нельзя установить значение свойства, если соответствующее свойство целевого объекта является неконфигурируемым, и обернуто в геттер и сеттер, где сеттер равен <code>undefined</code>.</li> + <li>В строгом режиме, возвращение <code>false</code> из обработчика <code>set</code> вызовет ошибку {{jsxref("TypeError")}}.</li> + </ul> + </td> + </tr> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/deleteProperty", "handler.deleteProperty()")}}</td> + <td>Property deletion: <code>delete proxy[foo]</code> and <code>delete proxy.foo</code><br> + {{jsxref("Reflect.deleteProperty()")}}</td> + <td>Свойство не может быть удалено, если оно существует в целевом объекте как собственное, неконфигурируемое свойство.</td> + </tr> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/enumerate", "handler.enumerate()")}}</td> + <td>Property enumeration / for...in: <code>for (var name in proxy) {...}</code><br> + {{jsxref("Reflect.enumerate()")}}</td> + <td><code><font face="Open Sans, Arial, sans-serif">Метод </font>enumerate</code> должен возвращать объект.</td> + </tr> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/ownKeys", "handler.ownKeys()")}}</td> + <td>{{jsxref("Object.getOwnPropertyNames()")}}<br> + {{jsxref("Object.getOwnPropertySymbols()")}}<br> + {{jsxref("Object.keys()")}}<br> + {{jsxref("Reflect.ownKeys()")}}</td> + <td> + <ul> + <li>Метод <code>ownKeys</code> должен возвращать список.</li> + <li>Типом каждого элемента в возвращаемом списке должен быть {{jsxref("String")}} или {{jsxref("Symbol")}}.</li> + <li>Возвращаемый список должен содержать ключи для всех неконфигурируемых, собственных свойств целевого объекта.</li> + <li>Если целевой объект является нерасширяемым, возвращаемый список должен содержать все ключи для собственных полей целевого объекта и больше никаких других значений.</li> + </ul> + </td> + </tr> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/apply", "handler.apply()")}}</td> + <td><code>proxy(..args)</code><br> + {{jsxref("Function.prototype.apply()")}} and {{jsxref("Function.prototype.call()")}}<br> + {{jsxref("Reflect.apply()")}}</td> + <td>Ограничений нет.</td> + </tr> + <tr> + <td>{{jsxref("Global_Objects/Proxy/handler/construct", "handler.construct()")}}</td> + <td><code>new proxy(...args)</code><br> + {{jsxref("Reflect.construct()")}}</td> + <td>Обработчик должен возвращать <code>Object</code>.</td> + </tr> + </tbody> +</table> + +<h2 id="Отзываемый_Proxy">Отзываемый <code>Proxy</code></h2> + +<p>Метод {{jsxref("Proxy.revocable()")}} создает отзываемый объект <code>Proxy</code>. Такой прокси объект может быть отозван функцией <code>revoke</code>, которая отключает все ловушки-обработчики. После этого любые операции над прокси объектом вызовут ошибку {{jsxref("TypeError")}}.</p> + +<pre class="brush: js">var revocable = Proxy.revocable({}, { + get: function(target, name) { + return '[[' + name + ']]'; + } +}); +var proxy = revocable.proxy; +console.log(proxy.foo); // "[[foo]]" + +revocable.revoke(); + +console.log(proxy.foo); // ошибка TypeError +proxy.foo = 1; // снова ошибка TypeError +delete proxy.foo; // опять TypeError +typeof proxy; // "object", для метода typeof нет ловушек</pre> + +<h2 id="Рефлексия">Рефлексия</h2> + +<p>{{jsxref("Reflect")}} это встроенный объект, предоставляющий методы для перехватываемых операций JavaScript. Это те же самые методы, что имеются в {{jsxref("Global_Objects/Proxy/handler","обработчиках Proxy","","true")}}. Объект <code>Reflect</code> не является функцией.</p> + +<p><code>Reflect</code> помогает при пересылке стандартных операций из обработчика к целевому объекту.</p> + +<p>Например, метод {{jsxref("Reflect.has()")}} это тот же <a href="/ru/docs/Web/JavaScript/Reference/Operators/in"><code>оператор in</code></a> но в виде функции:</p> + +<pre class="brush: js">Reflect.has(Object, 'assign'); // true +</pre> + +<h3 id="Улучшенная_функция_apply">Улучшенная функция <code>apply</code></h3> + +<p>В ES5 обычно используется метод {{jsxref("Function.prototype.apply()")}} для вызова функции в определенном контексте (с определенным <code>this)</code> и с параметрами, заданными в виде массива (или <a href="/ru/docs/Web/JavaScript/Guide/Indexed_collections#Working_with_array-like_objects">массиво-подобного объекта</a>).</p> + +<pre class="brush: js">Function.prototype.apply.call(Math.floor, undefined, [1.75]);</pre> + +<p>С методом {{jsxref("Reflect.apply")}} эта операция менее громоздка и более понятна:</p> + +<pre class="brush: js">Reflect.apply(Math.floor, undefined, [1.75]); +// 1; + +Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111]); +// "hello" + +Reflect.apply(RegExp.prototype.exec, /ab/, ['confabulation']).index; +// 4 + +Reflect.apply(''.charAt, 'ponies', [3]); +// "i" +</pre> + +<h3 id="Проверка_успешности_определения_нового_свойства">Проверка успешности определения нового свойства</h3> + +<p>Метод {{jsxref("Object.defineProperty")}}, в случае успеха операции, возвращает объект, а при неудаче вызывает ошибку {{jsxref("TypeError")}}. Из-за этого определение свойств требует обработки блоком {{jsxref("Statements/try...catch","try...catch")}} для перехвата возможных ошибок. Метод {{jsxref("Reflect.defineProperty")}}, в свою очередь, возвращает успешность операции в виде булева значения, благодаря чему возможно использование простого {{jsxref("Statements/if...else","if...else")}} условия:</p> + +<pre class="brush: js">if (Reflect.defineProperty(target, property, attributes)) { + // успех +} else { + // что-то пошло не так +}</pre> + +<p>{{Previous("Web/JavaScript/Guide/Iterators_and_Generators")}}</p> diff --git a/files/ru/web/javascript/guide/modules/index.html b/files/ru/web/javascript/guide/modules/index.html new file mode 100644 index 0000000000..0664a4d93f --- /dev/null +++ b/files/ru/web/javascript/guide/modules/index.html @@ -0,0 +1,451 @@ +--- +title: Модули JavaScript +slug: Web/JavaScript/Guide/Modules +translation_of: Web/JavaScript/Guide/Modules +--- +<div>{{JSSidebar("JavaScript Guide")}}{{Previous("Web/JavaScript/Guide/Meta_programming")}}</div> + +<div>Это руководство содержит всю необходимую информацию для начала работы с модулями JavaScript.</div> + +<h2 id="Модули_история_вопроса">Модули: история вопроса</h2> + +<p>Сначала программы на JavaSctipt были небольшими — в прежние времена они использовались для изолированных задач, добавляя при необходимости немного интерактивности веб-страница, так что большие скрипты в основном не требовались. Прошло несколько лет, и вот уже мы видим полномасштабные приложения, работающие в броузерах и содержащие массу кода на JavaScript; кроме того, язык стал использоваться и в других контекстах (например, <a href="/en-US/docs/Glossary/Node.js">Node.js</a>).</p> + +<p>Таким образом, в последние годы появились причины на то, чтобы подумать о механизмах деления программ на JavaScript на отдельные модули, которые можно импортировать по мере нужды. Node.js включала такую возможность уже давно, кроме того, некоторые библиотеки и фреймворки JavaSctipt разрешали использование модулей (например, <a href="https://en.wikipedia.org/wiki/CommonJS">CommonJS</a> и основанные на <a href="https://github.com/amdjs/amdjs-api/blob/master/AMD.md">AMD</a> системы модулей типа <a href="https://requirejs.org/">RequireJS</a>, а позднее также <a href="https://webpack.github.io/">Webpack</a> и <a href="https://babeljs.io/">Babel</a>).</p> + +<p>К счастью, современные броузера стали сами поддерживать функциональность модулей, о чем и рассказывает эта статья. Этому можно только порадоваться — броузеры могут оптимизировать загрузку модулей, что было бы гораздо эффективнее использования библиотеки, и взять на себя обработку на стороне клиента и прочие накладные расходы.</p> + +<h2 id="Поддержка_в_броузерах">Поддержка в броузерах</h2> + +<p>Встроенная обработка модулей JavaScript свяазана с функциями {{JSxRef("Statements/import", "import")}} и {{JSxRef("Statements/export", "export")}}, которые поддерживаются броузерами следующим образом:</p> + +<h3 id="import">import</h3> + +<p>{{Compat("javascript.statements.import")}}</p> + +<h3 id="export">export</h3> + +<p>{{Compat("javascript.statements.export")}}</p> + +<h2 id="Introducing_an_example">Introducing an example</h2> + +<p>To demonstrate usage of modules, we've created a <a href="https://github.com/mdn/js-examples/tree/master/modules">simple set of examples</a> that you can find on GitHub. These examples demonstrate a simple set of modules that create a <a href="/en-US/docs/Web/HTML/Element/canvas" title="Use the HTML <canvas> element with either the canvas scripting API or the WebGL API to draw graphics and animations."><code><canvas></code></a> element on a webpage, and then draw (and report information about) different shapes on the canvas.</p> + +<p>These are fairly trivial, but have been kept deliberately simple to demonstrate modules clearly.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you want to download the examples and run them locally, you'll need to run them through a local web server.</p> +</div> + +<h2 id="Basic_example_structure">Basic example structure</h2> + +<p>In our first example (see <a href="https://github.com/mdn/js-examples/tree/master/modules/basic-modules">basic-modules</a>) we have a file structure as follows:</p> + +<pre class="notranslate">index.html +main.js +modules/ + canvas.js + square.js</pre> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: All of the examples in this guide have basically the same structure; the above should start getting pretty familiar.</p> +</div> + +<p>The modules directory's two modules are described below:</p> + +<ul> + <li><code>canvas.js</code> — contains functions related to setting up the canvas: + + <ul> + <li><code>create()</code> — creates a canvas with a specified <code>width</code> and <code>height</code> inside a wrapper <a href="/en-US/docs/Web/HTML/Element/div" title="The HTML Content Division element (<div>) is the generic container for flow content. It has no effect on the content or layout until styled using CSS."><code><div></code></a> with a specified ID, which is itself appended inside a specified parent element. Returns an object containing the canvas's 2D context and the wrapper's ID.</li> + <li><code>createReportList()</code> — creates an unordered list appended inside a specified wrapper element, which can be used to output report data into. Returns the list's ID.</li> + </ul> + </li> + <li><code>square.js</code> — contains: + <ul> + <li><code>name</code> — a constant containing the string 'square'.</li> + <li><code>draw()</code> — draws a square on a specified canvas, with a specified size, position, and color. Returns an object containing the square's size, position, and color.</li> + <li><code>reportArea()</code> — writes a square's area to a specific report list, given its length.</li> + <li><code>reportPerimeter()</code> — writes a square's perimeter to a specific report list, given its length.</li> + </ul> + </li> +</ul> + +<h2 id="Aside_—_.mjs_versus_.js">Aside — <code>.mjs</code> versus <code>.js</code></h2> + +<p>Throughout this article, we've used <code>.js</code> extensions for our module files, but in other resources you may see the <code>.mjs</code> extension used instead. <a href="https://v8.dev/features/modules#mjs">V8's documentation recommends this</a>, for example. The reasons given are:</p> + +<ul> + <li>It is good for clarity, i.e. it makes it clear which files are modules, and which are regular JavaScript.</li> + <li>It ensures that your module files are parsed as a module by runtimes such as <a href="https://nodejs.org/api/esm.html#esm_enabling">Node.js</a>, and build tools such as <a href="https://babeljs.io/docs/en/options#sourcetype">Babel</a>.</li> +</ul> + +<p>However, we decided to keep to using <code>.js</code>, at least for the moment. To get modules to work correctly in a browser, you need to make sure that your server is serving them with a <code>Content-Type</code> header that contains a JavaScript MIME type such as <code>text/javascript</code>. If you don't, you'll get a strict MIME type checking error along the lines of "The server responded with a non-JavaScript MIME type" and the browser won't run your JavaScript. Most servers already set the correct type for <code>.js</code> files, but not yet for <code>.mjs</code> files. Servers that already serve <code>.mjs</code> files correctly include <a href="https://pages.github.com/">GitHub Pages</a> and <code><a href="https://github.com/http-party/http-server#readme">http-server</a></code> for Node.js.</p> + +<p>This is OK if you are using such an environment already, or if you aren't but you know what you are doing and have access (i.e. you can configure your server to set the correct <code><a href="https://wiki.developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type">Content-Type</a></code> for <code>.mjs</code> files). It could however cause confusion if you don't control the server you are serving files from, or are publishing files for public use, as we are here.</p> + +<p>For learning and portability purposes, we decided to keep to <code>.js</code>.</p> + +<p>If you really value the clarity of using <code>.mjs</code> for modules versus using <code>.js</code> for "normal" JavaScript files, but don't want to run into the problem described above, you could always use <code>.mjs</code> during development and convert them to <code>.js</code> during your build step.</p> + +<p>It is also worth noting that:</p> + +<ul> + <li>Some tools may never support <code>.mjs</code>, such as <a href="https://www.typescriptlang.org/">TypeScript</a>.</li> + <li>The <code><script type="module"></code> attribute is used to denote when a module is being pointed to, as you'll see below.</li> +</ul> + +<h2 id="Exporting_module_features">Exporting module features</h2> + +<p>The first thing you do to get access to module features is export them. This is done using the {{JSxRef("Statements/export", "export")}} statement.</p> + +<p>The easiest way to use it is to place it in front of any items you want exported out of the module, for example:</p> + +<pre class="brush: js; notranslate">export const name = 'square'; + +export function draw(ctx, length, x, y, color) { + ctx.fillStyle = color; + ctx.fillRect(x, y, length, length); + + return { + length: length, + x: x, + y: y, + color: color + }; +}</pre> + +<p>You can export functions, <code>var</code>, <code>let</code>, <code>const</code>, and — as we'll see later — classes. They need to be top-level items; you can't use <code>export</code> inside a function, for example.</p> + +<p>A more convenient way of exporting all the items you want to export is to use a single export statement at the end of your module file, followed by a comma-separated list of the features you want to export wrapped in curly braces. For example:</p> + +<pre class="brush: js; notranslate">export { name, draw, reportArea, reportPerimeter };</pre> + +<h2 id="Importing_features_into_your_script">Importing features into your script</h2> + +<p>Once you've exported some features out of your module, you need to import them into your script to be able to use them. The simplest way to do this is as follows:</p> + +<pre class="brush: js; notranslate">import { name, draw, reportArea, reportPerimeter } from './modules/square.js';</pre> + +<p>You use the {{JSxRef("Statements/import", "import")}} statement, followed by a comma-separated list of the features you want to import wrapped in curly braces, followed by the keyword from, followed by the path to the module file — a path relative to the site root, which for our <code>basic-modules</code> example would be <code>/js-examples/modules/basic-modules</code>.</p> + +<p>However, we've written the path a bit differently — we are using the dot (<code>.</code>) syntax to mean "the current location", followed by the path beyond that to the file we are trying to find. This is much better than writing out the entire relative path each time, as it is shorter, and it makes the URL portable — the example will still work if you move it to a different location in the site hierarchy.</p> + +<p>So for example:</p> + +<pre class="notranslate">/js-examples/modules/basic-modules/modules/square.js</pre> + +<p>becomes</p> + +<pre class="notranslate">./modules/square.js</pre> + +<p>You can see such lines in action in <code><a href="https://github.com/mdn/js-examples/blob/master/modules/basic-modules/main.js">main.js</a></code>.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: In some module systems, you can omit the file extension and the leading <code>/</code>, <code>./</code>, or <code>../</code> (e.g. <code>'modules/square'</code>). This doesn't work in native JavaScript modules.</p> +</div> + +<p>Once you've imported the features into your script, you can use them just like they were defined inside the same file. The following is found in <code>main.js</code>, below the import lines:</p> + +<pre class="brush: js; notranslate">let myCanvas = create('myCanvas', document.body, 480, 320); +let reportList = createReportList(myCanvas.id); + +let square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue'); +reportArea(square1.length, reportList); +reportPerimeter(square1.length, reportList); +</pre> + +<div class="blockIndicator note"> +<p><strong>Note: </strong>Although imported features are available in the file, they are read only views of the feature that was exported. You cannot change the variable that was imported, but you can still modify properties similar to <code>const</code>. Additionally, these features are imported as live bindings, meaning that they can change in value even if you cannot modify the binding unlike <code>const</code>.</p> +</div> + +<h2 id="Applying_the_module_to_your_HTML">Applying the module to your HTML</h2> + +<p>Now we just need to apply the <code>main.js</code> module to our HTML page. This is very similar to how we apply a regular script to a page, with a few notable differences.</p> + +<p>First of all, you need to include <code>type="module"</code> in the <a href="/en-US/docs/Web/HTML/Element/script" title="The HTML <script> element is used to embed or reference executable code; this is typically used to embed or refer to JavaScript code."><code><script></code></a> element, to declare this script as a module. To import the <code>main.js</code> script, we use this:</p> + +<pre class="brush: html; no-line-numbers notranslate"><script type="module" src="main.js"></script></pre> + +<p>You can also embed the module's script directly into the HTML file by placing the JavaScript code within the body of the <code><script></code> element:</p> + +<pre class="brush: js notranslate"><script type="module"> + /* JavaScript module code here */ +</script></pre> + +<p>The script into which you import the module features basically acts as the top-level module. If you omit it, Firefox for example gives you an error of "SyntaxError: import declarations may only appear at top level of a module".</p> + +<p>You can only use <code>import</code> and <code>export</code> statements inside modules, not regular scripts.</p> + +<h2 id="Other_differences_between_modules_and_standard_scripts">Other differences between modules and standard scripts</h2> + +<ul> + <li>You need to pay attention to local testing — if you try to load the HTML file locally (i.e. with a <code>file://</code> URL), you'll run into CORS errors due to JavaScript module security requirements. You need to do your testing through a server.</li> + <li>Also, note that you might get different behavior from sections of script defined inside modules as opposed to in standard scripts. This is because modules use {{JSxRef("Strict_mode", "strict mode", "", 1)}} automatically.</li> + <li>There is no need to use the <code>defer</code> attribute (see <a href="/en-US/docs/Web/HTML/Element/script#Attributes" title="The HTML <script> element is used to embed or reference executable code; this is typically used to embed or refer to JavaScript code."><code><script></code> attributes</a>) when loading a module script; modules are deferred automatically.</li> + <li>Modules are only executed once, even if they have been referenced in multiple <code><script></code> tags.</li> + <li>Last but not least, let's make this clear — module features are imported into the scope of a single script — they aren't available in the global scope. Therefore, you will only be able to access imported features in the script they are imported into, and you won't be able to access them from the JavaScript console, for example. You'll still get syntax errors shown in the DevTools, but you'll not be able to use some of the debugging techniques you might have expected to use.</li> +</ul> + +<h2 id="Default_exports_versus_named_exports">Default exports versus named exports</h2> + +<p>The functionality we've exported so far has been comprised of <strong>named exports</strong> — each item (be it a function, <code>const</code>, etc.) has been referred to by its name upon export, and that name has been used to refer to it on import as well.</p> + +<p>There is also a type of export called the <strong>default export</strong> — this is designed to make it easy to have a default function provided by a module, and also helps JavaScript modules to interoperate with existing CommonJS and AMD module systems (as explained nicely in <a href="https://hacks.mozilla.org/2015/08/es6-in-depth-modules/">ES6 In Depth: Modules</a> by Jason Orendorff; search for "Default exports").</p> + +<p>Let's look at an example as we explain how it works. In our basic-modules <code>square.js</code> you can find a function called <code>randomSquare()</code> that creates a square with a random color, size, and position. We want to export this as our default, so at the bottom of the file we write this:</p> + +<pre class="brush: js; notranslate">export default randomSquare;</pre> + +<p>Note the lack of curly braces.</p> + +<p>We could instead prepend <code>export default</code> onto the function and define it as an anonymous function, like this:</p> + +<pre class="brush: js; notranslate">export default function(ctx) { + ... +}</pre> + +<p>Over in our <code>main.js</code> file, we import the default function using this line:</p> + +<pre class="brush: js; notranslate">import randomSquare from './modules/square.js';</pre> + +<p>Again, note the lack of curly braces. This is because there is only one default export allowed per module, and we know that <code>randomSquare</code> is it. The above line is basically shorthand for:</p> + +<pre class="brush: js; notranslate">import {default as randomSquare} from './modules/square.js';</pre> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: The as syntax for renaming exported items is explained below in the <a href="#Renaming_imports_and_exports">Renaming imports and exports</a> section.</p> +</div> + +<h2 id="Avoiding_naming_conflicts">Avoiding naming conflicts</h2> + +<p>So far, our canvas shape drawing modules seem to be working OK. But what happens if we try to add a module that deals with drawing another shape, like a circle or triangle? These shapes would probably have associated functions like <code>draw()</code>, <code>reportArea()</code>, etc. too; if we tried to import different functions of the same name into the same top-level module file, we'd end up with conflicts and errors.</p> + +<p>Fortunately there are a number of ways to get around this. We'll look at these in the following sections.</p> + +<h2 id="Renaming_imports_and_exports">Renaming imports and exports</h2> + +<p>Inside your <code>import</code> and <code>export</code> statement's curly braces, you can use the keyword <code>as</code> along with a new feature name, to change the identifying name you will use for a feature inside the top-level module.</p> + +<p>So for example, both of the following would do the same job, albeit in a slightly different way:</p> + +<pre class="brush: js; notranslate">// inside module.js +export { + function1 as newFunctionName, + function2 as anotherNewFunctionName +}; + +// inside main.js +import { newFunctionName, anotherNewFunctionName } from './modules/module.js';</pre> + +<pre class="brush: js; notranslate">// inside module.js +export { function1, function2 }; + +// inside main.js +import { function1 as newFunctionName, + function2 as anotherNewFunctionName } from './modules/module.js';</pre> + +<p>Let's look at a real example. In our <a href="https://github.com/mdn/js-examples/tree/master/modules/renaming">renaming</a> directory you'll see the same module system as in the previous example, except that we've added <code>circle.js</code> and <code>triangle.js</code> modules to draw and report on circles and triangles.</p> + +<p>Inside each of these modules, we've got features with the same names being exported, and therefore each has the same <code>export</code> statement at the bottom:</p> + +<pre class="brush: js; notranslate">export { name, draw, reportArea, reportPerimeter };</pre> + +<p>When importing these into <code>main.js</code>, if we tried to use</p> + +<pre class="brush: js; notranslate">import { name, draw, reportArea, reportPerimeter } from './modules/square.js'; +import { name, draw, reportArea, reportPerimeter } from './modules/circle.js'; +import { name, draw, reportArea, reportPerimeter } from './modules/triangle.js';</pre> + +<p>The browser would throw an error such as "SyntaxError: redeclaration of import name" (Firefox).</p> + +<p>Instead we need to rename the imports so that they are unique:</p> + +<pre class="brush: js; notranslate">import { name as squareName, + draw as drawSquare, + reportArea as reportSquareArea, + reportPerimeter as reportSquarePerimeter } from './modules/square.js'; + +import { name as circleName, + draw as drawCircle, + reportArea as reportCircleArea, + reportPerimeter as reportCirclePerimeter } from './modules/circle.js'; + +import { name as triangleName, + draw as drawTriangle, + reportArea as reportTriangleArea, + reportPerimeter as reportTrianglePerimeter } from './modules/triangle.js';</pre> + +<p>Note that you could solve the problem in the module files instead, e.g.</p> + +<pre class="brush: js; notranslate">// in square.js +export { name as squareName, + draw as drawSquare, + reportArea as reportSquareArea, + reportPerimeter as reportSquarePerimeter };</pre> + +<pre class="brush: js; notranslate">// in main.js +import { squareName, drawSquare, reportSquareArea, reportSquarePerimeter } from './modules/square.js';</pre> + +<p>And it would work just the same. What style you use is up to you, however it arguably makes more sense to leave your module code alone, and make the changes in the imports. This especially makes sense when you are importing from third party modules that you don't have any control over.</p> + +<h2 id="Creating_a_module_object">Creating a module object</h2> + +<p>The above method works OK, but it's a little messy and longwinded. An even better solution is to import each module's features inside a module object. The following syntax form does that:</p> + +<pre class="brush: js; notranslate">import * as Module from './modules/module.js';</pre> + +<p>This grabs all the exports available inside <code>module.js</code>, and makes them available as members of an object <code>Module</code>, effectively giving it its own namespace. So for example:</p> + +<pre class="brush: js; notranslate">Module.function1() +Module.function2() +etc.</pre> + +<p>Again, let's look at a real example. If you go to our <a href="https://github.com/mdn/js-examples/tree/master/modules/module-objects">module-objects</a> directory, you'll see the same example again, but rewritten to take advantage of this new syntax. In the modules, the exports are all in the following simple form:</p> + +<pre class="brush: js; notranslate">export { name, draw, reportArea, reportPerimeter };</pre> + +<p>The imports on the other hand look like this:</p> + +<pre class="brush: js; notranslate">import * as Canvas from './modules/canvas.js'; + +import * as Square from './modules/square.js'; +import * as Circle from './modules/circle.js'; +import * as Triangle from './modules/triangle.js';</pre> + +<p>In each case, you can now access the module's imports underneath the specified object name, for example:</p> + +<pre class="brush: js; notranslate">let square1 = Square.draw(myCanvas.ctx, 50, 50, 100, 'blue'); +Square.reportArea(square1.length, reportList); +Square.reportPerimeter(square1.length, reportList);</pre> + +<p>So you can now write the code just the same as before (as long as you include the object names where needed), and the imports are much neater.</p> + +<h2 id="Modules_and_classes">Modules and classes</h2> + +<p>As we hinted at earlier, you can also export and import classes; this is another option for avoiding conflicts in your code, and is especially useful if you've already got your module code written in an object-oriented style.</p> + +<p>You can see an example of our shape drawing module rewritten with ES classes in our <a href="https://github.com/mdn/js-examples/tree/master/modules/classes">classes</a> directory. As an example, the <code><a href="https://github.com/mdn/js-examples/blob/master/modules/classes/modules/square.js">square.js</a></code> file now contains all its functionality in a single class:</p> + +<pre class="brush: js; notranslate">class Square { + constructor(ctx, listId, length, x, y, color) { + ... + } + + draw() { + ... + } + + ... +}</pre> + +<p>which we then export:</p> + +<pre class="brush: js; notranslate">export { Square };</pre> + +<p>Over in <code><a href="https://github.com/mdn/js-examples/blob/master/modules/classes/main.js">main.js</a></code>, we import it like this:</p> + +<pre class="brush: js; notranslate">import { Square } from './modules/square.js';</pre> + +<p>And then use the class to draw our square:</p> + +<pre class="brush: js; notranslate">let square1 = new Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, 'blue'); +square1.draw(); +square1.reportArea(); +square1.reportPerimeter();</pre> + +<h2 id="Aggregating_modules">Aggregating modules</h2> + +<p>There will be times where you'll want to aggregate modules together. You might have multiple levels of dependencies, where you want to simplify things, combining several submodules into one parent module. This is possible using export syntax of the following forms in the parent module:</p> + +<pre class="brush: js; notranslate">export * from 'x.js' +export { name } from 'x.js'</pre> + +<p>For an example, see our <a href="https://github.com/mdn/js-examples/tree/master/modules/module-aggregation">module-aggregation</a> directory. In this example (based on our earlier classes example) we've got an extra module called <code>shapes.js</code>, which aggregates all the functionality from <code>circle.js</code>, <code>square.js</code>, and <code>triangle.js</code> together. We've also moved our submodules inside a subdirectory inside the <code>modules</code> directory called <code>shapes</code>. So the module structure in this example is:</p> + +<pre class="notranslate">modules/ + canvas.js + shapes.js + shapes/ + circle.js + square.js + triangle.js</pre> + +<p>In each of the submodules, the export is of the same form, e.g.</p> + +<pre class="brush: js; notranslate">export { Square };</pre> + +<p>Next up comes the aggregation part. Inside <code><a href="https://github.com/mdn/js-examples/blob/master/modules/module-aggregation/modules/shapes.js">shapes.js</a></code>, we include the following lines:</p> + +<pre class="brush: js; notranslate">export { Square } from './shapes/square.js'; +export { Triangle } from './shapes/triangle.js'; +export { Circle } from './shapes/circle.js';</pre> + +<p>These grab the exports from the individual submodules and effectively make them available from the <code>shapes.js</code> module.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: The exports referenced in <code>shapes.js</code> basically get redirected through the file and don't really exist there, so you won't be able to write any useful related code inside the same file.</p> +</div> + +<p>So now in the <code>main.js</code> file, we can get access to all three module classes by replacing</p> + +<pre class="brush: js; notranslate">import { Square } from './modules/square.js'; +import { Circle } from './modules/circle.js'; +import { Triangle } from './modules/triangle.js';</pre> + +<p>with the following single line:</p> + +<pre class="brush: js; notranslate">import { Square, Circle, Triangle } from './modules/shapes.js';</pre> + +<h2 id="Dynamic_module_loading">Dynamic module loading</h2> + +<p>The newest part of the JavaScript modules functionality to be available in browsers is dynamic module loading. This allows you to dynamically load modules only when they are needed, rather than having to load everything up front. This has some obvious performance advantages; let's read on and see how it works.</p> + +<p>This new functionality allows you to call {{JSxRef("Statements/import", "import()", "#Dynamic_Imports")}} as a function, passing it the path to the module as a parameter. It returns a {{JSxRef("Promise")}}, which fulfills with a module object (see <a href="#Creating_a_module_object">Creating a module object</a>) giving you access to that object's exports, e.g.</p> + +<pre class="brush: js; notranslate">import('./modules/myModule.js') + .then((module) => { + // Do something with the module. + });</pre> + +<p>Let's look at an example. In the <a href="https://github.com/mdn/js-examples/tree/master/modules/dynamic-module-imports">dynamic-module-imports</a> directory we've got another example based on our classes example. This time however we are not drawing anything on the canvas when the example loads. Instead, we include three buttons — "Circle", "Square", and "Triangle" — that, when pressed, dynamically load the required module and then use it to draw the associated shape.</p> + +<p>In this example we've only made changes to our <code><a href="https://github.com/mdn/js-examples/blob/master/modules/dynamic-module-imports/index.html">index.html</a></code> and <code><a href="https://github.com/mdn/js-examples/blob/master/modules/dynamic-module-imports/main.mjs">main.js</a></code> files — the module exports remain the same as before.</p> + +<p>Over in <code>main.js</code> we've grabbed a reference to each button using a <a href="/en-US/docs/Web/API/Document/querySelector"><code>Document.querySelector()</code></a> call, for example:</p> + +<pre class="brush: js; notranslate">let squareBtn = document.querySelector('.square');</pre> + +<p>We then attach an event listener to each button so that when pressed, the relevant module is dynamically loaded and used to draw the shape:</p> + +<pre class="brush: js; notranslate">squareBtn.addEventListener('click', () => { + import('./modules/square.js').then((Module) => { + let square1 = new Module.Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, 'blue'); + square1.draw(); + square1.reportArea(); + square1.reportPerimeter(); + }) +});</pre> + +<p>Note that, because the promise fulfillment returns a module object, the class is then made a subfeature of the object, hence we now need to access the constructor with <code>Module.</code> prepended to it, e.g. <code>Module.Square( ... )</code>.</p> + +<h2 id="Troubleshooting">Troubleshooting</h2> + +<p>Here are a few tips that may help you if you are having trouble getting your modules to work. Feel free to add to the list if you discover more!</p> + +<ul> + <li>We mentioned this before, but to reiterate: <code>.js</code> files need to be loaded with a MIME-type of <code>text/javascript</code> (or another JavaScript-compatible MIME-type, but <code>text/javascript</code> is recommended), otherwise you'll get a strict MIME type checking error like "The server responded with a non-JavaScript MIME type".</li> + <li>If you try to load the HTML file locally (i.e. with a <code>file://</code> URL), you'll run into CORS errors due to JavaScript module security requirements. You need to do your testing through a server. GitHub pages is ideal as it also serves <code>.js</code> files with the correct MIME type.</li> + <li>Because <code>.mjs</code> is a non-standard file extension, some operating systems might not recognise it, or try to replace it with something else. For example, we found that macOS was silently adding on <code>.js</code> to the end of <code>.mjs</code> files and then automatically hiding the file extension. So all of our files were actually coming out as <code>x.mjs.js</code>. Once we turned off automatically hiding file extensions, and trained it to accept <code>.mjs</code>, it was OK.</li> +</ul> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="https://developers.google.com/web/fundamentals/primers/modules#mjs">Using JavaScript modules on the web</a>, by Addy Osmani and Mathias Bynens</li> + <li><a href="https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/">ES modules: A cartoon deep-dive</a>, Hacks blog post by Lin Clark</li> + <li><a href="https://hacks.mozilla.org/2015/08/es6-in-depth-modules/">ES6 in Depth: Modules</a>, Hacks blog post by Jason Orendorff</li> + <li>Axel Rauschmayer's book <a href="http://exploringjs.com/es6/ch_modules.html">Exploring JS: Modules</a></li> +</ul> + +<p>{{Previous("Web/JavaScript/Guide/Meta_programming")}}</p> diff --git a/files/ru/web/javascript/guide/numbers_and_dates/index.html b/files/ru/web/javascript/guide/numbers_and_dates/index.html new file mode 100644 index 0000000000..7022834e0d --- /dev/null +++ b/files/ru/web/javascript/guide/numbers_and_dates/index.html @@ -0,0 +1,378 @@ +--- +title: Числа и даты +slug: Web/JavaScript/Guide/Numbers_and_dates +translation_of: Web/JavaScript/Guide/Numbers_and_dates +--- +<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Expressions_and_Operators", "Web/JavaScript/Guide/Text_formatting")}}</div> + +<p class="summary">Данный раздел представляет собой введение в работу с числами и датами в JavaScript.</p> + +<h2 id="Числа">Числа</h2> + +<p>В JavaScript все числа являются <a class="external external-icon" href="https://en.wikipedia.org/wiki/Double-precision_floating-point_format">числами двойной точности в соответствии с 64-битным двоичным форматом IEEE 754</a> (т.е. числами, пренадлежащими диапазону между -(2<sup>53</sup> -1) и 2<sup>53</sup> -1). <strong>Целые числа не рассматриваются как отдельный тип чисел</strong>. В дополнение к числам с плавающей запятой, к числовому типу данных относятся также три символьные величины: <code>+</code>{{jsxref("бесконечность")}}, <code>-</code>{{jsxref("бесконечность")}}, и {{jsxref("NaN")}} (не-число). В разделе <a href="/en-US/docs/Web/JavaScript/Data_structures">типы и структуры данных в JavaScript</a> числовой тип данных описан в контексте с другими примитивными типами в JavaScript.</p> + +<p>Вы можете использовать четыре типа числовых литералов: десятичный, двоичный, восьмеричный и шестнадцатеричный.</p> + +<h3 id="Десятичные_числа">Десятичные числа</h3> + +<pre class="brush: js">1234567890 +42 + +// Будьте внимательны при использование нулей в начале чисел: + +0888 // 888 обрабатывается как десятичное +0777 // обрабатывается как восьмеричное в нестрогой форме (511 в десятичной) +</pre> + +<p>Обратите внимание, что десятичные литералы могут начинаться с нуля (<code>0</code>) за которым следует другая десятичная цифра, но если следующая за нулем цифра меньше 8, то число обрабатывается как восьмеричное.</p> + +<h3 id="Двоичные_числа">Двоичные числа</h3> + +<p>Систаксис двоичных чисел использует ведущий 0 за которым следует латинская буква "B" в верхнем или нижнем регистре (<code>0b</code> or <code>0B</code>). Если цифры после <code>0b</code> не являются 0 или 1, то будет сгенерированно <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError">SyntaxError</a></code> с сообщением: "Missing binary digits after 0b".</p> + +<pre class="brush: js">var FLT_SIGNBIT = 0b10000000000000000000000000000000; // 2147483648 +var FLT_EXPONENT = 0b01111111100000000000000000000000; // 2139095040 +var FLT_MANTISSA = 0B00000000011111111111111111111111; // 8388607</pre> + +<h3 id="Восьмеричные_числа">Восьмеричные числа</h3> + +<p>Синтаксис восмеричных чисел использует ноль в начале. Если цифры после 0 не входят в диапазон от 0 до 7, число будет интерпретированно как десятичное.</p> + +<pre class="brush: js">var n = 0755; // 493 +var m = 0644; // 420 +</pre> + +<h3 id="Шестнадцатеричные_числа">Шестнадцатеричные числа</h3> + +<p>Синтаксис шестнадцатеричных чисел исользует ведущий 0 за которым следует латинская буква "X" в верхнем или нижнем регистре (<code>0x</code> or <code>0X</code>). Если цифры после 0x не входят в диапазон (0123456789ABCDEF), то будет сгенерированно <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError">SyntaxError</a></code> с сообщением: "Identifier starts immediately after numeric literal".</p> + +<pre class="brush: js">0xFFFFFFFFFFFFFFFFF // 295147905179352830000 +0x123456789ABCDEF // 81985529216486900 +0XA // 10 +</pre> + +<h2 id="Объект_Number">Объект Number</h2> + +<p>У этого встроенного объекта {{jsxref("Number")}} есть свойства для целочисленных констант, таких как максимальное число, не-число и бесконечность. Вы не можете изменить значения этих свойств, и Вы должны использовать их следующим образом:</p> + +<pre class="brush: js">var biggestNum = Number.MAX_VALUE; +var smallestNum = Number.MIN_VALUE; +var infiniteNum = Number.POSITIVE_INFINITY; +var negInfiniteNum = Number.NEGATIVE_INFINITY; +var notANum = Number.NaN; +</pre> + +<p>Как видно из примера выше, для получения перечисленных значений, нужно обращаться к свойствам предопределенного глобального объекта <code>Number</code>. Тогда как у экземпляра этого объекта, созданного вами при работе программы, этих свойств не будет. </p> + +<p>В следующей таблице приведен список свойств объекта <code>Number</code>.</p> + +<table class="standard-table"> + <caption>Свойства объекта <code>Number</code></caption> + <thead> + <tr> + <th scope="col">Свойство</th> + <th scope="col">Описание</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{jsxref("Number.MAX_VALUE")}}</td> + <td>Наибольшее число из возможных для представления</td> + </tr> + <tr> + <td>{{jsxref("Number.MIN_VALUE")}}</td> + <td>Наименьшее число из возможных для представления</td> + </tr> + <tr> + <td>{{jsxref("Number.NaN")}}</td> + <td>Специальное "Не числовое" ("not a number") значение</td> + </tr> + <tr> + <td>{{jsxref("Number.NEGATIVE_INFINITY")}}</td> + <td>Специальное значение "Минус бесконечность"; возвращается при переполнении</td> + </tr> + <tr> + <td>{{jsxref("Number.POSITIVE_INFINITY")}}</td> + <td>Специальное значение "Плюс бесконечность"; возвращается при переполнении</td> + </tr> + <tr> + <td>{{jsxref("Number.EPSILON")}}</td> + <td>Разница между единицей и наименьшим значением, большим единицы, которое может быть представлено типом {{jsxref("Number")}}.</td> + </tr> + <tr> + <td>{{jsxref("Number.MIN_SAFE_INTEGER")}}</td> + <td>Минимальное целое, безопасное число в JavaScript.</td> + </tr> + <tr> + <td>{{jsxref("Number.MAX_SAFE_INTEGER")}}</td> + <td>Максимальное целое, безопасное число в JavaScript.</td> + </tr> + </tbody> +</table> + +<table class="standard-table"> + <caption>Методы объекта <code>Number</code></caption> + <thead> + <tr> + <th>Метод</th> + <th>Описание</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{jsxref("Number.parseFloat()")}}</td> + <td>Принимает строку как аргумент, и возвращает числовое значение с плавающей точкой, которое удалось распознать.<br> + Тоже самое что и глобальная функция {{jsxref("parseFloat", "parseFloat()")}}.</td> + </tr> + <tr> + <td>{{jsxref("Number.parseInt()")}}</td> + <td>Принимает строку как аргумент, и возвращает целочисленное значение в заданной системе исчисления, которое удалось распознать.<br> + Тоже самое что и глобальная функция {{jsxref("parseInt", "parseInt()")}}.</td> + </tr> + <tr> + <td>{{jsxref("Number.isFinite()")}}</td> + <td>Определяет, является ли число, переданное в качестве аргумента, конечным.</td> + </tr> + <tr> + <td>{{jsxref("Number.isInteger()")}}</td> + <td>Определяет, является ли число, переданное в качестве аргумента, целым.</td> + </tr> + <tr> + <td>{{jsxref("Number.isNaN()")}}</td> + <td>Определяет, является ли число, переданное в качестве аргумента, {{jsxref("Global_Objects/NaN", "NaN")}} (не числом). Аналогичный, но более надежный метод чем глобальная функция {{jsxref("Global_Objects/isNaN", "isNaN()")}}.</td> + </tr> + <tr> + <td>{{jsxref("Number.isSafeInteger()")}}</td> + <td>Определяет, является ли .число, переданное в качестве аргумента, целым и безопасным.</td> + </tr> + </tbody> +</table> + +<p><code><font face="Open Sans, Arial, sans-serif">Прототип </font>Number</code> предоставляет ряд методов, для получения значения числа в различных форматах. В следующей таблице перечислены методы, доступные через <code>Number.prototype</code>.</p> + +<table class="standard-table"> + <caption>Методы <code>Number.prototype</code></caption> + <thead> + <tr> + <th scope="col">Метод</th> + <th scope="col">Описание</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{jsxref("Number.toExponential", "toExponential()")}}</td> + <td>Возвращает строку, представляющую число в экспоненциальном представлении.</td> + </tr> + <tr> + <td>{{jsxref("Number.toFixed", "toFixed()")}}</td> + <td>Возвращает строку, представляющую число с заданным количеством разрядов после запятой.</td> + </tr> + <tr> + <td>{{jsxref("Number.toPrecision", "toPrecision()")}}</td> + <td>Возвращает строку, представляющую число с указанной точностью.</td> + </tr> + </tbody> +</table> + +<h2 id="Объект_Math"><code>Объект Math</code></h2> + +<p>Встроенный глобальный объект {{jsxref("Math")}} содержит свойства и методы для математических констант и функций. Например, свойство объекта <code>Math </code><code>PI</code> содержит значение математической константы "Пи" (3.141...), которые вы можете использовать в программе как</p> + +<pre class="brush: js">Math.PI +</pre> + +<p>Подобным образом, математические функции являются методами объекта <code>Math</code>. Они включают тригонометрические, логорифмические, экспоненциальные и другие функции. Например, если вы хотите использовать тригонометрическую функцию синуса, вы напишете следующий код</p> + +<pre class="brush: js">Math.sin(1.56) +</pre> + +<p>Заметьте, что все тригонометрические методы объекта <code>Math</code> принимают аргументы в радианах.</p> + +<p>В следующей таблице перечислены методы объекта <code>Math</code>.</p> + +<table class="standard-table"> + <caption>Методы объекта <code>Math</code></caption> + <thead> + <tr> + <th scope="col">Метод</th> + <th scope="col">Описание</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{jsxref("Math.abs", "abs()")}}</td> + <td>Возвращает абсолютное значение (модуль) аргумента</td> + </tr> + <tr> + <td>{{jsxref("Math.sin", "sin()")}}, {{jsxref("Math.cos", "cos()")}}, {{jsxref("Math.tan", "tan()")}}</td> + <td>Стандартные тригонометрические функции; принимают аргументы в радианах</td> + </tr> + <tr> + <td>{{jsxref("Math.asin", "asin()")}}, {{jsxref("Math.acos", "acos()")}}, {{jsxref("Math.atan", "atan()")}}, {{jsxref("Math.atan2", "atan2()")}}</td> + <td>Обратные тригонометрические функции; возвращают значения в радианах</td> + </tr> + <tr> + <td>{{jsxref("Math.sinh", "sinh()")}}, {{jsxref("Math.cosh", "cosh()")}}, {{jsxref("Math.tanh", "tanh()")}}</td> + <td>Гиперболические тригонометрические функции; принимают аргументы в гиперболических углах</td> + </tr> + <tr> + <td>{{jsxref("Math.asinh", "asinh()")}}, {{jsxref("Math.acosh", "acosh()")}}, {{jsxref("Math.atanh", "atanh()")}}</td> + <td>Обратные гиперболические тригонометрические функции; возвращают значения в гиперболических углах</td> + </tr> + <tr> + <td> + <p>{{jsxref("Math.pow", "pow()")}}, {{jsxref("Math.exp", "exp()")}}, {{jsxref("Math.expm1", "expm1()")}}, {{jsxref("Math.log10", "log10()")}}, {{jsxref("Math.log1p", "log1p()")}}, {{jsxref("Math.log2", "log2()")}}</p> + </td> + <td>Экпоненциальные и логорифмические функции</td> + </tr> + <tr> + <td>{{jsxref("Math.floor", "floor()")}}, {{jsxref("Math.ceil", "ceil()")}}</td> + <td>Возвращают наибольшее/наименьшее целое, которое меньше/больше или равно входному значению</td> + </tr> + <tr> + <td>{{jsxref("Math.min", "min()")}}, {{jsxref("Math.max", "max()")}}</td> + <td>Возвращают наибольшее или наименьшее (соответственно) из входных числовых значений, перечисленных через запятую</td> + </tr> + <tr> + <td>{{jsxref("Math.random", "random()")}}</td> + <td>Возвращает случайное число от 0 до 1</td> + </tr> + <tr> + <td>{{jsxref("Math.round", "round()")}}, {{jsxref("Math.fround", "fround()")}}, {{jsxref("Math.trunc", "trunc()")}},</td> + <td>Функции округления и отсечения дробной части</td> + </tr> + <tr> + <td>{{jsxref("Math.sqrt", "sqrt()")}}, {{jsxref("Math.cbrt", "cbrt()")}}, {{jsxref("Math.hypot", "hypot()")}}</td> + <td>Корень квадратный, корень кубический, корень квадратный из суммы квадратов аргументов</td> + </tr> + <tr> + <td>{{jsxref("Math.sign", "sign()")}}</td> + <td>Знак числа, показывает является ли входное число позитивным, негативным или равным нулю</td> + </tr> + <tr> + <td>{{jsxref("Math.clz32", "clz32()")}},<br> + {{jsxref("Math.imul", "imul()")}}</td> + <td>Количество первых нулевых бит в 32-битном двоичном представлении.<br> + Возвращает результат Cи-подобного 32-битного целочисленного умножения двух аргументов.</td> + </tr> + </tbody> +</table> + +<p>В отличии от большинства других объектов, вам не нужно создавать свои экземпляры объекта <code>Math</code>. Всегда следует использовать глобальный объект <code>Math</code> непосредственно.</p> + +<h2 id="Объект_Date"><code>Объект Date</code></h2> + +<p>JavaScript не имеет отдельного типа данных для хранения дат. Однако, вы можете использовать объект {{jsxref("Date")}} и его методы для работы с датами и времененем в вашем приложении. Объект <code>Date</code> имеет большое количество методов для записи, чтения и оперирования датой и временем, а свойств не имеет ни одного.</p> + +<p>JavaScript оперирует датами во многом аналогично языку Java. Для работы с датой эти два языка имеют множество одинаковых методов, и оба они хранят даты как количество миллисекунд, прошедших с 00:00:00 1 Января 1970 года.</p> + +<p>Период значений, которые может принимать Data, простирается от -100 000 000 до100 000 000 дней, относительно 1 Января 1970 года.</p> + +<p>Чтобы создать свой экземпляр объекта <code>Date используйте такой код</code>:</p> + +<pre class="brush: js">var dateObjectName = new Date([parameters]); +</pre> + +<p>где <code>dateObjectName</code> это имя переменной, которой будет присвоено созданное значение с типом <code>Date</code>; вместо этой переменной, присвоить созданное значение можно как свойство, любому существующему объекту.</p> + +<p>Вызов <code>Date</code> как функции, без ключевого слова <code>new,</code> возвращает текущую дату и время в виде текстовой строки.</p> + +<p>Содержимым блока <code>parameters</code> в коде представленном выше, могут выступать любая из следующих конструкций:</p> + +<ul> + <li>Пусто: создает текущую дату и время. Пример: <code>today = new Date();</code>.</li> + <li>Текстовая строка, содержащая дату и время в следующем формате: "Месяц день, год часы:минуты:секунды". Например: <code>var Xmas95 = new Date("December 25, 1995 13:30:00")</code>. Если не указать секунды, минуты или часы, то их значение будет принято за 0.</li> + <li>Набор целочисленных значений для года, месяца и дня. Например: <code>var Xmas95 = new Date(1995, 11, 25)</code>.</li> + <li>Набор целочисленных значений для года, месяца, дня, часов, минут и секунд. Например: <code>var Xmas95 = new Date(1995, 11, 25, 9, 30, 0);</code>.</li> +</ul> + +<h3 id="Получение_даты_в_русскоязычном_формате">Получение даты в русскоязычном формате</h3> + +<pre>new Date().toLocaleString('ru', + { + day: 'numeric', + month: 'long', + year: 'numeric' + }); +// текущая дата в формате: '10 января 2019 г.' +</pre> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString">Подробнее про метод toLocalString</a></p> + +<h3 id="Методы_объекта_Date">Методы объекта <code>Date</code></h3> + +<p>Методы объекта <code>Date</code> для работы с датой и временем делятся на следующие категории:</p> + +<ul> + <li>"set" методы, служат для установки параметров объекта <code>Date</code>.</li> + <li>"get" методы, служат для получения параметров объекта <code>Date</code>.</li> + <li>"to" методы, служат для получения значения объекта <code>Date</code> в текстовом виде.</li> + <li>"parse" и UTC методы, служат для распознавания дат и времени <font face="Consolas, Liberation Mono, Courier, monospace">из тектового формата</font>.</li> +</ul> + +<p>При помощи методов групп "get" и"set", вы можете получить и установить значения секунд, минут, часов, дня месяца, дня недели, месяца и года по отдельности. Отдельно выделим метод <code>getDay</code>, который возвращает день недели, однако соответствующего ему метода <code>setDay</code> не существует, потому-что день недели высчитывается автоматически. Все эти методы используют в своей работе целочисленные значения по следующим правилам:</p> + +<ul> + <li>Секунды и минуты: от 0 до 59</li> + <li>Часы: от 0 до 23</li> + <li>Дни недели: от 0 (Воскресенье) до 6 (Суббота)</li> + <li>Дни месяца: от 1 до 31</li> + <li>Месяцы: от 0 (Январь) до 11 (Декабрь)</li> + <li>Год: год относительно 1900 года.</li> +</ul> + +<p>Например, предположим, что вы определили дату следующим образом:</p> + +<pre class="brush: js">var Xmas95 = new Date("December 25, 1995"); +</pre> + +<p>Тогда <code>Xmas95.getMonth()</code> вернет 11, а <code>Xmas95.getFullYear()</code> вернет 1995.</p> + +<p>Методы <code>getTime</code> и <code>setTime могут быть</code> полезны при сравнении дат. Метод <code>getTime</code> возвращает количество миллисекунд, прошедших с 00:00:00 1 Января, 1970 года.</p> + +<p>Для примера рассмотрим следующий код, показывающий количество дней оставшихся до конца текущего года:</p> + +<pre class="brush: js">var today = new Date(); // Получаем текущую дату +var endYear = new Date(1995, 11, 31, 23, 59, 59, 999); // Устанавливаем месяц и день на конец года +endYear.setFullYear(today.getFullYear()); // Устанавливаем текущий год +var msPerDay = 24 * 60 * 60 * 1000; // Количество миллисекунд в одних сутках +var daysLeft = (endYear.getTime() - today.getTime()) / msPerDay; +var daysLeft = Math.round(daysLeft); // возвращает количество дней, оставшихся до конца года +</pre> + +<p>Этот пример создает объект <code>Date</code> названный <code>today, который содержит текущую дату и время</code>. Затем, создается воспомогательный <code>Date</code> объект, названный <code>endYear,</code> которому устанавливаются значения, указывающие на конец года. После этого, при помощи расчитанного количества миллисекунд в сутках, вычисляется количество дней между <code>today</code> и <code>endYear</code>, При этом используются метод <code>getTime</code> и округление, для получения количества полных дней.</p> + +<p>Метод <code>parse</code> полезен для присвоения значений существующим объектам <code>Date</code> из текстового формата. Например, следующий код использует мотоды <code>parse</code> и <code>setTime</code> чтобы установить значение переменной <code>IPOdate</code>:</p> + +<pre class="brush: js">var IPOdate = new Date(); +IPOdate.setTime(Date.parse("Aug 9, 1995")); +</pre> + +<h3 id="Пример">Пример</h3> + +<p>В следующем примере приведена функция <code>JSClock(), которая возвращает время в формате электронных часов:</code></p> + +<pre class="brush: js">function JSClock() { + var time = new Date(); + var hour = time.getHours(); + var minute = time.getMinutes(); + var second = time.getSeconds(); + var temp = "" + ((hour > 12) ? hour - 12 : hour); + if (hour == 0) + temp = "12"; + temp += ((minute < 10) ? ":0" : ":") + minute; + temp += ((second < 10) ? ":0" : ":") + second; + temp += (hour >= 12) ? " P.M." : " A.M."; + return temp; +} +</pre> + +<p>Первым делом, функция JSClock создает новый объект <code>Date</code>, названный <code>time</code>; так как объект создается баз параметров, переменная <code>time </code>содержит текущую дату и время. Затем вызываются методы <code>getHours</code>, <code>getMinutes </code>и <code>getSeconds</code>, чтобы установить значения переменным <code>hour</code>, <code>minute </code>и <code>second</code>.</p> + +<p>Следующие четыре выражения строят текстовую строку на основе time. Первое из них создает переменную <code>temp</code>, присваивая ей значение при помощи условия; Если <code>hour</code> больше чем 12, то (<code>hour - 12</code>), иначе просто <code>hour.</code> В случае же, когда <code>hour</code> равно 0, берется фиксированное значение "12".</p> + +<p>Следующее выражение приращивает минуты к переменной <code>temp</code>. Если количество минут меньше 10, то условное выражение добавляет строку с двоеточием и заполняющим нулем, иначе, просто строку с двоеточием. Секунды приращиваются к переменной <code>temp</code> тем же путем.</p> + +<p>В завершение всего, последнее условное выражение добавляет строку "P.M." к переменной <code>temp</code> если <code>hour</code> равно или больше 12, иначе, добавляется строка "A.M.".</p> + +<p>{{PreviousNext("Web/JavaScript/Guide/Expressions_and_Operators", "Web/JavaScript/Guide/Text_formatting")}}</p> diff --git a/files/ru/web/javascript/guide/predefined_core_objects/index.html b/files/ru/web/javascript/guide/predefined_core_objects/index.html new file mode 100644 index 0000000000..d7fd638b6d --- /dev/null +++ b/files/ru/web/javascript/guide/predefined_core_objects/index.html @@ -0,0 +1,922 @@ +--- +title: Predefined Core Objects +slug: Web/JavaScript/Guide/Predefined_Core_Objects +translation_of: Web/JavaScript/Guide +--- +<p>Эта глава описывает предопределённые объекты в стандартном JavaScript: <code>Array</code>, <code>Boolean</code>, <code>Date</code>, <code>Function</code>, <code>Math</code>, <code>Number</code>, <code>RegExp</code>, и <code>String</code>.</p> + +<h2 id="Объект_Array">Объект Array</h2> + +<p>В JavaScript массив как тип данных отсутствует. Тем не менее, вы можете использовать предопределённый объект <code>Array</code> и его методы, чтобы работать с массивами в ваших приложениях. Объект <code>Array</code> содержит различные методы для манипуляций с массивами, такими как объединение, обращение и сортировка. У него есть свойство для определения длины массива и другие свойства для работы с регулярными выражениями.</p> + +<p><em>Массив</em> - это упорядоченный набор значений, обращаться к которым можно с помощью имени и индекса. Например, можно создать массив <code>emp</code>, который содержит имена сотрудников фирмы, проиндексированные номерами. Тогда <code>emp[1]</code> будет соответствовать сотруднику номер один, <code>emp[2]</code> сотруднику номер два и так далее.</p> + +<h3 id="Создание_объекта_Array">Создание объекта Array</h3> + +<p>Следующие инструкции создают эквивалентные массивы:</p> + +<div style="margin-right: 270px;"> +<pre class="brush: js">var arr = new Array(element0, element1, ..., elementN); +var arr = Array(element0, element1, ..., elementN); +var arr = [element0, element1, ..., elementN]; +</pre> +</div> + +<p><code>element0, element1, ..., elementN</code> это список значений во вновь создаваемом массиве. Когда эти значения заданы, массив инициализирует ими свои эелементы. Длина массива определяется по числу аргументов и сохраняется в свойстве <code>length </code>(длина).</p> + +<p>Синтаксис с квадратными скобками называется "литералом массива" (array literal) или "инициализатором массива" (array initializer). Такая запись короче других и используется чаще. Подробности смотрите в <a href="/en-US/docs/JavaScript/Guide/Values,_Variables,_and_Literals#Array_Literals" title="en-US/docs/JavaScript/Guide/Values, Variables, and Literals#Array Literals">Array Literals</a>.</p> + +<p>Создать массив ненулевой длины, но без элементов, можно одним из следующих способов:</p> + +<pre class="brush: js">var arr = new Array(arrayLength); +var arr = Array(arrayLength); + +// This has exactly the same effect +var arr = []; +arr.length = arrayLength; +</pre> + +<p>Обратите внимание: в приведённом выше коде <code>arrayLength</code> должен быть значением типа <code>Number</code>, то есть числом, иначе будет создан массив с одним элементом (переданным конструктору значением). Вызов <code>arr.length</code> возвратит <code>arrayLength</code>, хотя на самом деле элемент содержит пустые (неопределённые, undefined) элементы. Итерация по массиву циклом for...in не возвратит никаких элементов.</p> + +<p>Массивы можно не только определить как и переменные, но и присвоить существующему объекту как свойство:</p> + +<pre class="brush: js">var obj = {}; +// ... +obj.prop = [element0, element1, ..., elementN]; + +// OR +var obj = {prop: [element0, element1, ...., elementN]} +</pre> + +<p>Если же вы хотите создать одноэлементный массив, содержащий число, придётся использовать запись с квадратными скобками, так как когда конструктору Array() передаётся одно-единственное число, оно трактуется как длина массива, а не как хранимвый элемент.</p> + +<pre><code>var arr = [42]; +var arr = Array(42); // Creates an array with no element, but with arr.length set to 42 + +// The above code is equivalent to +var arr = []; +arr.length = 42; +</code> +</pre> + +<p>Вызов <code>Array(N)</code> приводит к <code>RangeError</code>, если <code>N</code> не является целым числом, чья дробная часть не равна нулю. Следующий пример иллюстрирует это поведение.</p> + +<pre>var arr = Array(9.3); // RangeError: Invalid array length +</pre> + +<p>Если ваш код должен создавать массивы с отдельными элементами произвольного типа, безопаснее использовать литералы массива. Или, создайте пустой массив, прежде чем добавлять элементы к нему.</p> + +<h3 id="Заполнение_массива">Заполнение массива</h3> + +<p>You can populate an array by assigning values to its elements. For example,</p> + +<pre class="brush: js">var emp = []; +emp[0] = "Casey Jones"; +emp[1] = "Phil Lesh"; +emp[2] = "August West"; +</pre> + +<p><strong>Note:</strong> if you supply a non-integer value to the array operator in the code above, a property will be created in the object representing the array, instead of an array element.</p> + +<pre> var arr = []; +arr[3.4] = "Oranges"; +console.log(arr.length); // 0 +console.log(arr.hasOwnProperty(3.4)); // true +</pre> + +<p>You can also populate an array when you create it:</p> + +<pre class="brush: js">var myArray = new Array("Hello", myVar, 3.14159); +var myArray = ["Mango", "Apple", "Orange"] +</pre> + +<h3 id="Referring_to_Array_Elements">Referring to Array Elements</h3> + +<p>You refer to an array's elements by using the element's ordinal number. For example, suppose you define the following array:</p> + +<pre class="brush: js">var myArray = ["Wind", "Rain", "Fire"]; +</pre> + +<p>You then refer to the first element of the array as <code>myArray[0]</code> and the second element of the array as <code>myArray[1]</code>. The index of the elements begins with zero.</p> + +<p><strong>Note:</strong> the array operator (square brackets) is also used for accessing the array's properties (arrays are also objects in JavaScript). For example,</p> + +<pre> var arr = ["one", "two", "three"]; +arr[2]; // three +arr["length"]; // 3 +</pre> + +<h3 id="Understanding_length">Understanding length</h3> + +<p>At the implementation level, JavaScript's arrays actually store their elements as standard object properties, using the array index as the property name. The <code>length</code> property is special; it always returns the index of the last element plus one (in following example Dusty is indexed at 30 so cats.length returns 30 + 1). Remember, Javascript Array indexes are 0-based: they start at 0, not 1. This means that the <code><code>length</code></code> property will be one more than the highest index stored in the array:</p> + +<pre class="brush: js">var cats = []; +cats[30] = ['Dusty']; +print(cats.length); // 31 +</pre> + +<p>You can also assign to the <code>length</code> property. Writing a value that is shorter than the number of stored items truncates the array; writing 0 empties it entirely:</p> + +<pre class="brush: js">var cats = ['Dusty', 'Misty', 'Twiggy']; +console.log(cats.length); // 3 + +cats.length = 2; +console.log(cats); // prints "Dusty,Misty" - Twiggy has been removed + +cats.length = 0; +console.log(cats); // prints nothing; the cats array is empty + +cats.length = 3; +console.log(cats); // [undefined, undefined, undefined] +</pre> + +<h3 id="Iterating_over_arrays">Iterating over arrays</h3> + +<p>A common operation is to iterate over the values of an array, processing each one in some way. The simplest way to do this is as follows:</p> + +<pre class="brush: js">var colors = ['red', 'green', 'blue']; +for (var i = 0; i < colors.length; i++) { + console.log(colors[i]); +} +</pre> + +<p>If you know that none of the elements in your array evaluate to <code>false</code> in a boolean context — if your array consists only of <a href="/en-US/docs/DOM" title="en-US/docs/DOM">DOM</a> nodes, for example, you can use a more efficient idiom:</p> + +<pre class="brush: js">var divs = document.getElementsByTagName('div'); +for (var i = 0, div; div = divs[i]; i++) { + /* Process div in some way */ +} +</pre> + +<p>This avoids the overhead of checking the length of the array, and ensures that the <code>div</code> variable is reassigned to the current item each time around the loop for added convenience.</p> + +<p>The <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach" title="en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach"><code>forEach()</code></a> method, introduced in JavaScript 1.6, provides another way of iterating over an array:</p> + +<pre class="brush: js">var colors = ['red', 'green', 'blue']; +colors.forEach(function(color) { + console.log(color); +}); +</pre> + +<p>The function passed to <code>forEach</code> is executed once for every item in the array, with the array item passed as the argument to the function. Unassigned values are not iterated in a <code>forEach</code> loop.</p> + +<p>Note that the elements of array omitted when the array is defined are not listed when iterating by <code>forEach, </code>but are listed when <code>undefined</code> has been manually assigned to the element:</p> + +<pre class="brush: js">var array = ['first', 'second', , 'fourth']; + +// returns ['first', 'second', 'fourth']; +array.forEach(function(element) { + console.log(element); +}) + +if(array[2] === undefined) { console.log('array[2] is undefined'); } // true + +var array = ['first', 'second', undefined, 'fourth']; + +// returns ['first', 'second', undefined, 'fourth']; +array.forEach(function(element) { + console.log(element); +})</pre> + +<p>Since JavaScript elements are saved as standard object properties, it is not advisable to iterate through JavaScript arrays using for...in loops because normal elements and all enumerable properties will be listed.</p> + +<h3 id="Array_Methods">Array Methods</h3> + +<p>The <code>Array</code> object has the following methods:</p> + +<ul> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/concat" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/concat"><code>concat()</code></a> joins two arrays and returns a new array. + + <pre class="brush: js">var myArray = new Array("1", "2", "3"); +myArray = myArray.concat("a", "b", "c"); // myArray is now ["1", "2", "3", "a", "b", "c"] +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/join" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/join"><code>join(deliminator = ",")</code></a> joins all elements of an array into a string. + <pre class="brush: js">var myArray = new Array("Wind", "Rain", "Fire"); +var list = myArray.join(" - "); // list is "Wind - Rain - Fire" +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/push" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/push"><code>push()</code></a> adds one or more elements to the end of an array and returns the resulting length of the array. + <pre class="brush: js">var myArray = new Array("1", "2"); +myArray.push("3"); // myArray is now ["1", "2", "3"] +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/pop" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/pop"><code>pop()</code></a> removes the last element from an array and returns that element. + <pre class="brush: js">var myArray = new Array("1", "2", "3"); +var last = myArray.pop(); // myArray is now ["1", "2"], last = "3" +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/shift" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/shift"><code>shift()</code></a> removes the first element from an array and returns that element. + <pre class="brush: js">var myArray = new Array ("1", "2", "3"); +var first = myArray.shift(); // myArray is now ["2", "3"], first is "1" +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/unshift" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/unshift"><code>unshift()</code></a> adds one or more elements to the front of an array and returns the new length of the array. + <pre class="brush: js">var myArray = new Array ("1", "2", "3"); +myArray.unshift("4", "5"); // myArray becomes ["4", "5", "1", "2", "3"]</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/slice" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/slice"><code>slice(start_index, upto_index)</code></a> extracts a section of an array and returns a new array. + <pre class="brush: js">var myArray = new Array ("a", "b", "c", "d", "e"); +myArray = myArray.slice(1, 4); /* starts at index 1 and extracts all elements + until index 3, returning [ "b", "c", "d"] */ +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/splice" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/splice"><code>splice(index, count_to_remove, addelement1, addelement2, ...)</code></a> removes elements from an array and (optionally) replaces them. + <pre class="brush: js">var myArray = new Array ("1", "2", "3", "4", "5"); +myArray.splice(1, 3, "a", "b", "c", "d"); // myArray is now ["1", "a", "b", "c", "d", "5"] + // This code started at index one (or where the "2" was), removed 3 elements there, + // and then inserted all consecutive elements in its place. +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/reverse" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/reverse"><code>reverse()</code></a> transposes the elements of an array: the first array element becomes the last and the last becomes the first. + <pre class="brush: js">var myArray = new Array ("1", "2", "3"); +myArray.reverse(); // transposes the array so that myArray = [ "3", "2", "1" ] +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/sort"><code>sort()</code></a> sorts the elements of an array. + <pre class="brush: js">var myArray = new Array("Wind", "Rain", "Fire"); +myArray.sort(); // sorts the array so that myArrray = [ "Fire", "Rain", "Wind" ] +</pre> + + <p><code>sort()</code> can also take a callback function to determine how array elements are compared. The function compares two values and returns one of three values:</p> + + <ul> + <li>if <code>a</code> is less than <code>b</code> by the sorting system, return -1 (or any negative number)</li> + <li>if <code>a</code> is greater than <code>b</code> by the sorting system, return 1 (or any positive number)</li> + <li>if <code>a</code> and <code>b</code> are considered equivalent, return 0.</li> + </ul> + + <p>For instance, the following will sort by the last letter of an array:</p> + + <pre class="brush: js">var sortFn = function(a, b){ + if (a[a.length - 1] < b[b.length - 1]) return -1; + if (a[a.length - 1] > b[b.length - 1]) return 1; + if (a[a.length - 1] == b[b.length - 1]) return 0; +} +myArray.sort(sortFn); // sorts the array so that myArray = ["Wind","Fire","Rain"]</pre> + </li> +</ul> + +<p>Compatibility code for older browsers can be found for each of these functions on the individual pages. Native browser support for these features in various browsers can be found<a class="external" href="http://www.robertnyman.com/javascript/" title="http://www.robertnyman.com/javascript/"> here.</a></p> + +<ul> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/indexOf"><code>indexOf(searchElement[, fromIndex])</code></a> searches the array for <code>searchElement</code> and returns the index of the first match. + + <pre class="brush: js">var a = ['a', 'b', 'a', 'b', 'a']; +alert(a.indexOf('b')); // Alerts 1 +// Now try again, starting from after the last match +alert(a.indexOf('b', 2)); // Alerts 3 +alert(a.indexOf('z')); // Alerts -1, because 'z' was not found +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/lastIndexOf" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/lastIndexOf"><code>lastIndexOf(searchElement[, fromIndex])</code></a> works like <code>indexOf</code>, but starts at the end and searches backwards. + <pre class="brush: js">var a = ['a', 'b', 'c', 'd', 'a', 'b']; +alert(a.lastIndexOf('b')); // Alerts 5 +// Now try again, starting from before the last match +alert(a.lastIndexOf('b', 4)); // Alerts 1 +alert(a.lastIndexOf('z')); // Alerts -1 +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/forEach"><code>forEach(callback[, thisObject])</code></a> executes <code>callback</code> on every array item. + <pre class="brush: js">var a = ['a', 'b', 'c']; +a.forEach(alert); // Alerts each item in turn +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/map" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/map"><code>map(callback[, thisObject])</code></a> returns a new array of the return value from executing <code>callback</code> on every array item. + <pre class="brush: js">var a1 = ['a', 'b', 'c']; +var a2 = a1.map(function(item) { return item.toUpperCase(); }); +alert(a2); // Alerts A,B,C +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/filter" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/filter"><code>filter(callback[, thisObject])</code></a> returns a new array containing the items for which callback returned true. + <pre class="brush: js">var a1 = ['a', 10, 'b', 20, 'c', 30]; +var a2 = a1.filter(function(item) { return typeof item == 'number'; }); +alert(a2); // Alerts 10,20,30 +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/every" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/every"><code>every(callback[, thisObject])</code></a> returns true if <code>callback</code> returns true for every item in the array. + <pre class="brush: js">function isNumber(value){ + return typeof value == 'number'; +} +var a1 = [1, 2, 3]; +alert(a1.every(isNumber)); // Alerts true +var a2 = [1, '2', 3]; +alert(a2.every(isNumber)); // Alerts false +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/some" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/some"><code>some(callback[, thisObject])</code></a> returns true if <code>callback</code> returns true for at least one item in the array. + <pre class="brush: js">function isNumber(value){ + return typeof value == 'number'; +} +var a1 = [1, 2, 3]; +alert(a1.some(isNumber)); // Alerts true +var a2 = [1, '2', 3]; +alert(a2.some(isNumber)); // Alerts true +var a3 = ['1', '2', '3']; +alert(a3.some(isNumber)); // Alerts false +</pre> + </li> +</ul> + +<p>The methods above that take a callback are known as <em>iterative methods</em>, because they iterate over the entire array in some fashion. Each one takes an optional second argument called <code>thisObject</code>. If provided, <code>thisObject</code> becomes the value of the <code>this</code> keyword inside the body of the callback function. If not provided, as with other cases where a function is invoked outside of an explicit object context, <code>this</code> will refer to the global object (<a href="/en-US/docs/DOM/window" title="en-US/docs/DOM/window"><code>window</code></a>).</p> + +<p>The callback function is actually called with three arguments. The first is the value of the current item, the second is its array index, and the third is a reference to the array itself. JavaScript functions ignore any arguments that are not named in the parameter list so it is safe to provide a callback function that only takes a single argument, such as <code>alert</code>.</p> + +<ul> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/Reduce" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/reduce"><code>reduce(callback[, initialValue])</code></a> applies <code>callback(firstValue, secondValue)</code> to reduce the list of items down to a single value. + + <pre class="brush: js">var a = [10, 20, 30]; +var total = a.reduce(function(first, second) { return first + second; }, 0); +alert(total) // Alerts 60 +</pre> + </li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/ReduceRight" title="en-US/docs/JavaScript/Reference/Global + Objects/Array/reduceRight"><code>reduceRight(callback[, initialValue])</code></a> works like <code>reduce()</code>, but starts with the last element.</li> +</ul> + +<p><code>reduce</code> and <code>reduceRight</code> are the least obvious of the iterative array methods. They should be used for algorithms that combine two values recursively in order to reduce a sequence down to a single value.</p> + +<h3 id="Multi-Dimensional_Arrays">Multi-Dimensional Arrays</h3> + +<p>Arrays can be nested, meaning that an array can contain another array as an element. Using this characteristic of JavaScript arrays, multi-dimensional arrays can be created.</p> + +<p>The following code creates a two-dimensional array.</p> + +<pre class="brush: js">var a = new Array(4); +for (i = 0; i < 4; i++) { + a[i] = new Array(4); + for (j = 0; j < 4; j++) { + a[i][j] = "[" + i + "," + j + "]"; + } +} +</pre> + +<p>This example creates an array with the following rows:</p> + +<pre>Row 0: [0,0] [0,1] [0,2] [0,3] +Row 1: [1,0] [1,1] [1,2] [1,3] +Row 2: [2,0] [2,1] [2,2] [2,3] +Row 3: [3,0] [3,1] [3,2] [3,3] +</pre> + +<h3 id="Arrays_and_Regular_Expressions">Arrays and Regular Expressions</h3> + +<p>When an array is the result of a match between a regular expression and a string, the array returns properties and elements that provide information about the match. An array is the return value of <a href="/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec" title="en-US/docs/JavaScript/Reference/Global Objects/RegExp/exec"><code>RegExp.exec()</code></a>, <a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/match" title="en-US/docs/JavaScript/Reference/Global Objects/String/match"><code>String.match()</code></a>, and <a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/split" title="en-US/docs/JavaScript/Reference/Global +Objects/String/split"><code>String.split()</code></a>. For information on using arrays with regular expressions, see <a href="/en-US/docs/JavaScript/Guide/Regular_Expressions" title="en-US/docs/JavaScript/Guide/Regular Expressions">Regular Expressions</a>.</p> + +<h3 id="Working_with_Array-like_objects">Working with Array-like objects</h3> + +<p>Some JavaScript objects, such as the <a href="/en-US/docs/DOM/NodeList" title="en-US/docs/DOM/NodeList"><code>NodeList</code></a> returned by <a href="/en-US/docs/DOM/document.getElementsByTagName" title="en-US/docs/DOM/document.getElementsByTagName"><code>document.getElementsByTagName()</code></a> or the <a href="/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments" title="en-US/docs/JavaScript/Reference/Functions and +function +scope/arguments"><code>arguments</code></a> object made available within the body of a function, look and behave like arrays on the surface but do not share all of their methods. The <code>arguments</code> object provides a <a href="/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/length" title="en-US/docs/JavaScript/Reference/Functions +and function +scope/arguments/length"><code>length</code></a> attribute but does not implement the <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach" title="en-US/docs/JavaScript/Reference/Global Objects/Array/forEach"><code>forEach()</code></a> method, for example.</p> + +<p>Array generics, introduced in JavaScript 1.6, provide a way of running <code>Array</code> methods against other array-like objects. Each standard array method has a corresponding method on the <code>Array</code> object itself; for example:</p> + +<pre class="brush: js"> function alertArguments() { + Array.forEach(arguments, function(item) { + alert(item); + }); + } +</pre> + +<p>These generic methods can be emulated more verbosely in older versions of JavaScript using the call method provided by JavaScript function objects:</p> + +<pre class="brush: js"> Array.prototype.forEach.call(arguments, function(item) { + alert(item); + }); +</pre> + +<p>Array generic methods can be used on strings as well, since they provide sequential access to their characters in a similar way to arrays:</p> + +<pre class="brush: js">Array.forEach("a string", function(chr) { + alert(chr); +});</pre> + +<p>Here are some further examples of applying array methods to strings, also taking advantage of <a href="/en-US/docs/JavaScript/New_in_JavaScript/1.8#Expression_closures" title="en-US/docs/New_in_JavaScript_1.8#Expression_closures">JavaScript 1.8 expression closures</a>:</p> + +<pre class="brush: js">var str = 'abcdef'; +var consonantsOnlyStr = Array.filter(str, function (c) !(/[aeiou]/i).test(c)).join(''); // 'bcdf' +var vowelsPresent = Array.some(str, function (c) (/[aeiou]/i).test(c)); // true +var allVowels = Array.every(str, function (c) (/[aeiou]/i).test(c)); // false +var interpolatedZeros = Array.map(str, function (c) c+'0').join(''); // 'a0b0c0d0e0f0' +var numerologicalValue = Array.reduce(str, function (c, c2) c+c2.toLowerCase().charCodeAt()-96, 0); +// 21 (reduce() since JS v1.8) +</pre> + +<p>Note that <code>filter</code> and <code>map</code> do not automatically return the characters back into being members of a string in the return result; an array is returned, so we must use <code>join</code> to return back to a string.</p> + +<h3 id="Array_comprehensions">Array comprehensions</h3> + +<p>Introduced in JavaScript 1.7, array comprehensions provide a useful shortcut for constructing a new array based on the contents of another. Comprehensions can often be used in place of calls to <code>map()</code> and <code>filter()</code>, or as a way of combining the two.</p> + +<p>The following comprehension takes an array of numbers and creates a new array of the double of each of those numbers.</p> + +<pre class="brush: js">var numbers = [1, 2, 3, 4]; +var doubled = [i * 2 for (i of numbers)]; +alert(doubled); // Alerts 2,4,6,8 +</pre> + +<p>This is equivalent to the following <code>map()</code> operation:</p> + +<pre class="brush: js">var doubled = numbers.map(function(i){return i * 2;}); +</pre> + +<p>Comprehensions can also be used to select items that match a particular expression. Here is a comprehension which selects only even numbers:</p> + +<pre class="brush: js">var numbers = [1, 2, 3, 21, 22, 30]; +var evens = [i for (i of numbers) if (i % 2 === 0)]; +alert(evens); // Alerts 2,22,30 +</pre> + +<p><code>filter()</code> can be used for the same purpose:</p> + +<pre class="brush: js">var evens = numbers.filter(function(i){return i % 2 === 0;}); +</pre> + +<p><code>map()</code> and <code>filter()</code> style operations can be combined into a single array comprehension. Here is one that filters just the even numbers, then creates an array containing their doubles:</p> + +<pre class="brush: js">var numbers = [1, 2, 3, 21, 22, 30]; +var doubledEvens = [i * 2 for (i of numbers) if (i % 2 === 0)]; +alert(doubledEvens); // Alerts 4,44,60 +</pre> + +<p>The square brackets of an array comprehension introduce an implicit block for scoping purposes. New variables (such as i in the example) are treated as if they had been declared using <a href="/en-US/docs/JavaScript/Reference/Statements/let" title="/en-US/docs/JavaScript/Reference/Statements/let"><code>let</code></a>. This means that they will not be available outside of the comprehension.</p> + +<p>The input to an array comprehension does not itself need to be an array; <a href="/en-US/docs/JavaScript/Guide/Iterators_and_Generators" title="en-US/docs/JavaScript/Guide/Iterators and Generators">iterators and generators</a> can also be used.</p> + +<p>Even strings may be used as input; to achieve the filter and map actions (under Array-like objects) above:</p> + +<pre class="brush: js">var str = 'abcdef'; +var consonantsOnlyStr = [c for (c of str) if (!(/[aeiouAEIOU]/).test(c)) ].join(''); // 'bcdf' +var interpolatedZeros = [c+'0' for (c of str) ].join(''); // 'a0b0c0d0e0f0' +</pre> + +<p>Again, the input form is not preserved, so we have to use <code>join()</code> to revert back to a string.</p> + +<h2 id="Boolean_Object">Boolean Object</h2> + +<p>The <code>Boolean</code> object is a wrapper around the primitive Boolean data type. Use the following syntax to create a <code>Boolean</code> object:</p> + +<pre class="brush: js">var booleanObjectName = new Boolean(value); +</pre> + +<p>Do not confuse the primitive Boolean values <code>true</code> and <code>false</code> with the true and false values of the <code>Boolean</code> object. Any object whose value is not <code>undefined</code> , <code>null</code>, <code>0</code>, <code>NaN</code>, or the empty string, including a <code>Boolean</code> object whose value is false, evaluates to true when passed to a conditional statement. See <a href="/en-US/docs/JavaScript/Guide/Statements#if...else_Statement" title="en-US/docs/JavaScript/Guide/Statements#if...else Statement">if...else Statement</a> for more information.</p> + +<h2 id="Date_Object">Date Object</h2> + +<p>JavaScript does not have a date data type. However, you can use the <code>Date</code> object and its methods to work with dates and times in your applications. The <code>Date</code> object has a large number of methods for setting, getting, and manipulating dates. It does not have any properties.</p> + +<p>JavaScript handles dates similarly to Java. The two languages have many of the same date methods, and both languages store dates as the number of milliseconds since January 1, 1970, 00:00:00.</p> + +<p>The <code>Date</code> object range is -100,000,000 days to 100,000,000 days relative to 01 January, 1970 UTC.</p> + +<p>To create a <code>Date</code> object:</p> + +<pre class="brush: js">var dateObjectName = new Date([parameters]); +</pre> + +<p>where <code>dateObjectName</code> is the name of the <code>Date</code> object being created; it can be a new object or a property of an existing object.</p> + +<p>Calling <code>Date</code> without the <code>new</code> keyword simply converts the provided date to a string representation.</p> + +<p>The <code>parameters</code> in the preceding syntax can be any of the following:</p> + +<ul> + <li>Nothing: creates today's date and time. For example, <code>today = new Date();</code>.</li> + <li>A string representing a date in the following form: "Month day, year hours:minutes:seconds." For example, <code>var Xmas95 = new Date("December 25, 1995 13:30:00")</code>. If you omit hours, minutes, or seconds, the value will be set to zero.</li> + <li>A set of integer values for year, month, and day. For example, <code>var Xmas95 = new Date(1995, 11, 25)</code>.</li> + <li>A set of integer values for year, month, day, hour, minute, and seconds. For example, <code>var Xmas95 = new Date(1995, 11, 25, 9, 30, 0);</code>.</li> +</ul> + +<p><strong>JavaScript 1.2 and earlier</strong><br> + The <code>Date</code> object behaves as follows:</p> + +<ul> + <li>Dates prior to 1970 are not allowed.</li> + <li>JavaScript depends on platform-specific date facilities and behavior; the behavior of the <code>Date</code> object varies from platform to platform.</li> +</ul> + +<h3 id="Methods_of_the_Date_Object">Methods of the Date Object</h3> + +<p>The <code>Date</code> object methods for handling dates and times fall into these broad categories:</p> + +<ul> + <li>"set" methods, for setting date and time values in <code>Date</code> objects.</li> + <li>"get" methods, for getting date and time values from <code>Date</code> objects.</li> + <li>"to" methods, for returning string values from <code>Date</code> objects.</li> + <li>parse and UTC methods, for parsing <code>Date</code> strings.</li> +</ul> + +<p>With the "get" and "set" methods you can get and set seconds, minutes, hours, day of the month, day of the week, months, and years separately. There is a <code>getDay</code> method that returns the day of the week, but no corresponding <code>setDay</code> method, because the day of the week is set automatically. These methods use integers to represent these values as follows:</p> + +<ul> + <li>Seconds and minutes: 0 to 59</li> + <li>Hours: 0 to 23</li> + <li>Day: 0 (Sunday) to 6 (Saturday)</li> + <li>Date: 1 to 31 (day of the month)</li> + <li>Months: 0 (January) to 11 (December)</li> + <li>Year: years since 1900</li> +</ul> + +<p>For example, suppose you define the following date:</p> + +<pre class="brush: js">var Xmas95 = new Date("December 25, 1995"); +</pre> + +<p>Then <code>Xmas95.getMonth()</code> returns 11, and <code>Xmas95.getFullYear()</code> returns 1995.</p> + +<p>The <code>getTime</code> and <code>setTime</code> methods are useful for comparing dates. The <code>getTime</code> method returns the number of milliseconds since January 1, 1970, 00:00:00 for a <code>Date</code> object.</p> + +<p>For example, the following code displays the number of days left in the current year:</p> + +<pre class="brush: js">var today = new Date(); +var endYear = new Date(1995, 11, 31, 23, 59, 59, 999); // Set day and month +endYear.setFullYear(today.getFullYear()); // Set year to this year +var msPerDay = 24 * 60 * 60 * 1000; // Number of milliseconds per day +var daysLeft = (endYear.getTime() - today.getTime()) / msPerDay; +var daysLeft = Math.round(daysLeft); //returns days left in the year +</pre> + +<p>This example creates a <code>Date</code> object named <code>today</code> that contains today's date. It then creates a <code>Date</code> object named <code>endYear</code> and sets the year to the current year. Then, using the number of milliseconds per day, it computes the number of days between <code>today</code> and <code>endYear</code>, using <code>getTime</code> and rounding to a whole number of days.</p> + +<p>The <code>parse</code> method is useful for assigning values from date strings to existing <code>Date</code> objects. For example, the following code uses <code>parse</code> and <code>setTime</code> to assign a date value to the <code>IPOdate</code> object:</p> + +<pre class="brush: js">var IPOdate = new Date(); +IPOdate.setTime(Date.parse("Aug 9, 1995")); +</pre> + +<h3 id="Using_the_Date_Object_an_Example">Using the Date Object: an Example</h3> + +<p>In the following example, the function <code>JSClock()</code> returns the time in the format of a digital clock.</p> + +<pre class="brush: js">function JSClock() { + var time = new Date(); + var hour = time.getHours(); + var minute = time.getMinutes(); + var second = time.getSeconds(); + var temp = "" + ((hour > 12) ? hour - 12 : hour); + if (hour == 0) + temp = "12"; + temp += ((minute < 10) ? ":0" : ":") + minute; + temp += ((second < 10) ? ":0" : ":") + second; + temp += (hour >= 12) ? " P.M." : " A.M."; + return temp; +} +</pre> + +<p>The <code>JSClock</code> function first creates a new <code>Date</code> object called <code>time</code>; since no arguments are given, time is created with the current date and time. Then calls to the <code>getHours</code>, <code>getMinutes</code>, and <code>getSeconds</code> methods assign the value of the current hour, minute, and second to <code>hour</code>, <code>minute</code>, and <code>second</code>.</p> + +<p>The next four statements build a string value based on the time. The first statement creates a variable <code>temp</code>, assigning it a value using a conditional expression; if <code>hour</code> is greater than 12, (<code>hour - 12</code>), otherwise simply hour, unless hour is 0, in which case it becomes 12.</p> + +<p>The next statement appends a <code>minute</code> value to <code>temp</code>. If the value of <code>minute</code> is less than 10, the conditional expression adds a string with a preceding zero; otherwise it adds a string with a demarcating colon. Then a statement appends a seconds value to <code>temp</code> in the same way.</p> + +<p>Finally, a conditional expression appends "P.M." to <code>temp</code> if <code>hour</code> is 12 or greater; otherwise, it appends "A.M." to <code>temp</code>.</p> + +<h2 id="Function_Object">Function Object</h2> + +<p>The predefined <code>Function</code> object specifies a string of JavaScript code to be compiled as a function.</p> + +<p>To create a <code>Function</code> object:</p> + +<pre class="brush: js">var functionObjectName = new Function ([arg1, arg2, ... argn], functionBody); +</pre> + +<p><code>functionObjectName</code> is the name of a variable or a property of an existing object. It can also be an object followed by a lowercase event handler name, such as <code>window.onerror</code>.</p> + +<p><code>arg1</code>, <code>arg2</code>, ... <code>argn</code> are arguments to be used by the function as formal argument names. Each must be a string that corresponds to a valid JavaScript identifier; for example "x" or "theForm".</p> + +<p><code>functionBody</code> is a string specifying the JavaScript code to be compiled as the function body.</p> + +<p><code>Function</code> objects are evaluated each time they are used. This is less efficient than declaring a function and calling it within your code, because declared functions are compiled.</p> + +<p>In addition to defining functions as described here, you can also use the <a href="/en-US/docs/JavaScript/Reference/Statements/function" title="en-US/docs/JavaScript/Reference/Statements/function"><code>function</code> statement</a> and the function expression. See the <a href="/en-US/docs/JavaScript/Reference" title="en-US/docs/JavaScript/Reference">JavaScript Reference</a> for more information.</p> + +<p>The following code assigns a function to the variable <code>setBGColor</code>. This function sets the current document's background color.</p> + +<pre class="brush: js">var setBGColor = new Function("document.bgColor = 'antiquewhite'"); +</pre> + +<p>To call the <code>Function</code> object, you can specify the variable name as if it were a function. The following code executes the function specified by the <code>setBGColor</code> variable:</p> + +<pre class="brush: js">var colorChoice="antiquewhite"; +if (colorChoice=="antiquewhite") {setBGColor()} +</pre> + +<p>You can assign the function to an event handler in either of the following ways:</p> + +<ol> + <li> + <pre class="brush: js">document.form1.colorButton.onclick = setBGColor; +</pre> + </li> + <li> + <pre class="brush: html"><INPUT NAME="colorButton" TYPE="button" + VALUE="Change background color" + onClick="setBGColor()"> +</pre> + </li> +</ol> + +<p>Creating the variable <code>setBGColor</code> shown above is similar to declaring the following function:</p> + +<pre class="brush: js">function setBGColor() { + document.bgColor = 'antiquewhite'; +} +</pre> + +<p>Assigning a function to a variable is similar to declaring a function, but there are differences:</p> + +<ul> + <li>When you assign a function to a variable using <code>var setBGColor = new Function("...")</code>, <code>setBGColor</code> is a variable for which the current value is a reference to the function created with <code>new Function()</code>.</li> + <li>When you create a function using <code>function setBGColor() {...}</code>, <code>setBGColor</code> is not a variable, it is the name of a function.</li> +</ul> + +<p>You can nest a function within a function. The nested (inner) function is private to its containing (outer) function:</p> + +<ul> + <li>The inner function can be accessed only from statements in the outer function.</li> + <li>The inner function can use the arguments and variables of the outer function. The outer function cannot use the arguments and variables of the inner function.</li> +</ul> + +<h2 id="Math_Object">Math Object</h2> + +<p>The predefined <code>Math</code> object has properties and methods for mathematical constants and functions. For example, the <code>Math</code> object's <code>PI</code> property has the value of pi (3.141...), which you would use in an application as</p> + +<pre class="brush: js">Math.PI +</pre> + +<p>Similarly, standard mathematical functions are methods of <code>Math</code>. These include trigonometric, logarithmic, exponential, and other functions. For example, if you want to use the trigonometric function sine, you would write</p> + +<pre class="brush: js">Math.sin(1.56) +</pre> + +<p>Note that all trigonometric methods of <code>Math</code> take arguments in radians.</p> + +<p>The following table summarizes the <code>Math</code> object's methods.</p> + +<table class="standard-table"> + <caption>Table 7.1 Methods of Math</caption> + <thead> + <tr> + <th scope="col">Method</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>abs</code></td> + <td>Absolute value</td> + </tr> + <tr> + <td><code>sin</code>, <code>cos</code>, <code>tan</code></td> + <td>Standard trigonometric functions; argument in radians</td> + </tr> + <tr> + <td><code>acos</code>, <code>asin</code>, <code>atan</code>, <code>atan2</code></td> + <td>Inverse trigonometric functions; return values in radians</td> + </tr> + <tr> + <td><code>exp</code>, <code>log</code></td> + <td>Exponential and natural logarithm, base <code>e</code></td> + </tr> + <tr> + <td><code>ceil</code></td> + <td>Returns least integer greater than or equal to argument</td> + </tr> + <tr> + <td><code>floor</code></td> + <td>Returns greatest integer less than or equal to argument</td> + </tr> + <tr> + <td><code>min</code>, <code>max</code></td> + <td>Returns greater or lesser (respectively) of two arguments</td> + </tr> + <tr> + <td><code>pow</code></td> + <td>Exponential; first argument is base, second is exponent</td> + </tr> + <tr> + <td><code>random</code></td> + <td>Returns a random number between 0 and 1.</td> + </tr> + <tr> + <td><code>round</code></td> + <td>Rounds argument to nearest integer</td> + </tr> + <tr> + <td><code>sqrt</code></td> + <td>Square root</td> + </tr> + </tbody> +</table> + +<p>Unlike many other objects, you never create a <code>Math</code> object of your own. You always use the predefined <code>Math</code> object.</p> + +<h2 id="Number_Object">Number Object</h2> + +<p>The <code>Number</code> object has properties for numerical constants, such as maximum value, not-a-number, and infinity. You cannot change the values of these properties and you use them as follows:</p> + +<pre class="brush: js">var biggestNum = Number.MAX_VALUE; +var smallestNum = Number.MIN_VALUE; +var infiniteNum = Number.POSITIVE_INFINITY; +var negInfiniteNum = Number.NEGATIVE_INFINITY; +var notANum = Number.NaN; +</pre> + +<p>You always refer to a property of the predefined <code>Number</code> object as shown above, and not as a property of a <code>Number</code> object you create yourself.</p> + +<p>The following table summarizes the <code>Number</code> object's properties.</p> + +<table class="standard-table"> + <caption>Table 7.2 Properties of Number</caption> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>MAX_VALUE</code></td> + <td>The largest representable number</td> + </tr> + <tr> + <td><code>MIN_VALUE</code></td> + <td>The smallest representable number</td> + </tr> + <tr> + <td><code>NaN</code></td> + <td>Special "not a number" value</td> + </tr> + <tr> + <td><code>NEGATIVE_INFINITY</code></td> + <td>Special negative infinite value; returned on overflow</td> + </tr> + <tr> + <td><code>POSITIVE_INFINITY</code></td> + <td>Special positive infinite value; returned on overflow</td> + </tr> + </tbody> +</table> + +<p>The Number prototype provides methods for retrieving information from Number objects in various formats. The following table summarizes the methods of <code>Number.prototype</code>.</p> + +<table class="fullwidth-table"> + <caption>Table 7.3 Methods of Number.prototype</caption> + <thead> + <tr> + <th scope="col">Method</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>toExponential</code></td> + <td>Returns a string representing the number in exponential notation.</td> + </tr> + <tr> + <td><code>toFixed</code></td> + <td>Returns a string representing the number in fixed-point notation.</td> + </tr> + <tr> + <td><code>toPrecision</code></td> + <td>Returns a string representing the number to a specified precision in fixed-point notation.</td> + </tr> + <tr> + <td><code>toSource</code></td> + <td>Returns an object literal representing the specified <code>Number</code> object; you can use this value to create a new object. Overrides the <code>Object.toSource</code> method.</td> + </tr> + <tr> + <td><code>toString</code></td> + <td>Returns a string representing the specified object. Overrides the <code>Object.toString </code>method.</td> + </tr> + <tr> + <td><code>valueOf</code></td> + <td>Returns the primitive value of the specified object. Overrides the <code>Object.valueOf </code>method.</td> + </tr> + </tbody> +</table> + +<h2 id="RegExp_Object">RegExp Object</h2> + +<p>The <code>RegExp</code> object lets you work with regular expressions. It is described in <a href="/en-US/docs/JavaScript/Guide/Regular_Expressions" title="en-US/docs/JavaScript/Guide/Regular Expressions">Regular Expressions</a>.</p> + +<h2 id="String_Object">String Object</h2> + +<p>The <code>String</code> object is a wrapper around the string primitive data type. Do not confuse a string literal with the <code>String</code> object. For example, the following code creates the string literal <code>s1</code> and also the <code>String</code> object <code>s2</code>:</p> + +<pre class="brush: js">var s1 = "foo"; //creates a string literal value +var s2 = new String("foo"); //creates a String object +</pre> + +<p>You can call any of the methods of the <code>String</code> object on a string literal value—JavaScript automatically converts the string literal to a temporary <code>String</code> object, calls the method, then discards the temporary <code>String</code> object. You can also use the <code>String.length</code> property with a string literal.</p> + +<p>You should use string literals unless you specifically need to use a <code>String</code> object, because <code>String</code> objects can have counterintuitive behavior. For example:</p> + +<pre class="brush: js">var s1 = "2 + 2"; //creates a string literal value +var s2 = new String("2 + 2"); //creates a String object +eval(s1); //returns the number 4 +eval(s2); //returns the string "2 + 2"</pre> + +<p>A <code>String</code> object has one property, <code>length</code>, that indicates the number of characters in the string. For example, the following code assigns <code>x</code> the value 13, because "Hello, World!" has 13 characters:</p> + +<pre class="brush: js">var mystring = "Hello, World!"; +var x = mystring.length; +</pre> + +<p>A <code>String</code> object has two types of methods: those that return a variation on the string itself, such as <code>substring</code> and <code>toUpperCase</code>, and those that return an HTML-formatted version of the string, such as <code>bold</code> and <code>link</code>.</p> + +<p>For example, using the previous example, both <code>mystring.toUpperCase()</code> and <code>"hello, world!".toUpperCase()</code> return the string "HELLO, WORLD!"</p> + +<p>The <code>substring</code> method takes two arguments and returns a subset of the string between the two arguments. Using the previous example, <code>mystring.substring(4, 9)</code> returns the string "o, Wo". See the <a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/substring" title="en-US/docs/JavaScript/Reference/Global Objects/String/substring"><code>substring</code></a> method of the <code>String</code> object in the JavaScript Reference for more information.</p> + +<p>The <code>String</code> object also has a number of methods for automatic HTML formatting, such as <code>bold</code> to create boldface text and <code>link</code> to create a hyperlink. For example, you could create a hyperlink to a hypothetical URL with the <code>link</code> method as follows:</p> + +<pre class="brush: js">mystring.link("http://www.helloworld.com") +</pre> + +<p>The following table summarizes the methods of <code>String</code> objects.</p> + +<table class="fullwidth-table"> + <caption>Table 7.4 Methods of String Instances</caption> + <thead> + <tr> + <th scope="col">Method</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/anchor" title="en-US/docs/JavaScript/Reference/Global_Objects/String/anchor">anchor</a></code></td> + <td>Creates HTML named anchor.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/big" title="en-US/docs/JavaScript/Reference/Global_Objects/String/big">big</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/blink" title="en-US/docs/JavaScript/Reference/Global_Objects/String/blink">blink</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/bold" title="en-US/docs/JavaScript/Reference/Global_Objects/String/bold">bold</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/fixed" title="en-US/docs/JavaScript/Reference/Global_Objects/String/fixed">fixed</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/italics" title="en-US/docs/JavaScript/Reference/Global_Objects/String/italics">italics</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/small" title="en-US/docs/JavaScript/Reference/Global_Objects/String/small">small</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/strike" title="en-US/docs/JavaScript/Reference/Global_Objects/String/strike">strike</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/sub" title="en-US/docs/JavaScript/Reference/Global_Objects/String/sub">sub</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/sup" title="en-US/docs/JavaScript/Reference/Global_Objects/String/sup">sup</a></code></td> + <td>Create HTML formatted string.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/charAt" title="en-US/docs/JavaScript/Reference/Global_Objects/String/charAt">charAt</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/charCodeAt" title="en-US/docs/JavaScript/Reference/Global_Objects/String/charCodeAt">charCodeAt</a></code></td> + <td>Return the character or character code at the specified position in string.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/indexOf" title="en-US/docs/JavaScript/Reference/Global_Objects/String/indexOf">indexOf</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/lastIndexOf" title="en-US/docs/JavaScript/Reference/Global_Objects/String/lastIndexOf">lastIndexOf</a></code></td> + <td>Return the position of specified substring in the string or last position of specified substring, respectively.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/link" title="en-US/docs/JavaScript/Reference/Global_Objects/String/link">link</a></code></td> + <td>Creates HTML hyperlink.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/concat" title="en-US/docs/JavaScript/Reference/Global_Objects/String/concat">concat</a></code></td> + <td>Combines the text of two strings and returns a new string.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/fromCharCode" title="en-US/docs/JavaScript/Reference/Global_Objects/String/fromCharCode">fromCharCode</a></code></td> + <td>Constructs a string from the specified sequence of Unicode values. This is a method of the String class, not a String instance.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/split" title="en-US/docs/JavaScript/Reference/Global_Objects/String/split">split</a></code></td> + <td>Splits a <code>String</code> object into an array of strings by separating the string into substrings.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/slice" title="en-US/docs/JavaScript/Reference/Global_Objects/String/slice">slice</a></code></td> + <td>Extracts a section of an string and returns a new string.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/substring" title="en-US/docs/JavaScript/Reference/Global_Objects/String/substring">substring</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/substr" title="en-US/docs/JavaScript/Reference/Global_Objects/String/substr">substr</a></code></td> + <td>Return the specified subset of the string, either by specifying the start and end indexes or the start index and a length.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/match" title="en-US/docs/JavaScript/Reference/Global_Objects/String/match">match</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/replace" title="en-US/docs/JavaScript/Reference/Global_Objects/String/replace">replace</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/search" title="en-US/docs/JavaScript/Reference/Global_Objects/String/search">search</a></code></td> + <td>Work with regular expressions.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/toLowerCase" title="en-US/docs/JavaScript/Reference/Global_Objects/String/toLowerCase">toLowerCase</a></code>, <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/toUpperCase" title="en-US/docs/JavaScript/Reference/Global_Objects/String/toUpperCase">toUpperCase</a></code></td> + <td> + <p>Return the string in all lowercase or all uppercase, respectively.</p> + </td> + </tr> + </tbody> +</table> + +<p>autoPreviousNext("JSGChapters")</p> diff --git a/files/ru/web/javascript/guide/regular_expressions/assertions/index.html b/files/ru/web/javascript/guide/regular_expressions/assertions/index.html new file mode 100644 index 0000000000..2d04ed19aa --- /dev/null +++ b/files/ru/web/javascript/guide/regular_expressions/assertions/index.html @@ -0,0 +1,60 @@ +--- +title: Assertions +slug: Web/JavaScript/Guide/Regular_Expressions/Assertions +translation_of: Web/JavaScript/Guide/Regular_Expressions/Assertions +--- +<p>{{jsSidebar("JavaScript Guide")}}{{draft}}</p> + +<p>Проверка (assertion) задает возможность совпадения одним из указанных способов. Проверка может содержать условные выражения, опережающие (look-ahead) и ретроспективные (look-behind) проверки.</p> + +<h2 id="Типы">Типы</h2> + +<div class="blockIndicator note"> +<p>Символ <code>?</code> также может быть использован как обычный квантификатор.</p> +</div> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Выражение</th> + <th scope="col">Что означает</th> + </tr> + </thead> + <tbody> + <tr> + <td>x(?=y)</td> + <td> + <p><strong>Опережающая проверка: </strong><code><em>x</em></code> подходит только когда за <code><em>x</em></code> следует <code><em>y</em></code>. Например, /<code>Jack(?=Sprat)/</code> сработает для "Jack" только когда за ним будет "Sprat".<br> + <code>/Jack(?=Sprat|Frost)/</code> подойдет для "Jack" только когда за ним будет "Sprat" или "Frost". Следует заметить, что ни "Sprat" ни "Frost" не будут выданы как часть проверки.</p> + </td> + </tr> + <tr> + <td>x(?!y)</td> + <td> + <p><strong>Отрицательная опережающая проверка: </strong><code style="font-size: 1rem; letter-spacing: -0.00278rem;"><em>x</em></code><span style="font-size: 1rem; letter-spacing: -0.00278rem;"> подходит только когда за </span><code style="font-size: 1rem; letter-spacing: -0.00278rem;"><em>x</em></code><span style="font-size: 1rem; letter-spacing: -0.00278rem;"> не следует </span><code style="font-size: 1rem; letter-spacing: -0.00278rem;"><em>y</em></code><span style="font-size: 1rem; letter-spacing: -0.00278rem;">.</span> Например, <code style="font-size: 1rem; letter-spacing: -0.00278rem;">/\d+(?!\.)/</code><span style="font-size: 1rem; letter-spacing: -0.00278rem;"> сработает для числа в том случае, если за ним не стоит точка. Выполнение кода </span><code>/\d+(?!\.)/.exec('3.141')</code> выдаст только число "141", поскольку за "3" следует точка.</p> + </td> + </tr> + <tr> + <td>(?<=y)x</td> + <td> + <p><strong>Ретроспективная проверка: </strong><code style="font-size: 1rem; letter-spacing: -0.00278rem;"><em>x</em></code><span style="font-size: 1rem; letter-spacing: -0.00278rem;"> подходит только когда </span><code style="font-size: 1rem; letter-spacing: -0.00278rem;"><em>x</em></code><span style="font-size: 1rem; letter-spacing: -0.00278rem;"> предшествует </span><code style="font-size: 1rem; letter-spacing: -0.00278rem;"><em>y</em></code><span style="font-size: 1rem; letter-spacing: -0.00278rem;">.</span> Например, <code style="font-size: 1rem; letter-spacing: -0.00278rem;">/(?<=Jack)Sprat/</code><span style="font-size: 1rem; letter-spacing: -0.00278rem;"> сработает для "Sprat" только если перед ним есть "Jack". </span><code>/(?<=Jack|Tom)Sprat/</code> подойдет для "Sprat" если перед ним будут "Jack" или "Tom". Заметим, что ни "Jack" ни "Tom" не будут выданы.</p> + </td> + </tr> + <tr> + <td>(?<!y)x</td> + <td> + <p><strong>Отрицательная ретроспективная проверка: </strong><code style="font-size: 1rem; letter-spacing: -0.00278rem;"><em>x</em></code><span style="font-size: 1rem; letter-spacing: -0.00278rem;"> подходит только когда </span><code style="font-size: 1rem; letter-spacing: -0.00278rem;"><em>x</em></code><span style="font-size: 1rem; letter-spacing: -0.00278rem;"> не предшествует </span><code style="font-size: 1rem; letter-spacing: -0.00278rem;"><em>y</em></code><span style="font-size: 1rem; letter-spacing: -0.00278rem;">.</span> Например, <code style="font-size: 1rem; letter-spacing: -0.00278rem;">/(?<!-)\d+/</code><span style="font-size: 1rem; letter-spacing: -0.00278rem;"> сработает для числа в том случае, если перед ним не стоит знак минус. Выполнение кода </span><code>/(?<!-)\d+/.exec('3')</code> выдаст "3". Код <code>/(?<!-)\d+/.exec('-3')</code> ничего не найдет, т.к. перед числом есть знак минус.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Examples">Examples</h2> + +<p> </p> + +<h2 id="Browser_support">Browser support</h2> + +<p> </p> + +<h2 id="See_also">See also</h2> diff --git a/files/ru/web/javascript/guide/regular_expressions/character_classes/index.html b/files/ru/web/javascript/guide/regular_expressions/character_classes/index.html new file mode 100644 index 0000000000..08aa94b4c5 --- /dev/null +++ b/files/ru/web/javascript/guide/regular_expressions/character_classes/index.html @@ -0,0 +1,221 @@ +--- +title: Классы символов +slug: Web/JavaScript/Guide/Regular_Expressions/Character_Classes +tags: + - Guide + - JavaScript + - Reference + - RegExp + - Regular Expression + - character classes +translation_of: Web/JavaScript/Guide/Regular_Expressions/Character_Classes +--- +<p>{{JSSidebar("JavaScript Guide")}}</p> + +<p>Классы символов позволяют различать виды символов, к примеру, как различия между буквами и цифрами.</p> + +<div>{{EmbedInteractiveExample("pages/js/regexp-character-classes.html")}}</div> + +<h2 id="Типы">Типы</h2> + +<div class="hidden">The following table is also duplicated on <a href="/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Cheatsheet">this cheatsheet</a>. Do not forget to edit it as well, thanks!</div> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Символ</th> + <th scope="col">Значение</th> + </tr> + </thead> + <tbody> + </tbody> + <tbody> + <tr> + <td><code>.</code></td> + <td> + <p>Точка имеет одно из следеющих смыслов:</p> + + <ul> + <li>Сопадение с любым одним символом <em>за исключение</em> символовов завершения строки: <code>\n</code>, <code>\r</code>, <code>\u2028</code> or <code>\u2029</code>. Например, <code>/.y/</code> совпадает "my" с "ay", и не совпадает с "yes" и "yes make my day".</li> + <li>В набор символов, точка теряет свой специальный смысл и совпадает с литеральным символом точка.</li> + </ul> + + <p>Замечание. <code>m</code> флаг посика по множеству строк не меняет поведения точки. Чтобы найти воспадения во многострочном поиске можно использвать набор символов <code>[^]</code> — он сопадёт с любым символом включая символы заверешния строки.</p> + + <p>В ES2018 добавили <code>s</code> "dotAll" флаг, который ползволяет точке <code>(.</code>) находить все символы включая симполвы переноса строк.</p> + </td> + </tr> + <tr> + <td><code>\d</code></td> + <td> + <p>Совпадет с любой цифрой (арабский числа). Эквивалентно <code>[0-9]</code>. Например, <code>/\d/</code> или <code>/[0-9]/</code> находит "2" в "B2 is the suite number"..</p> + </td> + </tr> + <tr> + <td><code>\D</code></td> + <td> + <p>Совпадет с любым символом, который не является цифрой (арабский числа). Эквивалентно <code>[^0-9]</code>. Например, <code>/\D/</code> or <code>/[^0-9]/</code> находит "B" в "B2 is the suite number".</p> + </td> + </tr> + <tr> + <td><code>\w</code></td> + <td> + <p>Совпадет с любой бувенно-числовым симпволом из базового латинского алфавита включая нижнее подчёркивание. Эквивалентно <code>[A-Za-z0-9_]</code>. Например, <code>/\w/</code> находит "a" в "apple", "5" в "$5.28", "3" в "3D" и "m" в "Émanuel".</p> + </td> + </tr> + <tr> + <td><code>\W</code></td> + <td> + <p>Совпадет с любой бувенно-числовым, которое не является симпволом базового латинского алфавита, так же исключая нижнее подчёркивание. Эквивалентно <code>[^A-Za-z0-9_]</code>. Например, <code>/\W/</code> или <code>/[^A-Za-z0-9_]/</code> находит "%" в "50%" и "É" in "Émanuel".</p> + </td> + </tr> + <tr> + <td><code>\s</code></td> + <td> + <p>Совпадет с любым пробельным символом, включая пробел, символ табуляции, символ подачи странцы, символ подачи строки и другие Unicode пробелы. Эквивалентно <code>[ \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]</code>. Например, <code>/\s\w*/</code> находит " bar" в "foo bar".</p> + </td> + </tr> + <tr> + <td><code>\S</code></td> + <td> + <p>Совпадет с любым симвовом, не являяющимся проблельным. Эквивалентно <code>[^ \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]</code>. Например, <code>/\S\w*/</code> находит "foo" в "foo bar".</p> + </td> + </tr> + <tr> + <td><code>\t</code></td> + <td>Совпадет с символом горизонтальной табуляции.</td> + </tr> + <tr> + <td><code>\r</code></td> + <td>Совпадет с символом возврата каретки.</td> + </tr> + <tr> + <td><code>\n</code></td> + <td>Совпадет с символом подачи строки.</td> + </tr> + <tr> + <td><code>\v</code></td> + <td>Совпадет с символом вертикальной табуляции</td> + </tr> + <tr> + <td><code>\f</code></td> + <td>Совпадет с символом подачи страницы (формы).</td> + </tr> + <tr> + <td><code>[\b]</code></td> + <td>Совпадет с символом возарат назад (англ. backspace). Если вы ищите символ границы слова (<code>\b</code>), смотри <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Boundaries">Границы</a>.</td> + </tr> + <tr> + <td><code>\0</code></td> + <td>Совпадет с символом NUL character. Не используйте другую цифру.</td> + </tr> + <tr> + <td><code>\c<em>X</em></code></td> + <td> + <p>Совпадет с котрольным символом using <a href="https://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D1%80%D0%B5%D1%82%D0%BD%D0%B0%D1%8F_%D0%BD%D0%BE%D1%82%D0%B0%D1%86%D0%B8%D1%8F">каретную нотацию</a>, где "X" быква A–Z (соответствует кодам <code>U+0001</code><em>–</em><code>U+001F</code>). For example, <code>/\cM/</code> matches "\r" in "\r\n".</p> + </td> + </tr> + <tr> + <td><code>\x<em>hh</em></code></td> + <td>Совпадет с символом, код которого <code><em>hh</em></code> (две шестнадцатеричных цифры).</td> + </tr> + <tr> + <td><code>\u<em>hhhh</em></code></td> + <td>Совпадет с код-блоком UTF-16 со значением <code><em>hhhh</em></code> (четыре шестнадцатеричных цифры).</td> + </tr> + <tr> + <td><code>\u<em>{hhhh} </em>or <em>\u{hhhhh}</em></code></td> + <td>(Только когда установлен фла <code>u</code>.) Совпадет с Unicode символом со значением <code>U+<em>hhhh</em></code> или <code>U+<em>hhhhh</em></code> (шестнадцатеричные цифры).</td> + </tr> + <tr> + <td><code>\</code></td> + <td> + <p>Определяет что последующий символ должен быть интерпретирован по особому или должен быть "экранирован. Это работает в двух вариантах:</p> + + <ul> + <li>Для символов, которые относятся к литералам, последующий символ - это специальный символ, который не должен быть интерпретирован, как литерал. Например, <code>/b/</code> совпадает с символом "b". Установ обратного слэша перед "b". Таким образом <code>/\b/</code>. Будет означать символ границы слова. </li> + <li>Для символов, которые относятся к специальным, определяет что это не специальным символ, а должен быть интерепретирован, как литерал. Например, <code>*</code> - это специальный символ, который означает 0 или любое другое совпадений предыдующего символа, Например <code>/a*/</code> совпадает с любым количестовм символов "a" идущих подряд (или 0 "a") <code>a, aaaa, aaaaaa</code>. Если специальный символ <code>*</code>, как литерал, то перед ним ставится обратных слэш. Например, <code>/a\*/</code> сопадает только с "a*".</li> + </ul> + + <div class="blockIndicator note"> + <p>Чтобы найти литеральное совпадение с этим символова (<code>\</code> , экранируйте его самим же. Другими словами для поиска <code>\</code> используйте <code>/\\/</code>.</p> + </div> + </td> + </tr> + </tbody> +</table> + +<h2 id="Примеры">Примеры</h2> + +<h3 id="Плиск_серии_цифр">Плиск серии цифр</h3> + +<pre class="brush: js notranslate">var randomData = "015 354 8787 687351 3512 8735"; +var regexpFourDigits = /\b\d{4}\b/g; +// \b определяет границу поиска (например, не начиает поиск с середины слова) +// \d{4} определяет цифру, четыре раза +// определяет другую границу поиска (например, не начиает поиск с середины слова) + +// Вывод всех числел имеющих только 4 цифры +console.table(randomData.match(regexpFourDigits)); +// ['8787', '3512', '8735'] +</pre> + +<h3 id="Поиск_слов_латинский_алфавит_начинающих_с_A">Поиск слов (латинский алфавит), начинающих с A</h3> + +<pre class="brush: js notranslate">var aliceExcerpt = "I’m sure I’m not Ada,’ she said, ‘for her hair goes in such long ringlets, and mine doesn’t go in ringlets at all."; +var regexpWordStartingWithA = /\b[aA]\w+/g; +// \b определяет границу поиска (например, не начиает поиск с середины слова) +// [aA] определяет букву a или A +// \b определяет границу поиска (например, не начиает поиск с середины слова) + +console.table(aliceExcerpt.match(regexpWordStartingWithA)); +// ['Ada', 'and', 'at', 'all'] +</pre> + +<h3 id="Поиски_слов_из_Unicode_символов">Поиски слов (из Unicode символов)</h3> + +<p>Вместо латинского алфавита, мы может использовать диапазаон Unicode символов для определения слова (благодаря этому мы можем работать с текстами написанным, например на русском или арабском языке or Arabic). Unicode содержит большинство символов используемых на планете, мы так же можем объединять их диапазоны и классы символов.</p> + +<pre class="brush: js notranslate">var nonEnglishText = "Приключения Алисы в Стране чудес"; +var regexpBMPWord = /([\u0000-\u0019\u0021-\uFFFF])+/gu; +// BMP goes through U+0000 to U+FFFF but space is U+0020 + +console.table(nonEnglishText.match(regexpBMPWord)); +[ 'Приключения', 'Алисы', 'в', 'Стране', 'чудес' ] +</pre> + +<div class="hidden"> +<p>Note for MDN editors: please do not try to add funny examples with emoji as those characters are not handled by the platform (Kuma).</p> +</div> + +<h2 id="Спецификации">Спецификации</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Спецификация</th> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-characterclass', 'RegExp: Character classes')}}</td> + </tr> + </tbody> +</table> + +<h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2> + +<p>Для информации о совместимости с браузерами, посмотрите <a href="/ru/docs/Web/JavaScript/Guide/Regular_Expressions#Browser_compatibility">основную таблицу совместимости Regular Expressions</a>.</p> + +<h2 id="Смотрите_по_теме">Смотрите по теме</h2> + +<ul> + <li><a href="/ru/docs/Web/JavaScript/Guide/Regular_Expressions">Руководство по Regular expressions</a> + + <ul> + <li><a href="/ru/docs/Web/JavaScript/Guide/Regular_Expressions/Assertions">Assertions</a></li> + <li><a href="/ru/docs/Web/JavaScript/Guide/Regular_Expressions/Quantifiers">Quantifiers</a></li> + <li><a href="/ru/docs/Web/JavaScript/Guide/Regular_Expressions/Unicode_Property_Escapes">Unicode property escapes</a></li> + <li><a href="/ru/docs/Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges">Groups and ranges</a></li> + </ul> + </li> + <li><a href="/ru/docs/Web/JavaScript/Reference/Global_Objects/RegExp">Конструктор <code>RegExp()</code></a></li> +</ul> diff --git a/files/ru/web/javascript/guide/regular_expressions/index.html b/files/ru/web/javascript/guide/regular_expressions/index.html new file mode 100644 index 0000000000..834df23a39 --- /dev/null +++ b/files/ru/web/javascript/guide/regular_expressions/index.html @@ -0,0 +1,659 @@ +--- +title: Регулярные выражения +slug: Web/JavaScript/Guide/Regular_Expressions +translation_of: Web/JavaScript/Guide/Regular_Expressions +--- +<p>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Text_formatting", "Web/JavaScript/Guide/Indexed_collections")}}</p> + +<p class="summary">Регулярные выражения - это шаблоны, используемые для сопоставления последовательностей символов в строках. В JavaScript регулярные выражения также являются объектами. Эти шаблоны используются в методах <a href="/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec" title="exec"><code>exec</code></a> и <a href="/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/test" title="test"><code>test</code></a> объекта<a href="/en-US/docs/JavaScript/Reference/Global_Objects/RegExp" title="RegExp"> <code>RegExp</code></a>, а также <a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/match" title="match"><code>match</code></a>, <a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/replace" title="en-US/docs/JavaScript/Reference/Global_Objects/String/replace"><code>replace</code></a>,<a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/search" title="search"> <code>search</code></a> и <a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/split" title="split"><code>split</code></a> объекта <a href="/en-US/docs/JavaScript/Reference/Global_Objects/String" title="String"><code>String</code></a>. Данная глава описывает регулярные выражения в JavaScript.</p> + +<h2 id="Создание_регулярного_выражения">Создание регулярного выражения</h2> + +<p>Регулярное выражение можно создать двумя способами:</p> + +<ul> + <li>Используя литерал регулярного выражения, например: + <div style="margin-right: 270px;"> + <pre class="brush: js notranslate">var re = /ab+c/; +</pre> + </div> + + <p>Литералы регулярных выражений вызывают предварительную компиляцию регулярного выражения при анализе скрипта. Если ваше регулярное выражение постоянно, то пользуйтесь им, чтобы увеличить производительность.</p> + </li> + <li>Вызывая функцию конструктор объекта <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/RegExp" title="en-US/docs/JavaScript/Reference/Global Objects/RegExp">RegExp</a></code>, например: + <div style="margin-right: 270px;"> + <pre class="brush: js notranslate">var re = new RegExp("ab+c"); +</pre> + </div> + + <p>Использование конструктора влечет за собой компиляцию регулярного выражения во время исполнения скрипта. Используйте данный способ, если знаете, что выражение будет изменяться или не знаете шаблон заранее. Например вы получаете его из стороннего источника, при пользовательском вводе.</p> + </li> +</ul> + +<h2 id="Написание_шаблона_регулярного_выражения">Написание шаблона регулярного выражения</h2> + +<p>Шаблон регулярного выражения состоит из обычных символов, например <code>/abc/</code>, или комбинаций обычных и специальных символов, например <code>/ab*c/</code> или <code>/Chapter (\d+)\.\d*/</code>. Последний пример включает в себя скобки, которые используются как "запоминающий механизм". Соответствие этой части шаблона запоминается для дальнейшего использования, как описано в {{ web.link("#Использование_скобочных_выражений_для_нахождения_подстрок", "Использование совпадений подстрок заключённых в скобки") }}.</p> + +<h3 id="Использование_простых_шаблонов">Использование простых шаблонов</h3> + +<p>Простые шаблоны используются для нахождения прямого соответствия в тексте. Например, шаблон <code>/abc/</code> соответствует комбинации символов в строке только когда символы 'abc' встречаются вместе и в том же порядке. Такое сопоставление произойдет в строке "Hi, do you know your abc's?" и "The latest airplane designs evolved from slabcraft." В обоих случаях сопоставление произойдет с подстрокой 'abc'. Сопоставление не произойдет в строке "Grab crab", потому что она не содержит подстроку 'abc'.</p> + +<h3 id="Использование_специальных_символов">Использование специальных символов</h3> + +<p>В случае когда поиск соответствия требует чего-то большего, чем прямое сопоставление, например нахождение последовательности символов 'b' или нахождение пробела, шаблон включает в себя специальные символы. Например, шаблон <code>/ab*c/</code> соответствует любой комбинации символов, в которой за 'a' следует ноль или более символов 'b' (<code>*</code> означает ноль или более вхождений предыдущего символа), за которыми сразу же следует символ 'c'. В строке "cbbabbbbcdebc," этому шаблону сопоставляется подстрока 'abbbbc'.</p> + +<p>В следующей таблице приводится полный список специальных символов регулярных выражений с их описаниями.</p> + +<table class="fullwidth-table"> + <caption>Таблица 4.1 Специальные символы в регулярных выражения.</caption> + <thead> + <tr> + <th scope="col">Символ</th> + <th scope="col">Значение</th> + </tr> + </thead> + <tbody> + <tr> + <td><a href="#special-backslash" id="special-backslash" name="special-backslash"><code>\</code></a></td> + <td>Одно из следующего: + <ul> + <li>Для символов обычно обрабатываемых буквально, означает что следующий символ является специальным и не должен интерпретироваться буквально.</li> + <li style="list-style-type: none;">Например, <code>/b/ </code>сопоставляется символу 'b'. Добавляя слэш перед b, т.е используя <code>/\b/</code>, символ становится специальным символом, означающим границу слова.</li> + <li>Для символов обычно обрабатываемых особым образом означает, что следующий символ не является специальным и должен интерпретироваться буквально.</li> + <li style="list-style-type: none;">Например, <code>*</code> является специальным символом, сопоставляемым 0 или более повторений предыдущего символа; например, <code>/a*/</code> означает соответствие 0 или более символов а. Для буквальной интерпретации *, поставьте перед ней обратный слэш; например, <code>/a\*/</code> соответствует 'a*'.</li> + <li style="list-style-type: none;">Также не забудьте заэкранировать сам \ при его использовании в записи new RegExp("pattern") поскольку \ также является экранирующим символом в обычных строках.</li> + </ul> + </td> + </tr> + <tr> + <td><a href="#special-caret" id="special-caret" name="special-caret"><code>^</code></a></td> + <td> + <p>Соответствует началу ввода. Если установлен флаг многострочности, также производит сопоставление непосредственно после переноса строки.</p> + + <p>Например, <code>/^A/</code> не соответствует 'A' в "an A", но соответствует 'A' в "An E".</p> + + <p><br> + Этот символ имеет другое значение при появлении в начале шаблона набора символов.</p> + + <p>Например, <code>/[^a-z\s]/</code> соответствует 'I' в "I have 3 sisters".</p> + </td> + </tr> + <tr> + <td><a href="#special-dollar" id="special-dollar" name="special-dollar"><code>$</code></a></td> + <td> + <p>Соответствует концу ввода. Если установлен битовый флаг многострочности, также сопоставляется содержимому до переноса строки.</p> + + <p>Например, <code>/t$/</code> не соответствует 't' в строке "eater", но соответствует строке "eat".</p> + </td> + </tr> + <tr> + <td><a href="#special-asterisk" id="special-asterisk" name="special-asterisk"><code>*</code></a></td> + <td> + <p>Соответствует предыдущему символу повторенному 0 или более раз. Эквивалентно {0,}.</p> + + <p>Например, <code>/bo*/</code> соответствует 'boooo' в "A ghost booooed" и 'b' в "A bird warbled", но не в "A goat grunted".</p> + </td> + </tr> + <tr> + <td><a href="#special-plus" id="special-plus" name="special-plus"><code>+</code></a></td> + <td> + <p>Соответствует предыдущему символу повторенному 1 или более раз. Эквивалентно {1,}.</p> + + <p>Например, <code>/a+/</code> соответствует 'a' в "candy" и всем символам 'a' в "caaaaaaandy".</p> + </td> + </tr> + <tr> + <td><a href="#special-questionmark" id="special-questionmark" name="special-questionmark"><code>?</code></a></td> + <td>Соответствует предыдущему символу повторенному + <p> 0 или 1 раз. Эквивалентно {0,1}.</p> + + <p>Например, <code>/e?le?/</code> соответствует 'el' в "angel" и 'le' в "angle" а также 'l' в "oslo".</p> + + <p>Если использован сразу после квалификаторов <code>*</code>, <code>+</code>, <code>?</code>, или <code>{}</code>, делает квалификатор "нежадным" (соответствующим минимальному количеству символов), в отличие от режима по умолчанию, являющимся "жадным" (соответствующим максимальному числу символов). Например, используя /\d+/ не глобальное сопоставление "123abc" возвращает "123", если использовать /\d+?/, только "1" будет возвращена.</p> + + <p>Также используется в упреждающих утверждениях (assertions), описанных в строках x(?=y) и x(?!y) данной таблицы.</p> + </td> + </tr> + <tr> + <td><a href="#special-dot" id="special-dot" name="special-dot"><code>.</code></a></td> + <td> + <p>(десятичная точка) соответствует любому символу кроме переноса строки.</p> + + <p>Например, <code>/.n/</code> соответствует 'an' и 'on' в "nay, an apple is on the tree", но не 'nay'.</p> + </td> + </tr> + <tr> + <td><a href="#special-capturing-parentheses" id="special-capturing-parentheses" name="special-capturing-parentheses"><code>(x)</code></a></td> + <td> + <p>Соответствует 'x' и запоминает это соответствие. Это называется захватывающие скобки.</p> + + <p>Например, <code>/(foo)/</code> соответствует 'foo' в "foo bar." Сопоставленная строка может быть получена из элементов результирующего массива <code>[1]</code>, ..., <code>[n]</code>.</p> + </td> + </tr> + <tr> + <td><a href="#special-non-capturing-parentheses" id="special-non-capturing-parentheses" name="special-non-capturing-parentheses"><code>(?:x)</code></a></td> + <td>Соответствует 'x' но не запоминает соответствие. Это называется не-захватывающие скобки. Сопоставленная строка не может быть получена из элементов результирующего массива <code style="font-size: 14px; color: rgb(51, 51, 51);">[1]</code>, ..., <code style="font-size: 14px; color: rgb(51, 51, 51);">[n]</code>.</td> + </tr> + <tr> + <td><a href="#special-lookahead" id="special-lookahead" name="special-lookahead"><code>x(?=y)</code></a></td> + <td> + <p>Соответствует 'x' только если за 'x' следует 'y'. Это называется упреждение.</p> + + <p>Например, <code>/Jack(?=Sprat)/</code> соответствует 'Jack' только если за ним следует 'Sprat'. <code>/Jack(?=Sprat|Frost)/</code> соответствует 'Jack' только если за ним следует 'Sprat' или 'Frost'. Тем не менее, ни 'Sprat' ни 'Frost' не являются частью сопоставленного результата.</p> + </td> + </tr> + <tr> + <td><a href="#special-negated-look-ahead" id="special-negated-look-ahead" name="special-negated-look-ahead"><code>x(?!y)</code></a></td> + <td> + <p>Соответствует 'x' только если за 'x' не следует 'y'. Это называется отрицательное упреждение.</p> + + <p>Например, <code>/\d+(?!\.)/</code> соответствует числу только если за ним не следует десятичная точка. Регулярное выражение <code>/\d+(?!\.)/.exec("3.141")</code> сопоставит '141' но не '3.141'.</p> + </td> + </tr> + <tr> + <td><a href="#special-or" id="special-or" name="special-or"><code>x|y</code></a></td> + <td> + <p>Соответствует либо 'x' либо 'y'.</p> + + <p>Например, <code>/green|red/</code> соответствует 'green' в "green apple" и 'red' в "red apple."</p> + </td> + </tr> + <tr> + <td><a href="#special-quantifier" id="special-quantifier" name="special-quantifier"><code>{n}</code></a></td> + <td> + <p>n - положительное целое. Соответствует ровно <code>n</code> вхождениям предыдущего символа.</p> + + <p>Например, <code>/a{2}/</code> не соответствует 'a' в "candy," но соответствует всем а в "caandy," первым двум а в "caaandy."</p> + </td> + </tr> + <tr> + <td><a href="#special-quantifier-range" id="special-quantifier-range" name="special-quantifier-range"><code>{n,m}</code></a></td> + <td> + <p>m и n - положительные целые. Соответствует как минимум <code>n</code> и максимум <code>m</code> вхождениям предыдущего символа. При m=n=1 пропускается.</p> + + <p>Например, <code>/a{1,3}/</code> ничему не соответствует в строке "cndy", символу 'a' в "candy," двум а в "caandy," и трем первым а в "caaaaaaandy". Отметим, что при сопоставлении "caaaaaaandy", совпадает "aaa", хотя изначальная строка содержит больше а.</p> + </td> + </tr> + <tr> + <td><a href="#special-character-set" id="special-character-set" name="special-character-set"><code>[xyz]</code></a></td> + <td> + <p>Набор символов. Соответствует любому символу из перечисленных. Можно указать диапазон символов, используя тире. Специальные символы (как точка (<code>.</code>) и звездочка (<code>*</code>)) не имеют специального значения внутри такого набора. Их не надо экранировать. Экранирование работает также.</p> + + <p>Например, <code>[abcd]</code> эквивалентна <span style="font-family: monospace;">[</span><code>a-d]</code>. Они соответствуют 'b' в "brisket" и 'c' в "city". <code>/[a-z.]+/</code> и <code>/[\w.]+/</code> обе соответствуют всему в "test.i.ng".</p> + </td> + </tr> + <tr> + <td><a href="#special-negated-character-set" id="special-negated-character-set" name="special-negated-character-set"><code>[^xyz]</code></a></td> + <td> + <p>Инвертированный или дополняющий набор символов. Это означает соответствие всему, что не в скобках. Можно указать диапазон символов с помощью тире. Все, что действует в обычном наборе символов, действует и здесь.</p> + + <p>Например, <code>[^abc]</code> эквивалентно <code>[^a-c]</code>. Они соответствуют изначально 'r' в "brisket" и 'h' в "chop."</p> + </td> + </tr> + <tr> + <td><a href="#special-backspace" id="special-backspace" name="special-backspace"><code>[\b]</code></a></td> + <td>Соответствует бэкспейсу (U+0008). (Не путать с <code>\b</code>.)</td> + </tr> + <tr> + <td><a href="#special-word-boundary" id="special-word-boundary" name="special-word-boundary"><code>\b</code></a></td> + <td> + <p>Соответствует границе слова. Граница слова соответствует позиции, где за символом слова не следует другой символ слова или предшествует ему. Отметим, что граница слова не включается в соответствие. Другими словами, длина сопоставленной границы слова равна нулю. (Не путать с <code>[\b]</code>.)</p> + + <p>Примеры:<br> + <code>/\bmoo/</code> соответствует 'moo' в слове "moon" ;<br> + <code>/oo\b/</code> не соответствует 'oo' в слове "moon", поскольку за 'oo' следует символ 'n' , являющимся символом слова;<br> + <code>/oon\b/</code> соответствует 'oon' в слове "moon", поскольку 'oon' является окончанием строки, и таким образом, за этими символами не следует другой символ слова;<br> + <code>/\w\b\w/</code> никогда не будет ничему соответствовать, поскольку за символом слова никогда не может следовать и граница слова, и символ слова.</p> + + <div class="note"> + <p><strong>Note:</strong> JavaScript's regular expression engine defines a <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-15.10.2.6">specific set of characters</a>to be "word" characters. Any character not in that set is considered a word break. This set of characters is fairly limited: it consists solely of the Roman alphabet in both upper- and lower-case, decimal digits, and the underscore character. Accented characters, such as "é" or "ü" are, unfortunately, treated as word breaks.</p> + </div> + </td> + </tr> + <tr> + <td><a href="#special-non-word-boundary" id="special-non-word-boundary" name="special-non-word-boundary"><code>\B</code></a></td> + <td> + <p>Соответствует несловообразующей границе. Несловообразующая граница соответствует позиции, в которой предыдущий и следующий символы являются символами одного типа: либо оба должны быть словообразующими символами, либо несловообразующими. Начало и конец строки считаются несловообразующими символами. </p> + + <p>Например, <code>/\B../</code> соответствует 'oo' в слове "noonday" (, а <code>/y\B./</code> соответствует 'ye' в "possibly yesterday."</p> + </td> + </tr> + <tr> + <td><a href="#special-control" id="special-control" name="special-control"><code>\c<em>X</em></code></a></td> + <td> + <p>Где <em>X</em> является символом случайного выбора из последовательности от А до Я. Соответствует управляющему символу в строке.</p> + + <p>Например, <code>/\cM/</code> соответствует control-M (U+000D) в строке.</p> + </td> + </tr> + <tr> + <td><a href="#special-digit" id="special-digit" name="special-digit"><code>\d</code></a></td> + <td> + <p>Соответствует цифровому символу. Эквивалентно выражению <code>[0-9]</code>.</p> + + <p>Например, <code>/\d/</code> or <code>/[0-9]/</code> соотвествует '2' в "B2 is the suite number."</p> + </td> + </tr> + <tr> + <td><a href="#special-non-digit" id="special-non-digit" name="special-non-digit"><code>\D</code></a></td> + <td> + <p>Соответствует любому нецифровому символу. Эквивалентно выражению <code>[^0-9]</code>.</p> + + <p>Например, <code>/\D/</code> or <code>/[^0-9]/</code> соответствует 'B' в предложении "B2 is the suite number."</p> + </td> + </tr> + <tr> + <td><a href="#special-form-feed" id="special-form-feed" name="special-form-feed"><code>\f</code></a></td> + <td> + <p>Соответствует символу прогона страницы (U+000C). Особый символ управления печатью.</p> + </td> + </tr> + <tr> + <td><a href="#special-line-feed" id="special-line-feed" name="special-line-feed"><code>\n</code></a></td> + <td>Соответствует символу перевода строки (U+000A).</td> + </tr> + <tr> + <td><a href="#special-carriage-return" id="special-carriage-return" name="special-carriage-return"><code>\r</code></a></td> + <td>Соответствует символу возврата каретки (U+000D).</td> + </tr> + <tr> + <td><a href="#special-white-space" id="special-white-space" name="special-white-space"><code>\s</code></a></td> + <td> + <p>Соответствует одиночному символу пустого пространства, включая пробел, табуляция, прогон страницы, перевод строки. Эквивалентен <code>[ \f\n\r\t\v\u00A0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u2028\u2029\u202f\u205f\u3000]</code>.</p> + + <p>Например, <code>/\s\w*/</code> совпадает с ' bar' в "foo bar."</p> + </td> + </tr> + <tr> + <td><a href="#special-non-white-space" id="special-non-white-space" name="special-non-white-space"><code>\S</code></a></td> + <td> + <p>Соответствует одиночному символу непустого пространства. Эквивалентен<code> [^ \f\n\r\t\v\u00A0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]</code>.</p> + + <p>Например, <code>/\S\w*/</code> совпадает с 'foo' в "foo bar."</p> + </td> + </tr> + <tr> + <td><a href="#special-tab" id="special-tab" name="special-tab"><code>\t</code></a></td> + <td>Соответствует символу горизонтальной табуляции (U+0009).</td> + </tr> + <tr> + <td><a href="#special-vertical-tab" id="special-vertical-tab" name="special-vertical-tab"><code>\v</code></a></td> + <td>Соответствует символу вертикальной табуляции (U+000B).</td> + </tr> + <tr> + <td><a href="#special-word" id="special-word" name="special-word"><code>\w</code></a></td> + <td> + <p>Соответствует любому цифробуквенному символу включая нижнее подчеркивание. Эквивалентен <code>[A-Za-z0-9_]</code>.</p> + + <p>Например, <code>/\w/</code> совпадает с 'a' в "apple," '5' в "$5.28," и '3' в "3D."</p> + </td> + </tr> + <tr> + <td><a href="#special-non-word" id="special-non-word" name="special-non-word"><code>\W</code></a></td> + <td> + <p>Соответствует любому не цифробуквенному символу. Равносилен<code> [^A-Za-z0-9_]</code>.</p> + + <p>Например, <code>/\W/</code> or <code>/[^A-Za-z0-9_]/</code> совпадает с '%' в "50%."</p> + </td> + </tr> + <tr> + <td><a href="#special-backreference" id="special-backreference" name="special-backreference"><code>\<em>n</em></code></a></td> + <td> + <p>Где <em>n</em> это положительное целое, обратная ссылка на последнюю найденную подстроку, соответствующую <em>n</em> , заключенную в круглые скобки в регуляном выражении (считая левые скобки).</p> + + <p>Например, <code>/apple(,)\sorange\1/</code> соответствует 'apple, orange,' в "apple, orange, cherry, peach."</p> + </td> + </tr> + <tr> + <td><a href="#special-null" id="special-null" name="special-null"><code>\0</code></a></td> + <td>Соответствует символу NULL (U+0000). Не следует ставить за ним другой цифровой символ, поскольку <code>\0<digits></code> является восьмеричной экранирующей последовательностью.</td> + </tr> + <tr> + <td><a href="#special-hex-escape" id="special-hex-escape" name="special-hex-escape"><code>\xhh</code></a></td> + <td>Соответствует символам кода hh (две шестнадцатиричные цифры)</td> + </tr> + <tr> + <td><a href="#special-unicode-escape" id="special-unicode-escape" name="special-unicode-escape"><code>\uhhhh</code></a></td> + <td>Соответствует символам кода hhhh (четыре шестнадцатиричные цифры).</td> + </tr> + </tbody> +</table> + +<p>Экранирование пользовательского ввода, соответствующего буквенной строке внутри регулярного выражения, может быть достигнуто простой заменой: </p> + +<pre class="brush: js notranslate"><code>function escapeRegExp(string){ + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +}</code></pre> + +<h3 id="Использование_скобок">Использование скобок</h3> + +<p>Скобки вокруг любой части регулярного выражения означают что эта часть совпадаемой подстроки будет запомнена. Раз запомнена, подстрока может выбрана для использования как это описано в {{ web.link("#Using_Parenthesized_Substring_Matches", "Using Parenthesized Substring Matches") }}.</p> + +<p>Например, паттерн <code>/Chapter (\d+)\.\d*/</code> включает в себя дополнительные экранирующие и специальные символы и указывает на то, что часть шаблона должна быть запомнена. Он точно соответствует символам слова 'Chapter ', за которыми следует один или более цифровых символов (<code>\d</code> означает любой цифровой символ, а '<code>+'</code> означает 1 или более раз), за которым следует десятичная точка (сама по себе являющаяся специальным символом; предшествующий десятичной точке слэш ' \' означает, что паттерн должен искать литеральный символ '.'), после которой следует любой цифровой символ 0 или более раз ('<code>\d'</code> обозначает цифровой символ, '<code>*'</code> обозначает 0 или более раз). Кроме того, круглые скобки используются для запоминания первых же совпавших цифровых символов. </p> + +<p>Этот шаблон будет найден во фразе "Open Chapter 4.3, paragraph 6" и цифра '4' будет запомнена. Но он не будет найден во фразе "Chapter 3 and 4", поскольку эта строка не имеет точки после цифры '3'.</p> + +<p>Для того, чтобы сопоставить подстроку без вызова совпавшей части для запоминания, внутри круглых скобок необходимо предварить паттерн сочетанием символов ' <code>?:'</code>. Например, шаблон <code>(?:\d+)</code> будет соответствовать одному или более цифровому символу, но не запомнит совпавших символов. </p> + +<h2 id="Работа_с_Регулярными_Выражениями">Работа с Регулярными Выражениями</h2> + +<p>Регулярные выражения используются в методах <code>test</code> и <code>exec</code> объекта <code>RegExp</code> и с методами <code>match</code>, <code>replace</code>, <code>search</code>, и <code>split </code>объекта <code>String</code>. Эти методы подробно объясняются в <a href="/en-US/docs/JavaScript/Reference" title="en-US/docs/JavaScript/Reference">Справочнике JavaScript</a>.</p> + +<table class="standard-table"> + <caption>Table 4.2 Методы пользующиеся регулярными выражениями</caption> + <thead> + <tr> + <th scope="col">Метод</th> + <th scope="col">Описание</th> + </tr> + </thead> + <tbody> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec" title="en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec">exec</a></code></td> + <td>Метод <code>RegExp,</code> который выполняет поиск совпадения в строке. Он возвращает массив данных.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/test" title="en-US/docs/JavaScript/Reference/Global_Objects/RegExp/test">test</a></code></td> + <td>Метод <code>RegExp</code>, который тестирует совпадение в строке. Возвращет либо истину либо ложь.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/match" title="en-US/docs/JavaScript/Reference/Global_Objects/String/match">match</a></code></td> + <td>Метод <code>String</code>, который выполняет поиск совпадения в строке. Он возвращет массив данных либо null если совпадения отсутствуют.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/search" title="en-US/docs/JavaScript/Reference/Global_Objects/String/search">search</a></code></td> + <td>Метод <code>String,</code> который тестирует на совпадение в строке. Он возвращет индекс совпадения, или -1 если совпадений не будет найдено.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/replace" title="en-US/docs/JavaScript/Reference/Global_Objects/String/replace">replace</a></code></td> + <td>Метод <code>String</code>, который выполняет поиск совпадения в строке, и заменяет совпавшую подстроку другой подстрокой переданной как аргумент в этот метод.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/split" title="en-US/docs/JavaScript/Reference/Global_Objects/String/split">split</a></code></td> + <td>Метод <code>String,</code> который использует регулярное выражение или фиксированую строку чтобы разбить строку на массив подстрок.</td> + </tr> + </tbody> +</table> + +<p>Чтобы просто узнать есть ли в строке что либо соотвествующее шаблону, воспользуйтесь методами <code>test</code> или <code>search</code>; а чтобы получить больше информации пользуйтесь методами <code>exec</code> или <code>match</code> (хотя эти метода работают медленее). Если вы пользуютесь <code>exec</code> или <code>match</code> и если совпадения есть, эти методы вернут массив и обновленные свойства объекта ассоцированного регулярного выражения а также предопределенного объекта <code>RegExp </code>регулярного выражения. Если совпадений нет, метод <code>exec</code> вернет <code>null</code> (который сконвертируется в <code>false</code>).</p> + +<p>В след. примере, скрипт использует метод <code>exec</code> чтобы найти совпадения в строке.</p> + +<pre class="brush: js notranslate">var myRe = /d(b+)d/g; +var myArray = myRe.exec("cdbbdbsbz"); +</pre> + +<p>Если вам не нужен доступ к свойствам регулярного выражения, то альтернативный способ получить <code>myArray</code> можно так:</p> + +<pre class="brush: js notranslate">var myArray = /d(b+)d/g.exec("cdbbdbsbz"); +</pre> + +<p>Если вы хотите сконструировать регулярное выражение из строки, другой способ сделать это приведен ниже:</p> + +<pre class="brush: js notranslate">var myRe = new RegExp("d(b+)d", "g"); +var myArray = myRe.exec("cdbbdbsbz"); +</pre> + +<p>С помощью этих скриптов, поиск совпадения завершается и возвращает массив и обновленные ствойства показанные в след. таблице.</p> + +<table class="fullwidth-table"> + <caption>Table 4.3 Результаты выполнения регулярного выражения</caption> + <thead> + <tr> + <th scope="col">Объект</th> + <th scope="col">Свойство или индекс</th> + <th scope="col">Описание</th> + <th scope="col">В этом примере.</th> + </tr> + </thead> + <tbody> + <tr> + <td rowspan="4"><code>myArray</code></td> + <td></td> + <td>Совпавшая строка и все запомненные подстроки.</td> + <td><code>["dbbd", "bb"]</code></td> + </tr> + <tr> + <td><code>index</code></td> + <td>Индекс совпавшей подстроки (индекс начинается с нуля).</td> + <td><code>1</code></td> + </tr> + <tr> + <td><code>input</code></td> + <td>Исходная строка.</td> + <td><code>"cdbbdbsbz"</code></td> + </tr> + <tr> + <td><code>[0]</code></td> + <td>Последние совпавшие символы.</td> + <td><code>"dbbd"</code></td> + </tr> + <tr> + <td rowspan="2"><code>myRe</code></td> + <td><code>lastIndex</code></td> + <td>Индекс с которого начнется след. поиск совпадения. (Это свойство определяется только если регулярное выражение использует параметр g, описанный в {{ web.link("#Advanced_Searching_With_Flags", "Advanced Searching With Flags") }}.)</td> + <td><code>5</code></td> + </tr> + <tr> + <td><code>source</code></td> + <td>Текст шаблона. Обновляется в момент создания регулярного выражения, а не во время выполнения.</td> + <td><code>"d(b+)d"</code></td> + </tr> + </tbody> +</table> + +<p>Как показано во втором варианте этого примера, вы можете использовать регулярное выражение, созданное при помощи инициализатора объекта, без присваивания его переменной. Таким образом, если вы используете данную форму записи без присваивания переменной, то в процессе дальнейшего использования вы не можете получить доступ к свойствам данного регулярного выражения. Например, у вас есть следующий скрипт:</p> + +<pre class="brush: js notranslate">var myRe = /d(b+)d/g; +var myArray = myRe.exec("cdbbdbsbz"); +console.log("The value of lastIndex is " + myRe.lastIndex); +</pre> + +<p>Этот скрипт выведет:</p> + +<pre class="notranslate">The value of lastIndex is 5 +</pre> + +<p>Однако, если у вас есть следующий скрипт:</p> + +<pre class="brush: js notranslate">var myArray = /d(b+)d/g.exec("cdbbdbsbz"); +console.log("The value of lastIndex is " + /d(b+)d/g.lastIndex); +</pre> + +<p>Он выведет:</p> + +<pre class="notranslate">The value of lastIndex is 0 +</pre> + +<div class="syntaxbox">Совпадения <code>/d(b+)d/g</code> в двух случаях являются разными объектами регулярного выражения и, следовательно, имеют различные значения для свойства <code>lastIndex</code>. Если вам необходим доступ к свойствам объекта, созданного при помощи инициализатора, то вы должны сначала присвоить его переменной.</div> + +<div class="syntaxbox"></div> + +<h3 id="Использование_скобочных_выражений_для_нахождения_подстрок">Использование скобочных выражений для нахождения подстрок</h3> + +<p>Использование скобок в шаблоне регулярного выражения повлечет "запоминание" совпавшей подстроки. Для примера, <code>/a(b)c/</code> вызовет совпадение 'abc' и запомнит 'b'. Чтобы получить совпадения скобочного выражения используйте <code>Array</code> elements <code>[1]</code>, ..., <code>[n]</code>.</p> + +<p>Число возможных скобочных подстрок неограничено. Возвращаемый массив содержит все полученные совпадения, удовлетворяющие выражению в скобках. Следующий пример показывает как использовать скобочные выражения для нахождения подстрок.</p> + +<p>Следующий скрипт использует метод <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String/replace" title="en-US/docs/JavaScript/Reference/Global Objects/String/replace">replace()</a>,</code> чтобы поменять местами слова (символы) в строке. Для замены текста скрипт использует обозначения <code>$1</code> и <code>$2</code> для обозначения первого и второго совпадения скобочного выражения.</p> + +<pre class="brush: js notranslate">var re = /(\w+)\s(\w+)/; +var str = "John Smith"; +var newstr = str.replace(re, "$2, $1"); +console.log(newstr); +</pre> + +<p>Выведет "Smith, John".</p> + +<h3 id="Расширенный_поиск_с_флагами">Расширенный поиск с флагами</h3> + +<p>Регулярные выражения имеют четыре опциональных флага, которые делают возможным глобальный и регистронезависимый поиск. Флаги могут использоваться самостоятельно или вместе в любом порядке, а также могут являтся частью регулярного выражения.</p> + +<table style="line-height: 1.5;"> + <caption>Флаги регулярных выражений</caption> + <thead> + <tr> + <th scope="col">Flag</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>g</code></td> + <td>Глобальный поиск.</td> + </tr> + <tr> + <td>i</td> + <td>Регистронезависимый поиск.</td> + </tr> + <tr> + <td>m</td> + <td>Многострочный поиск.</td> + </tr> + <tr> + <td>y</td> + <td>Выполняет поиск начиная с символа, который находится на позиции свойства lastindex текущего регулярного выражения.</td> + </tr> + </tbody> +</table> + +<p>Чтобы использовать флаги в шаблоне регулярного выражения используйте следующий синтаксис:</p> + +<pre class="brush: js notranslate">var re = /pattern/flags; +</pre> + +<p>или</p> + +<pre class="brush: js notranslate">var re = new RegExp("pattern", "flags"); +</pre> + +<p>Обратите внимание, что флаги являются неотъемлемой частью регулярного выражения. Флаги не могут быть добавлены или удалены позднее.</p> + +<p>Для примера, <code>re = /\w+\s/g</code> создаёт регулярное выражение, которое ищет один или более символов, после котрых следует пробел и ищет данное совпадение на протяжении всей строки.</p> + +<pre class="brush: js notranslate">var re = /\w+\s/g; +var str = "fee fi fo fum"; +var myArray = str.match(re); +console.log(myArray); +</pre> + +<p>Выведет ["fee ", "fi ", "fo "]. В этом примере вы бы могли заменить строку:</p> + +<pre class="brush: js notranslate">var re = /\w+\s/g; +</pre> + +<p>на следующую:</p> + +<pre class="brush: js notranslate">var re = new RegExp("\\w+\\s", "g"); +</pre> + +<p>и получить тот же результат.</p> + +<p>Флаг <code>m</code> используется, чтобы входная строка рассматривалась как многострочная. Если флаг <code>m</code> используется, то <code>^</code> и <code>$</code> вызовет совпадение в начале или конце любой строки в строке ввода вместо начала или конца вводимой строки целиком.</p> + +<h2 id="Примеры">Примеры</h2> + +<p>След. примеры показывают использование регулярных выражений.</p> + +<h3 id="Изменение_порядка_в_Исходной_Строке">Изменение порядка в Исходной Строке</h3> + +<p>След. пример иллюстрирует формирование регулярного выражения и использование <code>string.split()</code> и <code>string.replace()</code>. Он очищает неправильно сформатированную исходную строку, которая содержит имена в неправильном порядке (имя идет первым) разделенные пробелами, табуляцией и одной точкой с запятой. В конце, изменяется порядок следования имен (фамилия станет первой) и сортируется список.</p> + +<pre class="brush: js notranslate">// The name string contains multiple spaces and tabs, +// and may have multiple spaces between first and last names. +var names = "Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand "; + +var output = ["---------- Original String\n", names + "\n"]; + +// Prepare two regular expression patterns and array storage. +// Split the string into array elements. + +// pattern: possible white space then semicolon then possible white space +var pattern = /\s*;\s*/; + +// Break the string into pieces separated by the pattern above and +// store the pieces in an array called nameList +var nameList = names.split(pattern); + +// new pattern: one or more characters then spaces then characters. +// Use parentheses to "memorize" portions of the pattern. +// The memorized portions are referred to later. +pattern = /(\w+)\s+(\w+)/; + +// New array for holding names being processed. +var bySurnameList = []; + +// Display the name array and populate the new array +// with comma-separated names, last first. +// +// The replace method removes anything matching the pattern +// and replaces it with the memorized string—second memorized portion +// followed by comma space followed by first memorized portion. +// +// The variables $1 and $2 refer to the portions +// memorized while matching the pattern. + +output.push("---------- After Split by Regular Expression"); + +var i, len; +for (i = 0, len = nameList.length; i < len; i++){ + output.push(nameList[i]); + bySurnameList[i] = nameList[i].replace(pattern, "$2, $1"); +} + +// Display the new array. +output.push("---------- Names Reversed"); +for (i = 0, len = bySurnameList.length; i < len; i++){ + output.push(bySurnameList[i]); +} + +// Sort by last name, then display the sorted array. +bySurnameList.sort(); +output.push("---------- Sorted"); +for (i = 0, len = bySurnameList.length; i < len; i++){ + output.push(bySurnameList[i]); +} + +output.push("---------- End"); + +console.log(output.join("\n")); +</pre> + +<h3 id="Использование_спецсимволов_для_проверки_входных_данных">Использование спецсимволов для проверки входных данных</h3> + +<p>В след. примере, ожидается что пользователь введет телефонный номер и требуется проверить правильность символов набранных пользователем. Когда пользователь нажмет кнопку "Check", скрипт проверит правильность введеного номера. Если номер правильный (совпадает с символами определенными в регулярном выражении), то скрипт покажет сообщение благодарности для пользователя и подтвердит номер. Если нет, то скрипт проинформирует пользователя, что телефонный номер неправильный.</p> + +<p>Внутри незахватывающих скобок <code>(?:, регуляное выражение ищет три цифры \d{3} ИЛИ |</code> открывающую скобку <code>\(, затем три цифры \d{3}</code>, затем закрывающую скобку <code>\), </code>(закрывающая незахватывающая скобка <code>)</code>), затем тире, слэш, или десятичная точка, и когда это выражение найдено, запоминает символ <code>([-\/\.])</code>, следующие за ним и запомненные три цифры <code>\d{3}</code>, следующее соответствие тире, слэша или десятичной точки <code>\1</code>, и следующие четыре цифры <code>\d{4}.</code></p> + +<p>Регулярное выражение ищет сначала 0 или одну открывающую скобку <code>\(?</code>, <code>затем три цифры \d{3}</code>, затем 0 или одну закрывающую скобку <code>\)?</code>, потом одно тире, слеш или точка и когда найдет это, запомнит символ<code>([-\/\.])</code>, след. три цифры<code> \d{3}</code>, followed by the remembered match of a dash, forward slash, or decimal point <code>\1</code>, followed by four digits <code>\d{4}</code>.</p> + +<p>Событие "Изменить" активируется, когда пользователь подтвердит ввод значения регулярного выражения, нажав клавишу "Enter". </p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + <meta http-equiv="Content-Script-Type" content="text/javascript"> + <script type="text/javascript"> + var re = /\(?\d{3}\)?([-\/\.])\d{3}\1\d{4}/; + function testInfo(phoneInput){ + var OK = re.exec(phoneInput.value); + if (!OK) + window.alert(RegExp.input + " isn't a phone number with area code!"); + else + window.alert("Thanks, your phone number is " + OK[0]); + } + </script> + </head> + <body> + <p>Enter your phone number (with area code) and then click "Check". + <br>The expected format is like ###-###-####.</p> + <form action="#"> + <input id="phone"><button onclick="testInfo(document.getElementById('phone'));">Check</button> + </form> + </body> +</html> +</pre> + +<pre class="script notranslate">autoPreviousNext("JSGChapters"); +</pre> diff --git a/files/ru/web/javascript/guide/text_formatting/index.html b/files/ru/web/javascript/guide/text_formatting/index.html new file mode 100644 index 0000000000..4316e2402a --- /dev/null +++ b/files/ru/web/javascript/guide/text_formatting/index.html @@ -0,0 +1,281 @@ +--- +title: Форматирование текста +slug: Web/JavaScript/Guide/Text_formatting +tags: + - JavaScript + - Руководство +translation_of: Web/JavaScript/Guide/Text_formatting +--- +<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Numbers_and_dates", "Web/JavaScript/Guide/Regular_Expressions")}}</div> + +<p class="summary">В этой главе приводится порядок работы со строками и текстом в JavaScript.</p> + +<h2 id="Строки">Строки</h2> + +<p>Строки используются для представления текстовых данных. Каждая строка - это набор "элементов", а каждый элемент - 16 битное беззнаковое целое значение. Элементы имеют определённые позиции. Так первый элемент имеет индекс 0, следущий - 1, и так далее. Длина строки - это количество элементов в ней. Вы можете создать строки, используя строковые литералы или объекты класса String.</p> + +<h3 id="Строковые_литералы">Строковые литералы</h3> + +<p>Вы можете создавать простые строки, используя либо одинарные, либо двойные кавычки:</p> + +<pre class="brush: js">'foo' +"bar"</pre> + +<p>Начиная со стандарта ES6 (ES-2015) для простых и сложных строк можно использовать обратные косые кавычки, а также, вставлять значения:</p> + +<pre>const name = "Alex"; +const str = + `Привет, ${name}, + как дела?`; + +console.log(str); +// Привет, Alex, +// как дела? +</pre> + +<p>Подробнее про использование обратных косых кавычек (` `), <a href="/ru/docs/Web/JavaScript/Guide/Text_formatting#Многострочные_шаблонные_строки">читайте ниже</a>.</p> + +<p>Строки с более богатым содержимым <span><span class="article-text">можно создать с помощью ESC-последовательностей</span></span><span><span class="comment">(комбинация символов, обычно используемая для задания неотображаемых символов и символов, имеющих специальное значение)</span></span>:</p> + +<h4 id="Шестнадцатиричные_экранированные_последовательности">Шестнадцатиричные экранированные последовательности</h4> + +<p>Число после \x трактуется как <a href="https://en.wikipedia.org/wiki/Hexadecimal">шестнадцатиричное.</a></p> + +<pre class="brush: js">'\xA9' // "©" +</pre> + +<h4 id="Unicode_экранированные_последовательности">Unicode экранированные последовательности</h4> + +<p>Экранированные последовательности Unicode требуют по меньшей мере 4 символа после <code>\u</code>.</p> + +<pre class="brush: js">'\u00A9' // "©"</pre> + +<h4 id="Экранирование_элементов_кода_Unicode">Экранирование элементов кода Unicode</h4> + +<p>Нововведение ECMAScript 6, которое позволяет экранировать каждый Unicode символ, используя шестнадцатиричные значения (вплоть до <code>0x10FFFF</code>). С простым экранированием Unicode обычно требуется писать связанные друг с другом части по - отдельности для получения того же результата.</p> + +<p>Смотрите также {{jsxref("String.fromCodePoint()")}} или {{jsxref("String.prototype.codePointAt()")}}.</p> + +<pre class="brush: js">'\u{2F804}' + +// То же самое с простым Unicode +'\uD87E\uDC04'</pre> + +<h3 id="Объекты_String">Объекты String</h3> + +<p>Объект <code>{{jsxref("String")}}</code> - это обёртка вокруг примитивного строкового типа данных.</p> + +<pre class="brush: js">var s = new String("foo"); // Создание объекта +console.log(s); // Отобразится: { '0': 'f', '1': 'o', '2': 'o'} +typeof s; // Вернет 'object' +</pre> + +<p>Вы можете вызвать любой метод объекта класса <code>String</code> на строковом литерале - JavaScript сам преобразует строковый литерал во временный объект <code>String</code>, вызовет требуемый метод и затем уничтожит этот временный объект. Со строковыми литералами вы также можете использовать и <code>String.length</code> свойство.</p> + +<p>Следует использовать строковые литералы до тех пор, пока вам действительно не обойтись без <code>String</code> объекта, потому что, порой, объект String может вести себя неожиданно (не так, как строковый литерал). Например:</p> + +<pre class="brush: js">var s1 = "2 + 2"; // Создание строкового литерала +var s2 = new String("2 + 2"); // Создание String объекта +eval(s1); // Вернет 4 +eval(s2); // Вернет строку "2 + 2"</pre> + +<p>Объект <code>String</code> имеет свойство <code>length</code>, которое обозначает количество символов в строке. Например, в следующем коде x получит значение 13 потому, что "Hello, World!" содержит 13 символов, каждый из которых представлен одним кодом UTF-16. Вы можете обратиться к каждому коду с помощью квадратных скобок. Вы не можете изменять отдельные символы строки, т.к. строки это массиво-подобные неизменяемые объекты:</p> + +<pre class="brush: js">var mystring = "Hello, World!"; +var x = mystring.length; +mystring[0] = 'L'; // Ничего не произойдет, т.к. строки неизменяемые +mystring[0]; // Вернет: "H" +</pre> + +<p>Объект <code>String</code> имеет множество методов, в том числе и те, которые возвращают преобразованную исходную строку (методы <code>substring</code>, <code>toUpperCase</code> и другие).</p> + +<p>В таблице ниже представлены методы String объекта.</p> + +<table class="standard-table"> + <caption> + <h4 id="Методы_String">Методы <code>String</code></h4> + </caption> + <thead> + <tr> + <th scope="col">Метод</th> + <th scope="col">Описание</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{jsxref("String.charAt", "charAt")}}, {{jsxref("String.charCodeAt", "charCodeAt")}}, {{jsxref("String.codePointAt", "codePointAt")}}</td> + <td>Возвращает символ или символьный код в указанной позиции в строке.</td> + </tr> + <tr> + <td>{{jsxref("String.indexOf", "indexOf")}}, {{jsxref("String.lastIndexOf", "lastIndexOf")}}</td> + <td>Возвращает первую (indexOf) или последнюю (lastIndexOf) позицию указанной подстроки в строке. Если данная подстрока не найдена, то возвращает -1.</td> + </tr> + <tr> + <td>{{jsxref("String.startsWith", "startsWith")}}, {{jsxref("String.endsWith", "endsWith")}}, {{jsxref("String.includes", "includes")}}</td> + <td>Проверяет, начинается/кончается/содержит ли строка указанную подстроку.</td> + </tr> + <tr> + <td>{{jsxref("String.concat", "concat")}}</td> + <td>Объединяет две строки и возвращает результат в качестве новой строки.</td> + </tr> + <tr> + <td>{{jsxref("String.fromCharCode", "fromCharCode")}}, {{jsxref("String.fromCodePoint", "fromCodePoint")}}</td> + <td>Создает строку из указанной последовательности Unicode значений. Это метод класса String, а не отдельного экземпляра этого класса.</td> + </tr> + <tr> + <td>{{jsxref("String.split", "split")}}</td> + <td>Разбивает строку на подстроки, результат возвращает в виде массива строк.</td> + </tr> + <tr> + <td>{{jsxref("String.slice", "slice")}}</td> + <td>Извлекает часть строки и возвращает её в качестве новой строки.</td> + </tr> + <tr> + <td>{{jsxref("String.substring", "substring")}}, {{jsxref("String.substr", "substr")}}</td> + <td> + <p>Возвращет указанную часть строки по начальному и конечному индексам, либо по начальному индексу и длине.</p> + </td> + </tr> + <tr> + <td>{{jsxref("String.match", "match")}}, {{jsxref("String.replace", "replace")}}, {{jsxref("String.search", "search")}}</td> + <td>Работа с регулярными выражениями.</td> + </tr> + <tr> + <td>{{jsxref("String.toLowerCase", "toLowerCase")}}, {{jsxref("String.toUpperCase", "toUpperCase")}}</td> + <td> + <p>Возвращает строку полностью в нижнем (toLowerCase) или верхнем (toUpperCase) регистре.</p> + </td> + </tr> + <tr> + <td>{{jsxref("String.normalize", "normalize")}}</td> + <td>Возвращает нормализованную Unicode форму строки - значения объекта String, на котором вызывается.</td> + </tr> + <tr> + <td>{{jsxref("String.repeat", "repeat")}}</td> + <td> + <p>Возвращает строку, которая представляет собой повторение исходной строки указанное количество раз.</p> + </td> + </tr> + <tr> + <td>{{jsxref("String.trim", "trim")}}</td> + <td> + <p>Убирает пробелы в начале и в конце строки, результат возвращается в качестве новой строки.</p> + </td> + </tr> + </tbody> +</table> + +<h3 id="Многострочные_шаблонные_строки">Многострочные шаблонные строки</h3> + +<p><a href="/en-US/docs/Web/JavaScript/Reference/template_strings">Шаблонные строки</a> представляют собой строковые литералы, которые могут содержать внутри себя встроенные выражения. С ними вы можете использовать многострочные строковые литералы и интерполяцию строк.</p> + +<p>Такого типа строки заключаются в пару обратных штрихов (` `) (<a class="external external-icon" href="https://en.wikipedia.org/wiki/Grave_accent">grave accent</a>) вместо двойных или одинарных кавычек. Шаблонные строки могут содержать заполнители, которые выделяются знаком доллара и фигурными скобками (<code>${выражение}</code>).</p> + +<h4 id="Многострочная_запись">Многострочная запись</h4> + +<p>Каждая новая горизонтальная линия символов, вставленная в исходный код, является частью шаблонной строки. Используя обычные строки, вам бы потребовалось использовать следующий синтаксис для многострочной записи:</p> + +<pre class="brush: js">console.log("string text line 1\n\ +string text line 2"); +// "string text line 1 +// string text line 2"</pre> + +<p>Того же результата можно добиться и другим способом (используя синтаксис шаблонных строк):</p> + +<pre class="brush: js">console.log(`string text line 1 +string text line 2`); +// "string text line 1 +// string text line 2"</pre> + +<h4 id="Встроенные_выражения">Встроенные выражения</h4> + +<p>Для того, чтобы добавить выражения внутрь обычных строк, вы бы использовали следующий синтаксис:</p> + +<pre class="brush: js">var a = 5; +var b = 10; +console.log("Fifteen is " + (a + b) + " and\nnot " + (2 * a + b) + "."); +// "Fifteen is 15 and +// not 20."</pre> + +<p>Теперь же, используя шаблонные строки, вы можете сделать это так:</p> + +<pre class="brush: js">var a = 5; +var b = 10; +console.log(`Fifteen is ${a + b} and\nnot ${2 * a + b}.`); +// "Fifteen is 15 and +// not 20."</pre> + +<p>Для более подробной информации смотри <a href="/en-US/docs/Web/JavaScript/Reference/template_strings">Шаблонные строки</a> в <a href="/en-US/docs/Web/JavaScript/Reference">справочнике по JavaScript</a>.</p> + +<h2 id="Интернационализация">Интернационализация</h2> + +<p>Объект {{jsxref("Intl")}} представляет собой пространство имен для ECMAScript API по интернационализации, которое обеспечивает чувствительное к языку сравнение строк, форматирование чисел, времени и даты. Конструкторы для объектов {{jsxref("Collator")}}, {{jsxref("NumberFormat")}} и {{jsxref("DateTimeFormat")}} являются свойствами <code>объекта Intl</code>.</p> + +<h3 id="Форматирование_времени_и_даты">Форматирование времени и даты</h3> + +<p>Объект {{jsxref("DateTimeFormat")}} полезен для форматирования времени и даты. В примере ниже дата форматируется так, как это принято в США (результат отличен для разных временных зон).</p> + +<pre class="brush: js">var msPerDay = 24 * 60 * 60 * 1000; + +// July 17, 2014 00:00:00 UTC. +var july172014 = new Date(msPerDay * (44 * 365 + 11 + 197)); + +var options = { year: "2-digit", month: "2-digit", day: "2-digit", + hour: "2-digit", minute: "2-digit", timeZoneName: "short" }; +var americanDateTime = new Intl.DateTimeFormat("en-US", options).format; + +console.log(americanDateTime(july172014)); // 07/16/14, 5:00 PM PDT +</pre> + +<h3 id="Форматирование_чисел">Форматирование чисел</h3> + +<p>Объект {{jsxref("NumberFormat")}} полезен при форматировании чисел, например, валют.</p> + +<pre class="brush: js">var gasPrice = new Intl.NumberFormat("en-US", + { style: "currency", currency: "USD", + minimumFractionDigits: 3 }); + +console.log(gasPrice.format(5.259)); // $5.259 + +var hanDecimalRMBInChina = new Intl.NumberFormat("zh-CN-u-nu-hanidec", + { style: "currency", currency: "CNY" }); + +console.log(hanDecimalRMBInChina.format(1314.25)); // ¥ 一,三一四.二五 +</pre> + +<h3 id="Сравнение">Сравнение</h3> + +<p>Объект {{jsxref("Collator")}} полезен для сравнения и сортировки строк.</p> + +<p>Например, в Германии есть два различных порядка сортировки строк в зависимости от документа: телефонная книга или словарь.<em> </em>Сортировка по типу телефонной книги подчеркивает звуки.</p> + +<pre class="brush: js">var names = ["Hochberg", "Hönigswald", "Holzman"]; + +var germanPhonebook = new Intl.Collator("de-DE-u-co-phonebk"); + +// as if sorting ["Hochberg", "Hoenigswald", "Holzman"]: +console.log(names.sort(germanPhonebook.compare).join(", ")); +// logs "Hochberg, Hönigswald, Holzman" +</pre> + +<p>Примером по сортировке для словаря слов на немецком языке служит следующий код:</p> + +<pre class="brush: js">var germanDictionary = new Intl.Collator("de-DE-u-co-dict"); + +// as if sorting ["Hochberg", "Honigswald", "Holzman"]: +console.log(names.sort(germanDictionary.compare).join(", ")); +// logs "Hochberg, Holzman, Hönigswald" +</pre> + +<p>Для более подробной информации об {{jsxref("Intl")}} API смотри <a href="https://hacks.mozilla.org/2014/12/introducing-the-javascript-internationalization-api/">Introducing the JavaScript Internationalization API</a>.</p> + +<h2 id="Регулярные_выражения">Регулярные выражения</h2> + +<p>Регулярные выражения - это шаблоны, которые используются для описания некоторого множества строк . Это очень мощный и в некоторый степени непростой механизм, и поэтому ему посвящена отдельная глава. Узнать больше о регулярных выражениях можно здесь:</p> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Regular_Expressions">Регулярные выражения JavaScript</a> в руководстве по JavaScript.</li> + <li>{{jsxref("RegExp")}} ссылка в документации.</li> +</ul> + +<div>{{PreviousNext("Web/JavaScript/Guide/Numbers_and_dates", "Web/JavaScript/Guide/Regular_Expressions")}}</div> diff --git a/files/ru/web/javascript/guide/working_with_objects/index.html b/files/ru/web/javascript/guide/working_with_objects/index.html new file mode 100644 index 0000000000..34da02e599 --- /dev/null +++ b/files/ru/web/javascript/guide/working_with_objects/index.html @@ -0,0 +1,492 @@ +--- +title: Работа с объектами +slug: Web/JavaScript/Guide/Working_with_Objects +translation_of: Web/JavaScript/Guide/Working_with_Objects +--- +<p>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Keyed_collections", "Web/JavaScript/Guide/Details_of_the_Object_Model")}}</p> + +<p class="summary">JavaScript спроектирован на основе простой парадигмы. В основе концепции лежат простые объекты. Объект <span style="line-height: 1.5;">—</span> это набор свойств, и каждое свойство состоит из имени и значения, ассоциированного с этим именем. Значением свойства может быть функция, которую можно назвать <em>методом</em> объекта. В дополнение к встроенным в браузер объектам, вы можете определить свои собственные объекты. Эта глава описывает как пользоваться объектами, свойствами, функциями и методами, а также как создавать свои собственные объекты.</p> + +<h2 id="Обзор_объектов">Обзор объектов</h2> + +<p>Объекты в JavaScript, как и во многих других языках программирования, похожи на объекты реальной жизни. Концепцию объектов JavaScript легче понять, проводя паралелли с реально существующими в жизни объектами.</p> + +<p>В JavaScript объект — это самостоятельная единица, имеющая свойства и определенный тип. Сравним, например, с чашкой. У чашки есть цвет, форма, вес, материал, из которого она сделана, и т.д. Точно так же, объекты JavaScript имеют свойства, которые определяют их характеристики.</p> + +<h2 id="Объекты_и_свойства">Объекты и свойства</h2> + +<p>В JavaScript объект имеет свойства, ассоциированные с ним. Свойство объекта можно понимать как переменную, закрепленную за объектом. Свойства объекта в сущности являются теми же самыми переменными JavaScript, за тем исключением, что они закреплены за объектом. Свойства объекта определяют его характеристики. Получить доступ к свойству объекта можно с помощью точечной записи:</p> + +<div style="margin-right: 270px;"> +<pre class="brush: js">objectName.propertyName +</pre> +</div> + +<p>Как и все переменные JavaScript, имя объекта (которое тоже может быть переменной) и имя свойства являются чуствительными к регистру. Вы можете определить свойство указав его значение. Например, давайте создадим объект <code>myCar</code> и определим его свойства <code>make</code>, <code>model</code>, и <code>year</code> следующим образом:</p> + +<pre class="brush: js">var myCar = new Object(); +myCar.make = "Ford"; +myCar.model = "Mustang"; +myCar.year = 1969; +</pre> + +<p>Неопределенные свойства объекта являются {{jsxref("undefined")}} (а не {{jsxref("null")}}).</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js">myCar<span class="punctuation token">.</span>color<span class="punctuation token">;</span> <span class="comment token">// undefined</span></code></pre> + +<p>Свойства объектов JavaScript также могут быть доступны или заданы с использованием скобочной записи (более подробно см. <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Property_Accessors">property accessors</a>). Объекты иногда называются <em>ассоциативными массивами</em>, поскольку каждое свойство связано со строковым значением, которое можно использовать для доступа к нему. Так, например, вы можете получить доступ к свойствам объекта <code>myCar </code>следующим образом:</p> + +<pre class="brush: js">myCar["make"] = "Ford"; +myCar["model"] = "Mustang"; +myCar["year"] = 1969; +</pre> + +<p>Имена свойств объекта могут быть строками JavaScript, или тем, что может быть сконвертировано в строку, включая пустую строку. Как бы то ни было, доступ к любому имени свойства, которое содержит невалидный JavaScript идентификатор (например, имя свойства содержит в себе пробел и тире или начинается с цифры), может быть получен с использованием квадратных скобок. Этот способ записи также полезен, когда имена свойств должны быть динамически определены (когда имя свойства не определено до момента исполнения). Примеры далее:</p> + +<pre class="brush: js">var myObj = new Object(), + str = "myString", + rand = Math.random(), + obj = new Object(); + +myObj.type = "Dot syntax"; +myObj["date created"] = "String with space"; +myObj[str] = "String value"; +myObj[rand] = "Random Number"; +myObj[obj] = "Object"; +myObj[""] = "Even an empty string"; + +console.log(myObj); +</pre> + +<p>Обратите внимание, что все ключи с квадратными скобками преобразуются в тип String, поскольку объекты в JavaScript могут иметь в качестве ключа только тип String. Например, в приведенном выше коде, когда ключ <code>obj</code> добавляется в <code>myObj</code>, JavaScript вызывает метод <code>obj.toString ()</code> и использует эту результирующую строку в качестве нового ключа.</p> + +<p>Вы также можете получить доступ к свойствам, используя значение строки, которое хранится в переменной:</p> + +<div style="width: auto;"> +<pre class="brush: js">var propertyName = "make"; +myCar[propertyName] = "Ford"; + +propertyName = "model"; +myCar[propertyName] = "Mustang"; +</pre> +</div> + +<p>Вы можете пользоваться квадратными скобками в конструкции <a class="internal" href="/ru/docs/JavaScript/Guide/Statements#for...in_Statement" title="ru/docs/JavaScript/Guide/Statements#for...in Statement">for...in</a> чтобы выполнить итерацию всех свойств объекта, для которых она разрешена. Чтобы показать как это работает, следующая функция показывает все свойства объекта, когда вы передаете в нее сам объект и его имя как аргументы функции:</p> + +<pre class="brush: js">function showProps(obj, objName) { + var result = ""; + for (var i in obj) { + if (obj.hasOwnProperty(i)) { + result += objName + "." + i + " = " + obj[i] + "\n"; + } + } + return result; +} +</pre> + +<p>Так что если вызвать эту функцию вот так <code>showProps(myCar, "myCar"),</code> то получим результат:</p> + +<pre class="brush: js">myCar.make = Ford +myCar.model = Mustang +myCar.year = 1969</pre> + +<h2 id="Перечисление_всех_свойств_объекта">Перечисление всех свойств объекта</h2> + +<p>Начиная с <a href="/ru/docs/JavaScript/ECMAScript_5_support_in_Mozilla" title="ru/docs/JavaScript/ECMAScript 5 support in Mozilla">ECMAScript 5</a>, есть три способа перечислить все свойства объекта (получить их список):</p> + +<ul> + <li>циклы <a href="/ru/docs/JavaScript/Reference/Statements/for...in" title="/ru/docs/JavaScript/Reference/Statements/for...in">for...in </a><br> + Этот метод перебирает все перечисляемые свойства объекта и его цепочку прототипов</li> + <li><a href="/ru/docs/JavaScript/Reference/Global_Objects/Object/keys" title="ru/docs/JavaScript/Reference/Global Objects/Object/keys">Object.keys(o)</a><br> + Этот метод возвращает массив со всеми собственными (те, что в цепочке прототипов, не войдут в массив) именами перечисляемых свойств объекта <code>o</code>.</li> + <li><a href="/ru/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames" title="ru/docs/JavaScript/Reference/Global Objects/Object/getOwnPropertyNames">Object.getOwnPropertyNames(o)</a><br> + Этот метод возвращает массив содержащий все имена своих свойств (перечисляемых и неперечисляемых) объекта <code>o</code>.</li> +</ul> + +<p>До ECMAScript 5 не было встроенного способа перечислить все свойства объекта. Однако это можно сделать с помощью следующей функции:</p> + +<pre class="brush: js">function listAllProperties(o){ + var objectToInspect; + var result = []; + + for(objectToInspect = o; objectToInspect !== null; objectToInspect = Object.getPrototypeOf(objectToInspect)){ + result = result.concat(Object.getOwnPropertyNames(objectToInspect)); + } + + return result; +} +</pre> + +<p>Это может быть полезно для обнаружения скрытых (hidden) свойств (свойства в цепочке прототипа, которые недоступны через объект, в случае, если другое свойство имеет такое же имя в предыдущем звене из цепочки прототипа). Перечислить доступные свойства можно, если удалить дубликаты из массива.</p> + +<h2 id="Создание_новых_объектов">Создание новых объектов</h2> + +<p>JavaScript содержит набор встроенных объектов. Также вы можете создавать свои объекты. Начиная с JavaScript 1.2, вы можете создавать объект с помощью инициализатора объекта. Другой способ <span style="line-height: 1.5;">—</span> создать функцию-конструктор и сделать экземпляр объекта с помощью этой функции и оператора <code>new</code>.</p> + +<h3 id="Использование_инициализаторов_объекта">Использование инициализаторов объекта</h3> + +<p>Помимо создания объектов с помощью функции-конструктора вы можете создавать объекты и другим, особым способом. Фактически, вы можете записать объект синтаксически, и он будет создан интерпретатором автоматически во время выполнения. Эта синтаксическая схема приведена ниже:</p> + +<pre class="brush: js">var obj = { property_1: value_1, // property_# may be an identifier... + 2: value_2, // or a number... + // ..., + "property n": value_n }; // or a string +</pre> + +<p>здесь <code>obj</code> <span style="line-height: 1.5;">—</span> это имя нового объекта, каждое <code>property_i</code> <span style="line-height: 1.5;">—</span> это идентификатор (имя, число или строковый литерал), и каждый <code>value_i</code> <span style="line-height: 1.5;">—</span> это значения, назначенные <em><code>property_i</code></em>. Имя <code>obj</code> и ссылка объекта на него необязательна; если далее вам не надо будет ссылаться на данный объект, то вам не обязательно назначать объект переменной. (Обратите внимание, что вам потребуется обернуть литерал объекта в скобки, если объект находится в месте, где ожидается инструкция, чтобы интерпретатор не перепутал его с блоком.)</p> + +<p>Если объект создан при помощи инициализатора объектов на высшем уровне скрипта, то JavaScript интерпретирует объект каждый раз, когда анализирует выражение, содержащее объект, записанный как литерал. Плюс, если пользоваться функцией инициализатором, то он будет создаваться каждый раз, когда функция вызывается.</p> + +<p>Следующая инструкция создает объект и назначает его переменной <code>x</code>, когда выражение <code>cond</code> истинно.</p> + +<pre class="brush: js">if (cond) var x = {hi: "there"}; +</pre> + +<p>Следующий пример создает объект <code>myHonda</code> с тремя свойствами. Заметьте, что свойство <code>engine</code> <span style="line-height: 1.5;">—</span> это также объект со своими собственными свойствами.</p> + +<pre class="brush: js">var myHonda = { + color: "red", + wheels: 4, + engine: { + cylinders: 4, + size: 2.2 + } +}; +</pre> + +<p>Вы также можете использовать инициализатор объекта для создания массивов. Смотрите {{ web.link("Values%2C_variables%2C_and_literals#Array_literals", "array literals") }}.</p> + +<p>До JavaScript 1.1 не было возможности пользоваться инициализаторами объекта. Единственный способ создавать объекты <span style="line-height: 1.5;">—</span> это пользоваться функциями-конструкторами или функциями других объектов, предназначенных для этой цели. Смотрите {{ anch("Using a constructor function") }}.</p> + +<h3 id="Использование_функции_конструктора">Использование функции конструктора</h3> + +<p>Другой способ создать объект в два шага описан ниже:</p> + +<ol> + <li>Определите тип объекта, написав функцию-конструктор. Название такой функции, как правило, начинается с заглавной буквы.</li> + <li>Создайте экземпляр объекта с помощью ключевого слова <code>new</code>.</li> +</ol> + +<p>Чтобы определить тип объекта создайте функцию, которая определяет тип объекта, его имя, свойства и методы. Например предположим, что вы хотите создать тип объекта для описания машин. Вы хотите, чтобы объект этого типа назывался <code>car</code>, и вы хотите, чтобы у него были свойства make, model, и year. Чтобы сделать это, напишите следующую функцию:</p> + +<pre class="brush: js">function Car(make, model, year) { + this.make = make; + this.model = model; + this.year = year; +} +</pre> + +<p>Заметьте, что используется <code>this</code> чтобы присвоить значения (переданные как аргументы функции) свойствам объекта.</p> + +<p>Теперь вы можете создать объект, называемый <code>mycar</code>, следующим образом:</p> + +<pre class="brush: js">var mycar = new Car("Eagle", "Talon TSi", 1993); +</pre> + +<p>Эта инструкция создает объект типа Car со ссылкой <code>mycar</code> и присваивает определенные значения его свойствам. Значением <code>mycar.make </code>станет строка "Eagle", <code>mycar.year</code> <span style="line-height: 1.5;">—</span> это целое число 1993, и так далее.</p> + +<p>Вы можете создать столько объектов <code>car,</code> сколько нужно, просто вызывая <code>new</code>. Например:</p> + +<pre class="brush: js">var kenscar = new Car("Nissan", "300ZX", 1992); +var vpgscar = new Car("Mazda", "Miata", 1990); +</pre> + +<p>Объект может иметь свойство, которое будет другим объектом. Например, далее определяется объект типа <code>Person</code> следующим образом:</p> + +<pre class="brush: js">function Person(name, age, sex) { + this.name = name; + this.age = age; + this.sex = sex; +} +</pre> + +<p>и затем создать два новых экземпляра объектов <code>Person</code> как показано далее:</p> + +<pre class="brush: js">var rand = new Person("Rand McKinnon", 33, "M"); +var ken = new Person("Ken Jones", 39, "M"); +</pre> + +<p>Затем, вы можете переписать определение <code>car</code> и включить в него свойство <code>owner</code>, которому назначить объект <code>person</code> следующим образом:</p> + +<pre class="brush: js">function Car(make, model, year, owner) { + this.make = make; + this.model = model; + this.year = year; + this.owner = owner; +} +</pre> + +<p>Затем, чтобы создать экземпляры новых объектов, выполните следующие инструкции:</p> + +<pre class="brush: js">var car1 = new Car("Eagle", "Talon TSi", 1993, rand); +var car2 = new Car("Nissan", "300ZX", 1992, ken); +</pre> + +<p>Заметьте, что вместо того, чтобы передавать строку, литерал или целое число при создании новых объектов, в выражениях выше передаются объекты <code>rand</code> и <code>ken</code> как аргумент функции. Теперь, если вам нужно узнать имя владельца car2, это можно сделать следующим образом:</p> + +<pre class="brush: js">car2.owner +</pre> + +<p>Заметьте, что в любое время вы можете добавить новое свойство ранее созданному объекту. Например, выражение</p> + +<pre class="brush: js">car1.color = "black"; +</pre> + +<p>добавляет свойство <code>color</code> к car1, и устанавливаего его значение равным "black." Как бы там ни было, это не влияет на любые другие объекты. Чтобы добавить новое свойство всем объектам одного типа, вы должны добавить свойство в определение типа объекта <code>car</code>.</p> + +<h3 id="Использование_метода_Object.create">Использование метода Object.create</h3> + +<p>Объекты также можно создавать с помощью метода <code>Object.create</code>. Этот метод очень удобен, так как позволяет вам указывать объект прототип для нового вашего объекта без определения функции конструктора.</p> + +<pre class="brush: js">// список свойств и методов для Animal +var Animal = { + type: 'Invertebrates', // Значение type по умолчанию + displayType: function() { // Метод отображающий тип объекта Animal + console.log(this.type); + } +}; + +// Создаем объект Animal +var animal1 = Object.create(Animal); +animal1.displayType(); // Выведет:Invertebrates + +// Создаем объект Animal и присваиваем ему type = Fishes +var fish = Object.create(Animal); +fish.type = 'Fishes'; +fish.displayType(); // Выведет:Fishes</pre> + +<h2 id="Наследование">Наследование</h2> + +<p>Все объекты в JavaScript наследуются как минимум от другого объекта. Объект, от которого произошло наследование называется прототипом, и унаследованные свойства могут быть найдены в объекте <code>prototype</code> конструктора.</p> + +<h2 id="Индексы_свойств_объекта">Индексы свойств объекта</h2> + +<p>В JavaScript 1.0 вы можете сослаться на свойства объекта либо по его имени, либо по его порядковому индексу. В JavaScript 1.1 и позже, если вы изначально определили свойство по имени, вы всегда должны ссылаться на него по его имени, и если вы изначально определили свойство по индексу, то должны ссылаться на него по его индексу.</p> + +<p>Это ограничение налагается когда вы создаете объект и его свойства с помощью функции конструктора (как мы это делали ранее с типом <em>Car </em>) и когда вы определяете индивидуальные свойства явно (например, <code>myCar.color = "red"</code>). Если вы изначально определили свойство объекта через индекс, например <code>myCar[5] = "25 mpg"</code>, то впоследствии сослаться на это свойство можно только так <code>myCar[5]</code>.</p> + +<p>Исключение из правил <span style="line-height: 1.5;">—</span> объекты, отображаемые из HTML, например массив<code> forms</code>. Вы всегда можете сослаться на объекты в этих массивах или используя их индекс (который основывается на порядке появления в HTML документе), или по их именам (если таковые были определены). Например, если второй html-тег <code><FORM></code> в документе имеет значение аттрибута <code>NAME</code> равное "myForm", вы можете сослаться на эту форму вот так: <code>document.forms[1]</code> или <code>document.forms["myForm"]</code> или <code>document.myForm</code>.</p> + +<h2 id="Определение_свойств_для_типа_объекта">Определение свойств для типа объекта</h2> + +<p>Вы можете добавить свойство к ранее определенному типу объекта воспользовавшись специальным свойством <code>prototype</code>. Через <code>prototype</code> создается свойство, единое для всех объектов данного типа, а не одного экземпляра этого типа объекта. Следующий код демонстрирует это, добавляя свойство <code>color</code> ко всем объектам типа <code>car</code>, а затем присваивая значение свойству <code>color</code> объекта<code> car1</code>.</p> + +<pre class="brush: js">Car.prototype.color = null; +car1.color = "black"; +</pre> + +<p>Смотрите <a href="/ru/docs/JavaScript/Reference/Global_Objects/Function/prototype" title="ru/docs/JavaScript/Reference/Global Objects/Function/prototype"><code>свойство prototype</code></a> объекта <code>Function</code> в <a href="/ru/docs/JavaScript/Reference" title="ru/docs/JavaScript/Reference">Справочнике JavaScript </a>для получения деталей.</p> + +<h2 id="Определение_методов">Определение методов</h2> + +<p><em>Метод</em> <span style="line-height: 1.5;">—</span> это функция, ассоциированная с объектом или, проще говоря, метод <span style="line-height: 1.5;">—</span> это свойство объекта, являющееся функцией. Методы определяются так же, как и обычные функции, за тем исключением, что они присваиваются свойству объекта. Например вот так:</p> + +<pre class="brush: js">objectName.methodname = function_name; + +var myObj = { + myMethod: function(params) { + // ...do something + } +}; +</pre> + +<p>где <code>objectName</code> <span style="line-height: 1.5;">— </span>это существующий объект, <code>methodname</code> <span style="line-height: 1.5;">— </span>это имя, которое вы присваиваете методу, и <code>function_name</code> <span style="line-height: 1.5;">—</span> это имя самой функции.</p> + +<p>Затем вы можете вызвать метод в контексте объекта следующим образом:</p> + +<pre class="brush: js">object.methodname(params); +</pre> + +<p>Вы можете определять методы для типа объекта, включая определение метода в функцию конструктора объекта. Например, вы можете определить функцию, которая форматирует и отображает свойства до этого определенных объектов <code>car</code>. Например,</p> + +<pre class="brush: js">function displayCar() { + var result = "A Beautiful " + this.year + " " + this.make + + " " + this.model; + pretty_print(result); +} +</pre> + +<p>где <code>pretty_print</code> <span style="line-height: 1.5;">—</span> это функция отображения горизонтальной линии и строки. Заметьте, что использование <code>this</code> позволяет ссылаться на объект, которому принадлежит метод.</p> + +<p>Вы можете сделать эту функцию методом <code>car,</code> добавив инструкцию</p> + +<pre class="brush: js">this.displayCar = displayCar; +</pre> + +<p>к определению объекта. Таким образом, полное определение <code>car</code> примет следующий вид:</p> + +<pre class="brush: js">function Car(make, model, year, owner) { + this.make = make; + this.model = model; + this.year = year; + this.owner = owner; + this.displayCar = displayCar; +} +</pre> + +<p>Теперь вы можете вызвать метод <code>displayCar</code> для каждого из объектов как показано ниже:</p> + +<pre class="brush: js">car1.displayCar(); +car2.displayCar(); +</pre> + +<h2 id="Использование_this_для_ссылки_на_объект">Использование <code>this</code> для ссылки на объект</h2> + +<p>В JavaScript есть специальное ключевое слово this, которое вы можете использовать внутри метода, чтобы ссылаться на текущий объект. Предположим, у вас есть функция validate, которая сверяет свойство value, переданного ей объекта с некоторыми верхним и нижним значениями:</p> + +<pre class="brush: js">function validate(obj, lowval, hival) { + if ((obj.value < lowval) || (obj.value > hival)) + alert("Invalid Value!"); +} +</pre> + +<p>Вы можете вызвать эту функцию <code>validate</code> в каждом элементе формы, в обработчике события <code>onchange</code>. Используйте <code>this</code> для доступа к этому элементу, как это сделано ниже:</p> + +<pre class="brush: html"><input type="text" name="age" size="3" + onChange="validate(this, 18, 99)"> +</pre> + +<p>В общем случае, <code>this</code> ссылается на объект, вызвавший метод.</p> + +<p>Через <code>this</code> можно обратиться и к родительской форме элемента, воспользовавшись свойством <code>form</code>. В следующем примере форма <code>myForm</code> содержит элемент ввода <code>Text </code>и кнопку <code>button1</code>. Когда пользователь нажимает кнопку, значению объекта <code>Text</code> назначается имя формы. Обработчик событий кнопки <code>onclick</code> пользуется <code>this.form</code> чтобы сослаться на текущую форму, <code>myForm</code>.</p> + +<pre class="brush: html"><form name="myForm"> +<p><label>Form name:<input type="text" name="text1" value="Beluga"></label> +<p><input name="button1" type="button" value="Show Form Name" + onclick="this.form.text1.value = this.form.name"> +</p> +</form></pre> + +<h2 id="Определение_геттеров_и_сеттеров">Определение геттеров и сеттеров</h2> + +<p><em><a href="/ru/docs/Web/JavaScript/Reference/Functions/get">Геттер </a>(от англ. get - получить) </em><span style="line-height: 1.5;">—</span><em> </em>это метод, который получает значение определенного свойства. <em><a href="/ru/docs/Web/JavaScript/Reference/Functions/set">Сеттер </a>(от англ. set </em><span style="line-height: 1.5;">—</span><em> присвоить)</em> <span style="line-height: 1.5;">—</span> это метод, который присваивает значение определенному свойству объекта. Вы можете определить геттеры и сеттеры для любых из встроенных или определенных вами объектов, которые поддерживают добавление новых свойств. Синтаксис определения геттеров и сеттеров использует литеральный синтаксис объектов.</p> + +<p>Ниже проиллюстрировано, как могут работать геттеры и сеттеры в объекте определенном пользователем:</p> + +<pre class="brush: js"><code>var o = { + a: 7, + get b() { + return this.a + 1; + }, + set c(x) { + this.a = x / 2; + } +}; + +console.log(o.a); // 7 +console.log(o.b); // 8 +o.c = 50; +console.log(o.a); // 25</code></pre> + +<p>Объект <code>o</code> получит следующие свойства:</p> + +<ul> + <li><code>o.a</code> — число</li> + <li><code>o.b</code> — геттер, который возвращает <code>o.a</code> плюс 1</li> + <li><code>o.c</code> — сеттер, который присваивает значение <code>o.a</code> половине значения которое передано в <code>o.c</code></li> +</ul> + +<p>Следует особо отметить, что имена функций, указанные в литеральной форме "[gs]et <em>propertyName</em>() { }" не будут в действительности являться именами геттера и сеттера. Чтобы задать в качестве геттера и сеттера функции с явно определенными именами, используйте метод <code><a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty" title="en-US/docs/Core JavaScript 1.5 Reference/Global +Objects/Object/defineProperty">Object.defineProperty</a></code> (или его устаревший аналог <code><a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineGetter" title="en-US/docs/Core JavaScript 1.5 Reference/Global +Objects/Object/defineGetter">Object.prototype.__defineGetter__</a></code>).</p> + +<p>В коде ниже показано, как с помощью геттера и сеттера можно расширить прототип объекта {{jsxref("Date")}} и добавить ему свойство <code>year,</code> которое будет работать у всех экземпляров класса <code>Date</code>. Этот код использует существующие методы класса <code>Date</code> - <code>getFullYear</code> и <code>setFullYear</code> для работы геттера и сеттера.</p> + +<p>Определение геттера и сеттера для свойства <code>year</code>:</p> + +<pre class="brush: js"><code>var d = Date.prototype; +Object.defineProperty(d, 'year', { + get: function() { return this.getFullYear(); }, + set: function(y) { this.setFullYear(y); } +});</code></pre> + +<p>Использование свойства <code>year</code> заданного геттером и сеттером:</p> + +<pre class="brush: js"><code>var now = new Date(); +console.log(now.year); // 2000 +now.year = 2001; // 987617605170 +console.log(now); +// Wed Apr 18 11:13:25 GMT-0700 (Pacific Daylight Time) 2001</code></pre> + +<p>В принципе, геттеры и сеттеры могут быть либо:</p> + +<ul> + <li>определены при использовании {{ web.link("#Использование_инициализаторов_объекта", "Инициализаторов объекта") }}, или</li> + <li>добавлены существующему объекту в любой момент, при использовании методов добавления геттеров и сеттеров.</li> +</ul> + +<p>Когда определение геттера и сеттера использует {{ web.link("#Использование_инициализаторов_объекта", "инициализаторы объекта") }}, все что вам нужно, это дополнить геттер префиксом <code>get</code> а сеттер префиксом <code>set</code>. При этом, метод геттера не должен ожидать каких либо параметров, в то время как метод сеттера принимает один единственный параметр (новое значение для присвоения свойству). Например:</p> + +<pre class="brush: js"><code>var o = { + a: 7, + get b() { return this.a + 1; }, + set c(x) { this.a = x / 2; } +};</code></pre> + +<p>Геттеры и сеттеры, могут быть добавлены существующему объекту в любой момент, при помощи метода <code>Object.defineProperties</code>. Первый параметр этого метода - объект, которому вы хотите присвоить геттер и сеттер. Второй параметр - это объект, имена свойств которого будут соответствовать именам создаваемых свойств, а значения - объекты определяющие геттер и сеттер создаваемых свойств. В следующем примере создаются в точности такие же геттер и сеттер, как и в примере выше:</p> + +<pre class="brush: js"><code>var o = { a: 0 }; + +Object.defineProperties(o, { + 'b': { get: function() { return this.a + 1; } }, + 'c': { set: function(x) { this.a = x / 2; } } +}); + +o.c = 10; // Запускает сеттер, который присваивает 10 / 2 (5) свойству 'a' +console.log(o.b); // Запускает геттер, который возвращает a + 1 (тоесть 6)</code></pre> + +<p>То, какую из двух форм использовать для определения свойств, зависит от вашего стиля программирования и стоящей перед вами задачи. Если вы уже используете инициализатор объекта для определения прототипа, то, скорее всего, в большинстве случаев, вы воспользуетесь первой формой. Она более компактна и естественна. Однако, не редко, вторая форма является единственно возможной, в случаях, когда вы работаете с существующим объектом без доступа к его определению. Вторая форма наилучшим образом отражает динамическую природу JavaScript — но может сделать код сложным для чтения и понимания.</p> + +<h2 id="Удаление_свойств">Удаление свойств</h2> + +<p>Вы можете удалить свойство используя оператор <code>delete</code>. Следующий код показывает как удалить свойство.</p> + +<pre class="brush: js">//Creates a new object, myobj, with two properties, a and b. +var myobj = new Object; +myobj.a = 5; +myobj.b = 12; + +//Removes the a property, leaving myobj with only the b property. +delete myobj.a; +</pre> + +<p>Вы также можете воспользоваться <code>delete</code> чтобы удалить глобальную переменную, если ключевое слово <code>var</code> не было использовано при ее объявлении:</p> + +<pre class="brush: js">g = 17; +delete g; +</pre> + +<p>Смотри <code>{{ web.link("Expressions_and_operators#delete", "delete") }}</code> чтобы получить дополнительную информацию.</p> + +<h2 id="Сравнение_объектов">Сравнение объектов</h2> + +<p>В JavaScript объекты имеют ссылочный тип. Два отдельных объекта никогда не будут равными, даже если они имеют равный набор свойств. Только сравнение двух ссылок на один и тотже объект вернет true.</p> + +<pre class="brush: js"><code>// Две переменных ссылаются на два объекта с одинаковыми свойствами +var fruit = {name: 'apple'}; +var fruitbear = {name: 'apple'}; + +fruit == fruitbear; // вернет false +fruit === fruitbear; // вернет false</code></pre> + +<pre class="brush: js"><code>// Две переменные ссылаются на один общий объект +var fruit = {name: 'apple'}; +var fruitbear = fruit; // присвоим переменной fruitbear ссылку на объект fruit + +// теперь fruitbear и fruit ссылаются на один и тот же объект +fruit == fruitbear; // вернет true +fruit === fruitbear; // вернет true</code></pre> + +<pre class="brush: js"><code>fruit.name = 'grape'; +console.log(fruitbear); // вернет { name: "grape" } вместо { name: "apple" }</code></pre> + +<p>Подробнее смотрите <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators">Операторы сравнения</a>.</p> + +<h2 id="Смотрите_также">Смотрите также</h2> + +<ul> + <li>Для детального изучения читайте <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Details_of_the_Object_Model">подробнее об объектной модели JavaScript</a>.</li> + <li>Для изучения классов ECMAScript 2015 (новый способ определения объектов), читайте главу <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Classes">классы JavaScript</a>.</li> +</ul> + +<div>{{PreviousNext("Web/JavaScript/Guide/Keyed_collections", "Web/JavaScript/Guide/Details_of_the_Object_Model")}}</div> diff --git a/files/ru/web/javascript/guide/введение_в_javascript/index.html b/files/ru/web/javascript/guide/введение_в_javascript/index.html new file mode 100644 index 0000000000..1b49c45ddb --- /dev/null +++ b/files/ru/web/javascript/guide/введение_в_javascript/index.html @@ -0,0 +1,159 @@ +--- +title: Введение в JavaScript +slug: Web/JavaScript/Guide/Введение_в_JavaScript +tags: + - Beginner + - Guide + - JavaScript +translation_of: Web/JavaScript/Guide/Introduction +--- +<p>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide", "Web/JavaScript/Guide/Values,_variables,_and_literals")}}</p> + +<div class="summary"> +<p>Данная глава является введением в JavaScript и рассматривает некоторые его фундаментальные концепции.</p> +</div> + +<h2 id="Что_вам_уже_следует_знать">Что вам уже следует знать?</h2> + +<p>В данном руководстве предполагается, что вы имеете:</p> + +<ul> + <li>Общее понимание Internet и World Wide Web ({{Glossary("WWW")}}).</li> + <li>Хорошее знание HyperText Markup Language ({{Glossary("HTML")}}).</li> + <li>Некоторый опыт программирования. Если вы являетесь новичком в программировании, то ознакомьтесь с руководствами, приведенными на странице по <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript">JavaScript</a>.</li> +</ul> + +<h2 id="Где_можно_найти_информацию_о_JavaScript">Где можно найти информацию о JavaScript?</h2> + +<p>Документация по JavaScript на MDN включает:</p> + +<ul> + <li><a href="https://developer.mozilla.org/ru/docs/Learn">Изучение Web</a> предоставляет информацию для начинающих и вводит в базовые концепции программирования и Internet.</li> + <li><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide">Руководство по JavaScript</a> (данное руководство) предоставляет обзор JavaScript и его объектов.</li> + <li><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference">Справочник по JavaScript</a> предоставляет подробную информацию по JavaScript.</li> +</ul> + +<p>Если вы являетесь новичком в JavaScript, то начните с <a href="https://developer.mozilla.org/ru/docs/Learn">Изучение Web</a> и <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide">Руководство по JavaScript</a>. Как только вы освоите фундаментальные концепции, используйте <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference">Справочник по JavaScript</a> для того, чтобы получить более подробную информацию о конкретных объектах или операторах.</p> + +<h2 id="Что_такое_JavaScript">Что такое JavaScript?</h2> + +<p>JavaScript — это кросс-платформенный, объектно-ориентированный скриптовый язык, являющийся небольшим и легковесным. Внутри среды исполнения JavaScript может быть связан с объектами данной среды и предоставлять программный контроль над ними.</p> + +<p>JavaScript включает стандартную библиотеку объектов, например, <code>Array</code>, <code>Date</code> и <code>Math</code>, а также базовый набор языковых элементов, например, операторы и управляющие конструкции. Ядро JavaScript может быть расширено для различных целей путем добавления в него новых объектов, например:</p> + +<ul> + <li>JavaScript на стороне клиента расширяет ядро языка, предоставляя объекты для контроля браузера и его Document Object Model (DOM). Например, клиентские расширения позволяют приложению размещать элементы в форме HTML и обрабатывать пользовательские события, такие как щелчок мыши, ввод данных в форму и навигация по страницам.</li> + <li>JavaScript на стороне сервера расширяет ядро языка, предоставляя объекты для запуска JavaScript на сервере. Например, расширение на стороне сервера позволяет приложению соединяться с базой данных, обеспечивать непрерывность информации между вызовами приложения или выполнять манипуляции над файлами на сервере.</li> +</ul> + +<h2 id="JavaScript_и_Java">JavaScript и Java</h2> + +<p>JavaScript и Java похожи в одних отношениях, но фундаментально отличны в других. Javascript напоминает Java, но не имеет статической типизации и строгой проверки типов, которыми обладает Java. JavaScript следует большей части синтаксиса Java в выражениях, соглашениях об именовании и основного потока управления конструкциями, поэтому он был переименован из LiveScript в JavaScript.</p> + +<p>В отличие от системы скомпилированных классов Java, построенной на объявлениях, JavaScript поддерживает систему исполнения, основанную на небольшом числе типов данных, представляющих числовые, логические и строковые значения. JavaScript имеет объектную модель на базе прототипов вместо более общей модели на базе классов. Модель объектов на базе прототипов предоставляет динамическое наследование, т.е. то, что наследуется, может отличаться для отдельных объектов. JavaScript также поддерживает функции без каких-либо специальных декларативных требований. Функции могут быть свойствами объектов, выполняться как свободно-типизированные методы.</p> + +<p>По сравнению с Java, JavaScript является языком с очень свободной формой. Вам не надо объявлять переменные, классы и методы. Вам не надо беспокоиться о том, являются ли методы публичными (public), приватными (private) или защищенными (protected), а также вам не надо реализовывать интерфейсы. Переменные, параметры и возвращаемые функциями типы не являются явно типизированными.</p> + +<p>Java — это язык программирования, основанный на классах и предназначенный для быстрого выполнения и безопасности типов. Безопасность типов означает, например, что вы не можете привести тип integer к типу object reference или получить доступ к приватной памяти, изменяя байт-код Java. Ориентированная на классы модель Java означает, что программы состоят исключительно из классов и их методов. Наследование классов и строгая типизация в Java обычно требуют тесно связанные иерархии объектов. Эти требования делают программирование на Java более комплексным, чем программирование на JavaScript.</p> + +<p>По духу JavaScript происходит от небольших, динамически типизированных языков, таких как HyperTalk и dBASE. Эти скриптовые языки предлагают инструменты программирования для гораздо более широкой аудитории благодаря более простому синтаксису, специализированной встроенной функциональности и минимальным требованиям для создания объектов.</p> + +<table class="standard-table"> + <caption>Сравнение JavaScript и Java</caption> + <thead> + <tr> + <th scope="col">JavaScript</th> + <th scope="col">Java</th> + </tr> + </thead> + <tbody> + <tr> + <td>Объектно-ориентированный. Нет различий между типами объектов. Наследование реализовано через механизм прототипов, свойства и методы могут быть добавлены в любой объект динамически.</td> + <td>На базе классов. Объекты делятся на классы и экземпляры с наследованием через классовую иерархию. Классы и экземпляры не могут иметь динамически добавленные свойства или методы.</td> + </tr> + <tr> + <td>Типы данных переменных не объявляются (динамическая типизация).</td> + <td>Типы данных переменных должны быть объявлены (статическая типизация).</td> + </tr> + <tr> + <td>Не может автоматически записывать на жесткий диск.</td> + <td><span style="background-color: rgba(212, 221, 228, 0.14902);">Может автоматически записывать на жесткий диск.</span></td> + </tr> + </tbody> +</table> + +<p>Для получения дополнительной информации о различиях между JavaScript и Java, прочитайте <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model">Details of the object model</a>.</p> + +<h2 id="JavaScript_и_спецификация_ECMAScript">JavaScript и спецификация ECMAScript</h2> + +<p>JavaScript стандартизирован европейской ассоциацией <a href="http://www.ecma-international.org/">Ecma International</a>, деятельность которой посвящена стандартизации информационных и коммуникационных систем (изначально ECMA являлся акронимом European Computer Manufacturers Association). Эта стандартизированная версия JavaScript, называемая ECMAScript, работает одинаково во всех приложениях, поддерживающих стандарт. Компании могут использовать открытый стандарт языка, чтобы разработать собственную реализацию JavaScript. Стандарт ECMAScript задокументирован в спецификации ECMA-262. Чтобы узнать больше информации о разных версиях JavaScript и ECMAScript, прочитайте <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/New_in_JavaScript">Что нового в JavaScript</a>.</p> + +<p>Стандарт ECMA-262 также утвержден <a href="http://www.iso.org/iso/home.html">ISO</a> (International Organization for Standardization) как ISO-16262. Вы можете найти спецификацию на <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">сайте Ecma International</a>. Спецификация ECMAScript не описывает Document Object Model (DOM), которая стандартизирована <a href="http://www.w3.org/">World Wide Web Consortium (W3C)</a>. DOM определяет способ для доступа к объектам HTML документа из вашего скрипта. Чтобы получить более точное представление о различных технологиях, используемых при программировании на JavaScript, прочитайте <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/JavaScript_technologies_overview">Обзор JavaScript</a>.</p> + +<h3 id="Документация_JavaScript_против_спецификации_ECMAScript">Документация JavaScript против спецификации ECMAScript</h3> + +<p>Спецификация ECMAScript — это набор требований, касающихся реализации ECMAScript. Она предназначена для реализации языковых возможностей, соответствующих стандарту, в вашей реализации ECMAScript или движке (например, SpiderMonkey в Firefox или V8 в Google Chrome).</p> + +<p>Документ ECMAScript не предназначен для помощи программистам в создании скриптов; чтобы получить информацию о том, как писать скрипты, используйте документацию JavaScript.</p> + +<p>Спецификация ECMAScript использует терминологию и синтаксис, которые могут быть незнакомы JavaScript-программистам. Хотя описание языка может отличаться в ECMAScript, но сам язык остается таким же. JavaScript поддерживает всю функциональность, описанную в спецификации ECMAScript.</p> + +<p>Документация JavaScript описывает аспекты языка, являющиеся подходящими для JavaScript-программиста.</p> + +<h2 id="Начинаем_знакомство_с_JavaScript">Начинаем знакомство с JavaScript</h2> + +<p>Все, что вам нужно для знакомства с JavaScript — это современный браузер. Данное руководство включает некоторые возможности JavaScript, которые на данный момент доступны только в последних версиях Firefox, поэтому рекомендуется использовать последнюю версию Firefox.</p> + +<p>В Firefox встроены два инструмента, полезных для экспериментирования с JavaScript: Web Console и Scratchpad.</p> + +<h3 id="Web_Console">Web Console</h3> + +<p><a href="https://developer.mozilla.org/ru/docs/Tools/Web_Console">Web Console</a> отображает информацию о текущей загруженной веб-странице, а также включает <a href="https://developer.mozilla.org/ru/docs/Tools/Web_Console#The_command_line_interpreter">командную строку</a>, которую вы можете использовать, чтобы выполнить выражения JavaScript на текущей странице.</p> + +<p>Чтобы открыть Web Console, выберите "Web Console" из меню "Web Developer", которое находится под меню "Tools" в Firefox. Консоль появится в нижней части окна браузера. Вдоль нижней части консоли размещается командная строка, которую вы можете использовать для ввода JavaScript, результат выполнения появится на панели выше:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/16569/2019-04-04_00-15-29.png" style="display: block; height: 1824px; margin-left: auto; margin-right: auto; width: 2784px;"></p> + + + +<pre>function greetMe(yourName) { + alert('Hello ' + yourName); +} +<code>console.log(eval('3 + 5'));</code></pre> + + + +<h3 id="Scratchpad">Scratchpad</h3> + +<p>Web Console отлично подходит для выполнения одиночных строк JavaScript, но хотя вы можете выполнить и несколько строк, это не очень удобно, к тому же вы не можете сохранить ваш код, используя Web Console. Поэтому для более комплексных примеров <a href="https://developer.mozilla.org/ru/docs/Tools/%D0%A7%D0%B5%D1%80%D0%BD%D0%BE%D0%B2%D0%B8%D0%BA">Scratchpad</a> является более подходящим инструментом.</p> + +<p>Чтобы открыть Scratchpad(<kbd>Shift</kbd>+<kbd>F4</kbd>), выберите "Scratchpad" из меню "Web Developer", которое находится под меню "Tools" в Firefox. Блокнот будет открыт в отдельном окне, вы можете использовать его для создания и выполнения JavaScript в браузере. Вы также можете сохранять ваши скрипты на жесткий диск, а потом загружать их.</p> + +<p>Если вы выберете "Display", то код в вашем блокноте будет выполнен в браузере, а результат вставлен обратно в блокнот как комментарий:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13468/scratchpad.png" style="display: block; height: 375px; margin-left: auto; margin-right: auto; width: 631px;"></p> + +<h3 id="Hello_world">Hello world</h3> + +<p>Чтобы начать писать JavaScript код откройте Scratchpad и напишите свой первый "Hello World!" код:</p> + +<pre><code>(function(){ + "use strict"; + /* Start of your code */ + function greetMe(yourName) { + alert('Hello ' + yourName); + } + + greetMe('World'); + /* End of your code */ +})();</code></pre> + +<p>Выберите код на панели и зажмите Ctrl + R, чтобы открыть код в браузере! На следующих страницах мы изучим синтаксис и возможности JS, чтобы вы могли написать сложное более сложное приложение. Не забывайте добавлять перед кодом <code>(function(){"use strict";</code> и <code>})();</code> после. вы узнаете, что это означает, а пока считайте, что это —</p> + +<p>1. Значительно улучшает производительность</p> + +<p>2. Предотвращает структуры, которые могут запутать вас на начальном этапе.</p> + +<p>3. Предотвращает взаимодействие фрагментов кода, выполняемых в консоли.</p> + +<p>{{PreviousNext("Web/JavaScript/Guide", "Web/JavaScript/Guide/Grammar_and_types")}}</p> diff --git a/files/ru/web/javascript/guide/об_этом_руководстве/index.html b/files/ru/web/javascript/guide/об_этом_руководстве/index.html new file mode 100644 index 0000000000..397327911c --- /dev/null +++ b/files/ru/web/javascript/guide/об_этом_руководстве/index.html @@ -0,0 +1,68 @@ +--- +title: Об этом руководстве +slug: Web/JavaScript/Guide/Об_этом_руководстве +--- +<p> </p> +<p><span id="result_box" lang="ru"><span class="hps">JavaScript</span> <span class="hps">является</span> <span class="hps">кросс-платформенным,</span> <span class="hps">объектно-ориентированный</span> <span class="hps">язык сценариев.</span> <span class="hps">Это руководство</span> <span class="hps">объясняет</span> <span class="hps">все, что нужно</span> <span class="hps">знать об использовании</span> <span class="hps">JavaScript.</span></span></p> +<h2 id="Новые_возможности_в_версиях_JavaScript"><span class="short_text" id="result_box" lang="ru"><span class="hps">Новые возможности в</span> <span class="hps">версиях</span> <span class="hps">JavaScript</span></span></h2> +<pre class="script" style="font-size: 16px;">/* Note: To add a link to new JavaScript version description +add version number to versionList variable below. The page linked to +must reside in /en/JavaScript/New_in_JavaScript/N, where N is version number. */ + +var versionList = ["1.5", "1.6", "1.7", "1.8", "1.8.1", "1.8.5"]; +var s = ""; +<ul> + foreach (var i in versionList){ + let s = "/en/JavaScript/New_in_JavaScript/" .. i; + <li>web.link(s, wiki.getPage(s).title)</li>; + } +</ul>; +</pre> +<h2 id="То_что_вы_должны_уже_знать"><span class="short_text" id="result_box" lang="ru"><span class="hps">То, что вы</span> <span class="hps">должны уже знать</span></span></h2> +<p>This guide assumes you have the following basic background:</p> +<ul> <li><span id="result_box" lang="ru"><span>Общее представление о</span> <span class="hps">сети Интернет и</span> <span class="hps atn">World Wide Web (</span><span>WWW).</span></span></li> <li><span id="result_box" lang="ru"><span class="hps">Хорошие</span> <span class="hps">знания</span> <span class="hps">языка</span> <span class="hps">гипертекстовой разметки</span> <span class="hps">(HTML).</span></span></li> +</ul> +<p><span id="result_box" lang="ru"><span class="hps">Некоторый опыт программирования</span> <span class="hps">на языках</span><span>, таких как</span> <span class="hps">C</span> <span class="hps">или</span> <span class="hps">Visual Basic,</span> <span class="hps">полезен,</span> <span class="hps">но не обязателен.</span></span></p> +<h2 id="Версии_JavaScript">Версии JavaScript</h2> +<table class="standard-table"> <caption>Таблица №1 версии JavaScript и веб-браузера Navigator</caption> <thead> <tr> <th scope="col">JavaScript version</th> <th scope="col">Navigator version</th> </tr> </thead> <tbody> <tr> <td>JavaScript 1.0</td> <td>Navigator 2.0</td> </tr> <tr> <td>JavaScript 1.1</td> <td>Navigator 3.0</td> </tr> <tr> <td>JavaScript 1.2</td> <td>Navigator 4.0-4.05</td> </tr> <tr> <td>JavaScript 1.3</td> <td>Navigator 4.06-4.7x</td> </tr> <tr> <td>JavaScript 1.4</td> <td> </td> </tr> <tr> <td>JavaScript 1.5</td> <td>Navigator 6.0<br> <span class="short_text" id="result_box" lang="ru"><span class="hps atn">Mozilla (</span><span>браузер с открытым</span> <span class="hps">исходным кодом)</span></span></td> </tr> <tr> <td>JavaScript 1.6</td> <td><a href="/en/Firefox_1.5_for_developers" title="en/Firefox_1.5_for_developers">Firefox 1.5</a>, other Mozilla 1.8-based products</td> </tr> <tr> <td>JavaScript 1.7</td> <td><a href="/en/Firefox_2_for_developers" title="en/Firefox_2_for_developers">Firefox 2</a>, other Mozilla 1.8.1-based products</td> </tr> <tr> <td>JavaScript 1.8</td> <td><a href="/en/Firefox_3_for_developers" title="en/Firefox_3_for_developers">Firefox 3</a>, other Gecko 1.9-based products</td> </tr> </tbody> +</table> +<p> </p> +<div class="almost_half_cell" id="gt-res-content"> <div dir="ltr" style="zoom: 1;"><span id="result_box" lang="ru"><span class="hps">Каждая версия</span> <span class="hps">Netscape</span> <span class="hps">Enterprise Server,</span> <span class="hps">также поддерживает</span> <span class="hps">различные версии</span> <span class="hps">JavaScript.</span> <span class="hps">Чтобы помочь вам</span> <span class="hps">писать сценарии</span><span>, которые совместимы</span> <span class="hps">с несколькими версиями</span> <span class="hps">Enterprise Server</span><span>, это руководство</span> <span class="hps">использует</span> <span class="hps">аббревиатуру</span> <span class="hps">для обозначения</span> <span class="hps">версии сервера</span><span>, в котором каждая</span> <span class="hps">функция была реализована</span><span>.</span></span></div> +</div> +<table class="standard-table"> <caption>Таблица №2 Аббревиатуры в версиях Netscape Enterprise Server</caption> <thead> <tr> <th scope="col">Аббревиатура</th> <th scope="col">Версия Server Enterprise</th> </tr> </thead> <tbody> <tr> <td>NES 2.0</td> <td>Netscape Enterprise Server 2.0</td> </tr> <tr> <td>NES 3.0</td> <td>Netscape Enterprise Server 3.0</td> </tr> </tbody> +</table> +<h2 id="Где_найти_информацию_о_JavaScript">Где найти информацию о JavaScript</h2> +<p><span id="result_box" lang="ru"><span class="hps">JavaScript</span> <span class="hps">документация включает в себя</span> <span class="hps">следующие книги:</span></span></p> +<ul> <li><a href="/en/JavaScript/Guide" title="en/Core_JavaScript_1.5_Guide">JavaScript Guide</a> <span id="result_box" lang="ru"><span class="hps atn">(</span><span>это руководство</span><span>) предоставляет информацию о</span> <span class="hps">языке</span> <span class="hps">JavaScript</span> <span class="hps">и его объектах.</span></span></li> <li><a href="/en/JavaScript/Reference" title="en/JavaScript/Reference">JavaScript Reference</a> <span class="short_text" id="result_box" lang="ru"><span class="hps">содержит справочный материал о</span> <span class="hps">языке</span> <span class="hps">JavaScript.</span></span></li> +</ul> +<p><span id="result_box" lang="ru"><span class="hps">Если</span> <span class="hps">вы новичок в</span> <span class="hps">JavaScript</span><span>, начните с</span></span> <a href="/en/JavaScript/Guide" title="en/Core_JavaScript_1.5_Guide"><span id="result_box" lang="ru"><span class="hps">руководства</span> <span class="hps">JavaScript.</span></span></a> <span id="result_box" lang="ru"><span class="hps">Если у вас есть</span> <span class="hps">твердое понимание</span> <span class="hps">основы</span><span>, вы можете использовать</span></span> <a href="/en/JavaScript/Reference" title="en/JavaScript/Reference">Справочник по JavaScript</a> <span id="result_box" lang="ru"><span>чтобы получить</span> <span class="hps">более подробную информацию</span> <span class="hps">на отдельных</span> <span class="hps">объектах и операторах.</span></span></p> +<h2 id="Советы_для_изучения_JavaScript"><span class="short_text" id="result_box" lang="ru"><span class="hps">Советы</span> <span class="hps">для изучения</span> <span class="hps">JavaScript</span></span></h2> +<p><span id="result_box" lang="ru"><span class="hps">Начало работы с</span> <span class="hps">JavaScript</span> <span class="hps">очень просто:</span> <span class="hps">все, что вам</span> <span class="hps">нужно, это</span> <span class="hps">современный</span> <span class="hps">веб-браузер.</span> <span class="hps">Это руководство</span> <span class="hps">включает в себя некоторые</span> <span class="hps">функции</span> <span class="hps">JavaScript</span><span>, которые только</span> <span class="hps">в настоящее время</span> <span class="hps">доступна в последней</span> <span class="hps">версии</span> <span class="hps atn">Firefox (</span><span>и других</span> браузеров с движком Gecko<span class="hps">)</span><span>, поэтому </span></span><span id="result_box" lang="ru"><span class="hps">рекомендуется</span></span><span id="result_box" lang="ru"><span> использование</span> <span class="hps">самых</span> <span class="hps">последних версий</span> <span class="hps">Firefox</span><span class="hps">.</span></span></p> +<h3 id="Интерактивный_интерпретатор"><span class="short_text" id="result_box" lang="ru"><span>Интерактивный интерпретатор</span></span></h3> +<p>Диалоговый JavaScript незамедлительно - неоценимая помощь изучению языка, так как это предоставляет вам возможность пробовать вещи в интерактивном режиме без необходимости сохранить файл и обновить страницу. Ошибочная Консоль Firefox, доступная через меню Инструменты, обеспечивает простой путь пробовать диалоговый JavaScript: Только вводят линию кода и щелкают кнопку "Evaluate".</p> +<p><img alt="Image:ErrorConsole.png" class="internal" src="/@api/deki/files/192/=ErrorConsole.png"></p> +<h3 id="Firebug">Firebug</h3> +<p>Более передовой диалоговый незамедлительно - доступный использующий <a class="external" href="http://www.getfirebug.com/">Firebug</a>, дополнение к Firefox. Выражения, которые вы печатаете, интерпретируются как объекты <span id="result_box" lang="ru"><span class="hps">и</span> <span class="hps">связанные с</span> <span class="hps">другими частями</span> <span class="hps">Firebug.</span></span> <span id="result_box" lang="ru"><span class="hps">Например, вы</span> <span class="hps">можете добавить</span> <span class="hps">5 плюс</span> <span class="hps">5,</span> <span class="hps">изменять регистр</span> <span class="hps">строки</span><span>,</span></span> get a clickable link to the document, or get a link to an element:</p> +<p><img alt="" class="internal" src="/@api/deki/files/5188/=FirebugCommandLine.PNG" style="width: 728px; height: 281px;"></p> +<p><span id="result_box" lang="ru"><span class="hps">Использование</span> <span class="hps">стрелки на</span> <span class="hps">правом нижнем углу</span> <span class="hps">дает</span> <span class="hps">команду</span> <span class="hps">редактор для</span> <span class="hps">многострочного</span> <span class="hps">сценариев.</span></span></p> +<p>Firebug also provides an advanced DOM inspector, a JavaScript debugger, a profiling tool and various other utilities. JavaScript code running in a Web page can call, <code>console.log()</code>, a function that prints its arguments to the Firebug console.</p> +<p>Many of the examples in this guide use <code>alert()</code> to show messages as they execute. If you have Firebug installed you can use <code>console.log()</code> in place of <code>alert()</code> when running these examples.</p> +<h2 id="Document_conventions">Document conventions</h2> +<p>JavaScript applications run on many operating systems; the information in this book applies to all versions. File and directory paths are given in Windows format (with backslashes separating directory names). For Unix versions, the directory paths are the same, except that you use slashes instead of backslashes to separate directories.</p> +<p>This guide uses uniform resource locators (URLs) of the following form:</p> +<p><code>http://<em>server</em>.<em>domain</em>/<em>path</em>/<em>file</em>.html</code></p> +<p>In these URLs, <em>server</em> represents the name of the server on which you run your application, such as <code>research1</code> or <code>www</code>; <em>domain</em> represents your Internet domain name, such as <code>netscape.com</code> or <code>uiuc.edu</code>; <em>path</em> represents the directory structure on the server; and <em>file</em><code>.html</code> represents an individual file name. In general, items in italics in URLs are placeholders and items in normal monospace font are literals. If your server has Secure Sockets Layer (SSL) enabled, you would use <code>https</code> instead of <code>http</code> in the URL.</p> +<p>This guide uses the following font conventions:</p> +<ul> <li><code>The monospace font</code> is used for sample code and code listings, API and language elements (such as method names and property names), file names, path names, directory names, HTML tags, and any text that must be typed on the screen. (<code><em>Monospace italic font</em></code> is used for placeholders embedded in code.)</li> <li><em>Italic type</em> is used for book titles, emphasis, variables and placeholders, and words used in the literal sense.</li> <li><strong>Boldface</strong> type is used for glossary terms.</li> +</ul> +<pre class="script" style="font-size: 16px;">autoPreviousNext("JSGChapters"); +wiki.languages({ + "zh-tw": "zh_tw/Core_JavaScript_1.5_教學/關於", + "es": "es/Gu\u00eda_JavaScript_1.5/Acerca_de_esta_gu\u00eda", + "fr": "fr/Guide_JavaScript_1.5/\u00c0_propos", + "ja": "ja/Core_JavaScript_1.5_Guide/About", + "ko": "ko/Core_JavaScript_1.5_Guide/About", + "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/O_tym_przewodniku", + "zh-cn": "cn/Core_JavaScript_1.5_Guide/\u5173\u4e8e" +}) +</pre> diff --git a/files/ru/web/javascript/guide/циклы_и_итерации/index.html b/files/ru/web/javascript/guide/циклы_и_итерации/index.html new file mode 100644 index 0000000000..231bc70804 --- /dev/null +++ b/files/ru/web/javascript/guide/циклы_и_итерации/index.html @@ -0,0 +1,362 @@ +--- +title: Циклы и итерации +slug: Web/JavaScript/Guide/Циклы_и_итерации +tags: + - for + - операторы цикла + - циклы +translation_of: Web/JavaScript/Guide/Loops_and_iteration +--- +<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Control_flow_and_error_handling", "Web/JavaScript/Guide/Functions")}}</div> + +<p class="summary">Циклы - простой способ сделать какое-то действие несколько раз. Эта глава <a href="/ru/docs/Web/JavaScript/Guide">руководства JavaScript Guide</a> познакомит вас с различными операторами доступными в JavaScript.</p> + +<p>Вы можете представить цикл в виде компьютеризированной версии игры, где вы говорите кому-то сделать X шагов в одном направлении, затем Y шагов в другом; для примера, идея игры "Иди 5 шагов на восток" может быть выражена в виде цикла:</p> + +<pre class="brush: js">var step; +for (step = 0; step < 5; step++) { + // Запускается 5 раз, с шагом от 0 до 4. + console.log('Идём 1 шаг на восток'); +} +</pre> + +<p>Существует множество различных видов циклов, но все они по сути делают тоже самое: повторяют какое-либо действие несколько раз (не забывайте про нулевой раз повторения, отсчёт в массиве начинается с 0). Различные по строению циклы предлагают разные способы для определения начала и окончания цикла. Для различных задач программирования существуют свои операторы цикла, с помощью которых они решаются намного проще.</p> + +<p>Операторы предназначеные для организации циклов в JavaScript:</p> + +<ul> + <li>{{anch("Цикл_for")}}</li> + <li>{{anch("Цикл_do...while")}}</li> + <li>{{anch("Цикл_while")}}</li> + <li>{{anch("Метка_(label)")}}</li> + <li>{{anch("break")}}</li> + <li>{{anch("continue")}}</li> + <li>{{anch("for...in")}}</li> + <li>{{anch("for...of")}}</li> +</ul> + +<h2 id="Цикл_for">Цикл <code>for</code> </h2> + +<p>Цикл <strong><a href="/ru/docs/Web/JavaScript/Reference/Statements/for"><code>for</code> </a> </strong>повторяет действия, пока не произойдёт какое-либо специальное событие завершения цикла. Оператор <code>for</code> в JavaScript аналогичен оператору for в Java и C. Объявление оператора <code>for</code> выглядит следующим образом:</p> + +<pre class="syntaxbox">for ([начало]; [условие]; [шаг]) выражения +</pre> + +<p>При его выполнении происходит следущее:</p> + +<ol> + <li>Выполняется выражение <code>начало</code>, если оно указано. Это выражение обычно инициализирует один или несколько счётчиков, но синтаксис позволяет выражению быть любой сложности. Также используется для объявления переменных.</li> + <li>Выполняется <code>условие</code>. Если <code>условие</code> истинно, то выполняются <code>выражения</code>. Если оно ложно, цикл <code>for</code> прерывается. Если же <code>условие</code> полностью пропущено, то оно считается истинным.</li> + <li>Выполняются <code>выражения</code>. Чтобы выполнить несколько выражений, используются блок-выражение <code>{ ... }</code> для группировки выражений.</li> + <li>Обновляется <code>шаг</code>, если он есть, а затем управление возвращается к шагу 2.</li> +</ol> + +<h3 id="Пример"><strong>Пример</strong></h3> + +<p>В следующей функции есть цикл <code>for</code>, который считает количество выбранных жанров в списке прокрутки (элемент {{HTMLElement("select")}}, который позволяет выбрать несколько элементов). Цикл <code>for</code> объявляет переменную <code>i</code> и задаёт ей значение 0. Также он проверяет, что <code>i</code> меньше количества элементов в элементе <code><select></code>, выполняет оператор <code>if</code> и увеличивает <code>i</code> на один после каждого прохода цикла.</p> + +<pre class="brush: html"><form name="selectForm"> + <p> + <label for="musicTypes">Выберите некоторые жанры музыки, а затем нажмите на кнопку ниже:</label> + <select id="musicTypes" name="musicTypes" multiple="multiple"> + <option selected="selected">R&B</option> + <option>Jazz</option> + <option>Blues</option> + <option>New Age</option> + <option>Classical</option> + <option>Opera</option> + </select> + </p> + <p><input id="btn" type="button" value="Как много выбрано?" /></p> +</form> + +<script> +function howMany(selectObject) { + var numberSelected = 0; + for (var i = 0; i < selectObject.options.length; i++) { + if (selectObject.options[i].selected) { + numberSelected++; + } + } + return numberSelected; +} + +var btn = document.getElementById("btn"); +btn.addEventListener("click", function(){ + alert('Выбрано элементов: ' + howMany(document.selectForm.musicTypes)) +}); +</script> + +</pre> + +<h2 id="Цикл_do...while">Цикл <code>do...while</code> </h2> + +<p>Цикл <code><a href="/ru/docs/Web/JavaScript/Reference/Statements/do...while">do...while</a></code> повторяется пока заданное условие истинно. Оператор <code>do...while</code> имеет вид:</p> + +<pre class="syntaxbox">do + выражения +while (условие); +</pre> + +<p><code>выражения</code> выполняются пока <code>условие</code> истинно. Чтобы использовать несколько выражений, используйте блок-выражение <code>{ ... }</code>, чтобы сгруппировать их. Если <code>условие</code> истинно, <code>выражения</code> выполнятся снова. В конце каждого прохода <code>условие</code> проверяется. Если <code>условие</code> ложно, выполнение приостанавливается и управление передаётся выражению после <code>do...while</code>.</p> + +<h3 id="Пример_2"><strong>Пример</strong></h3> + +<p>В следующем примере, цикл <code>do</code> выполнится минимум 1 раз и запускается снова, пока <code>i</code> меньше 5.</p> + +<pre class="brush: js">do { + i += 1; + console.log(i); +} while (i < 5);</pre> + +<h2 id="Цикл_while">Цикл <code>while</code></h2> + +<p>Цикл <code><a href="/ru/docs/Web/JavaScript/Reference/Statements/while">while</a></code> выполняет выражения пока условие истинно. Выглядит он так:</p> + +<pre class="syntaxbox">while (условие) + выражения +</pre> + +<p>Если <code>условие</code> становится ложным, выражения в цикле перестают выполняться и управление переходит к выражению после цикла.</p> + +<p><code>Условие</code> проверяется на истинность до того, как выполняются <code>выражения</code> в цикле. Если <code>условие</code> истинно, выполняются <code>выражения</code>, а затем условие проверяется снова. Если <code>условие</code> ложно, выполнение приостанавливается и управление переходит к выражению после <code>while</code>.</p> + +<p>Чтобы использовать несколько выражений, используйте блок выражение <code>{ ... }</code>, чтобы сгруппировать их.</p> + +<h3 id="Пример_1"><strong>Пример 1</strong></h3> + +<p>Следующий цикл <code>while</code> работает, пока <code>n</code> меньше трёх:</p> + +<pre class="brush: js">var n = 0; +var x = 0; +while (n < 3) { + n++; + x += n; +} +</pre> + +<p>С каждой итерацией, цикл увеличивает <code>n</code> и добавляет это значение к <code>x</code>. Поэтому, <code>x</code> и <code>n</code> получают следующие значения:</p> + +<ul> + <li>После первого прохода: <code>n</code> = 1 и <code>x</code> = 1</li> + <li>После второго: <code>n</code> = 2 и <code>x</code> = 3</li> + <li>После третьего прохода: <code>n</code> = 3 и <code>x</code> = 6</li> +</ul> + +<p>После третьего прохода, условие <code>n < 3</code> становится ложным, поэтому цикл прерывается.</p> + +<h3 id="Пример_2_2"><strong>Пример 2</strong></h3> + +<p>Избегайте бесконечных циклов. Убедитесь, что условие цикла в итоге станет ложным; иначе, цикл никогда не прервётся. Выражения в следующем цикле <code>while</code> будут выполняться вечно, т.к. условие никогда не станет ложным:</p> + +<pre class="brush: js">while (true) { + console.log("Hello, world"); +}</pre> + +<h2 id="Метка_(label)">Метка (label)</h2> + +<p><a href="/ru/docs/Web/JavaScript/Reference/Statements/label">Метка</a> представляет собой оператор с индентификатором, который позволяет вам ссылаться на какое-то место в вашей программе. Например, вы можете использовать метку, чтобы обозначить цикл, а затем использовать операторы <code>break</code> или <code>continue</code>, чтобы указать, должна ли программа прерывать цикл или продолжать его выполнение.</p> + +<p>Синтаксис метки следующий:</p> + +<pre class="syntaxbox">метка : + оператор +</pre> + +<p>Значение <em>метки</em> может быть любым корректным JavaScript индентификатором, не являющимся зарезервированным словом. <code><em>Оператор</em></code><em>, </em>указанный вами после метки может быть любым выражением.</p> + +<h3 id="Пример_3"><strong>Пример</strong></h3> + +<p>В этом примере, метка <code>markLoop</code> обозначает цикл <code>while</code>.</p> + +<pre class="brush: js">markLoop: +while (theMark == true) { + doSomething(); +}</pre> + +<h2 id="break"><code>break</code></h2> + +<p>Используйте оператор <code><a href="/ru/docs/Web/JavaScript/Reference/Statements/break">break</a></code>, чтобы прерывать цикл, переключать управление или в сочетании с оператором метка.</p> + +<ul> + <li>Когда вы используете <code>break</code> без метки, он прерывает циклы <code>while</code>, <code>do-while</code> и <code>for</code> или сразу переключает управление к следующему выражению.</li> + <li>Когда вы используете <code>break</code> с меткой, он прерывает специально отмеченное выражение.</li> +</ul> + +<p>Синтаксис оператора может быть таким:</p> + +<ol> + <li><code>break;</code></li> + <li><code>break <em>Метка</em>;</code></li> +</ol> + +<p>Первая форма синтаксиса прерывает цикл совсем или переключает управление; вторая прерывает специально обозначенное выражение.</p> + +<h3 id="Пример_1_2"><strong>Пример</strong> <strong>1</strong></h3> + +<p>Следующий пример проходит по элементам в массиве, пока не найдёт элемент, чьё значение - <code>theValue</code>:</p> + +<pre class="brush: js">for (i = 0; i < a.length; i++) { + if (a[i] == theValue) { + break; + } +}</pre> + +<h3 id="Пример_2_Прерывание_метки"><strong>Пример 2: Прерывание метки</strong></h3> + +<pre class="brush: js">var x = 0; +var z = 0 +labelCancelLoops: while (true) { + console.log("Внешний цикл: " + x); + x += 1; + z = 1; + while (true) { + console.log("Внутренний цикл: " + z); + z += 1; + if (z === 10 && x === 10) { + break labelCancelLoops; + } else if (z === 10) { + break; + } + } +} +</pre> + +<h2 id="continue"><code>continue</code></h2> + +<p>Оператор <code><a href="/ru/docs/Web/JavaScript/Reference/Statements/continue">continue</a></code> используется, чтобы шагнуть на шаг вперёд в циклах <code>while</code>, <code>do-while</code>, <code>for</code> или перейти к метке.</p> + +<ul> + <li>Когда вы используете <code>continue</code> без метки, он прерывает текущую итерацию циклов <code>while</code>, <code>do-while</code> и <code>for</code> и продолжает выполнение цикла со следующей итерации. В отличие от <code>break</code>, <code>continue</code> не прерывает выполнение цикла полностью. В цикле <code>while </code>он прыгает к условию. А в <code>for</code> увеличивает <code>шаг</code>.</li> + <li>Когда вы используете <code>continue</code> с меткой, он применяется к циклу с этой меткой.</li> +</ul> + +<p>Синтаксис <code>continue</code> может выглядеть так:</p> + +<ol> + <li><code>continue;</code></li> + <li><code>continue <em>Метка</em></code><em><code>;</code></em></li> +</ol> + +<h3 id="Пример_1_3"><strong>Пример 1</strong></h3> + +<p>Следующий пример показывает цикл <code>while</code> с оператором <code>continue</code>, который срабатывает, когда значение <code>i</code> равно 3. Таким образом, <code>n</code> получает значения 1, 3, 7 и 12.</p> + +<pre class="brush: js">var i = 0; +var n = 0; +while (i < 5) { + i++; + if (i == 3) { + continue; + } + n += i; +} +</pre> + +<h3 id="Пример_2_3"><strong>Пример 2</strong></h3> + +<p>Выражение, отмеченное <em><code>checkiandj</code></em> содержит выражение отмеченное <em><code>checkj</code></em>. При встрече с <code>continue</code>, программа прерывает текущую итерацию <em><code>checkj</code></em> и начинает следующую итерацию. Каждый раз при встрече с <code>continue</code>, <em><code>checkj</code></em> переходит на следующую итерацию, пока условие возвращает <code>false</code>. Когда возвращается <code>false</code>, после вычисления остатка от деления <em><code>checkiandj</code></em>, <em><code>checkiandj</code></em> переходит на следующую итерацию, пока его условие возвращает <code>false</code>. Когда возвращается <code>false</code>, программа продолжает выполнение с выражения после <em><code>checkiandj</code></em>.</p> + +<p>Если у <code>continue</code> проставлена метка <em><code>checkiandj</code></em>, программа может продолжиться с начала метки <em><code>checkiandj</code></em>.</p> + +<pre class="brush: js">checkiandj: + while (i < 4) { + console.log(i); + i += 1; + checkj: + while (j > 4) { + console.log(j); + j -= 1; + if ((j % 2) != 0) { + continue checkj; + } + console.log(j + " чётное."); + } + console.log("i = " + i); + console.log("j = " + j); + }</pre> + +<h2 id="for...in"><code>for...in</code> </h2> + +<p>Оператор <a href="/ru/docs/Web/JavaScript/Reference/Statements/for...in"><code>for...in</code></a> проходит по всем перечислимым свойствам объекта. JavaScript выполнит указанные выражения для каждого отдельного свойства. Цикл <code>for...in</code> выглядит так:</p> + +<pre class="syntaxbox">for (variable in object) { + выражения +} +</pre> + +<h3 id="Пример_4"><strong>Пример</strong></h3> + +<p>Следующая функция берёт своим аргументом объект и его имя. Затем проходит по всем свойствам объекта и возвращает строку, которая содержит имена свойств и их значения.</p> + +<pre class="brush: js">function dump_props(obj, obj_name) { + var result = ""; + for (var i in obj) { + result += obj_name + "." + i + " = " + obj[i] + "<br>"; + } + result += "<hr>"; + return result; +} +</pre> + +<p>Для объекта <code>car</code> со свойствами <code>make</code> и <code>model</code>, <font face="Consolas, Liberation Mono, Courier, monospace"><em>результатом </em>будет</font>:</p> + +<pre class="brush: js">car.make = Ford +car.model = Mustang +</pre> + +<h3 id="Пример_№2">Пример №2</h3> + +<p>Также, по ключу можно выводить значение:</p> + +<pre>let obj = {model: 'AUDI A8', year: '2019', color: 'brown'} + +for (key in obj) { + console.log(`${key} = ${obj[key]}`); +} +// model = AUDI A8 +// year = 2019 +// color = brown</pre> + +<h3 id="Массивы"><strong>Массивы</strong></h3> + +<p>Хотя, очень заманчиво использовать <strong>for...in</strong> как способ пройтись по всем элементам {{jsxref("Array")}}, этот оператор возвращает имя свойств определённых пользователем помимо числовых индексов. Таким образом лучше использовать стандартный <code><a href="/ru/docs/Web/JavaScript/Reference/Statements/for">for</a></code> для числовых индексов при взаимодействии с массивами, поскольку оператор <strong>for...in</strong> проходит по определённым пользователем свойствам в дополнение к элементам массива, если вы изменяете массив, например, добавляете свойства и методы.</p> + +<h3 id="Пример_5">Пример</h3> + +<pre>let arr = ['AUDI A8', '2019', 'brown']; +arr.cost = '$100.000'; + +for (key in arr) { + console.log(`${key} = ${arr[key]}`); +} + +// 0 = AUDI A8 +// 1 = 2019 +// 2 = brown +// cost = $100.000 +</pre> + +<h2 id="for...of"><code>for...of</code></h2> + +<p>Оператор <code><a href="/ru/docs/Web/JavaScript/Reference/Statements/for...of">for...of</a></code> создаёт цикл, проходящий по <a href="/ru/docs/Web/JavaScript/Guide/iterable">перечислимым объектам</a> (включая {{jsxref("Array")}}, {{jsxref("Map")}}, {{jsxref("Set")}}, объект <a href="/ru/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments">arguments</a> и так далее), вызывая на каждой итерации функцию с выражениями, которые надо выполнить для получения значения каждого отдельного свойства.</p> + +<pre class="syntaxbox">for (<em>variable</em> of <em>object</em>) { + <em>выражения +</em>}</pre> + +<p>Следующий пример показывает разницу между циклами <code>for...of</code> и <code><a href="/ru/docs/Web/JavaScript/Reference/Statements/for...in" title="ru/docs/JavaScript/Reference/Statements/for...in">for...in</a></code>. Тогда как <code>for...in</code> проходит по именам свойств, <code>for...of</code> проходит по значениям свойств:</p> + +<pre class="brush:js">let arr = [3, 5, 7]; +arr.foo = "hello"; + +for (let i in arr) { + console.log(i); // выводит "0", "1", "2", "foo" +} + +for (let i of arr) { + console.log(i); // выводит "3", "5", "7" +} +</pre> + +<p>{{PreviousNext("Web/JavaScript/Guide/Control_flow_and_error_handling", "Web/JavaScript/Guide/Functions")}}</p> |