diff options
author | Florian Merz <me@fiji-flo.de> | 2021-02-11 14:51:05 +0100 |
---|---|---|
committer | Florian Merz <me@fiji-flo.de> | 2021-02-11 14:51:05 +0100 |
commit | c058fa0fb22dc40ef0225b21a97578cddd0aaffa (patch) | |
tree | df20f8b4c724b61cb9c34cdb450a7ac77d690bd0 /files/ru/learn/javascript/objects | |
parent | 8260a606c143e6b55a467edf017a56bdcd6cba7e (diff) | |
download | translated-content-c058fa0fb22dc40ef0225b21a97578cddd0aaffa.tar.gz translated-content-c058fa0fb22dc40ef0225b21a97578cddd0aaffa.tar.bz2 translated-content-c058fa0fb22dc40ef0225b21a97578cddd0aaffa.zip |
unslug ru: move
Diffstat (limited to 'files/ru/learn/javascript/objects')
8 files changed, 2008 insertions, 0 deletions
diff --git a/files/ru/learn/javascript/objects/adding_bouncing_balls_features/index.html b/files/ru/learn/javascript/objects/adding_bouncing_balls_features/index.html new file mode 100644 index 0000000000..fe97392371 --- /dev/null +++ b/files/ru/learn/javascript/objects/adding_bouncing_balls_features/index.html @@ -0,0 +1,212 @@ +--- +title: Добавление функций в нашу демонстрацию отбойных шаров +slug: Learn/JavaScript/Объекты/Adding_bouncing_balls_features +translation_of: Learn/JavaScript/Objects/Adding_bouncing_balls_features +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">В этом упражнении мы будем использовать проект прыгающих шаров из предыдущей статьи и добавим в него новые интересные возможности.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Требования:</th> + <td>Перед тем как приступить к этому упражнению нужно выполнить задания из всех статей текущего модуля.</td> + </tr> + <tr> + <th scope="row">Цель:</th> + <td>Проверить насколько хорошо вы понимаете объекты и связанные с ними конструкции в языке Javascript. </td> + </tr> + </tbody> +</table> + +<h2 id="Начало">Начало</h2> + +<p>Для начала скопируйте файлы <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/index-finished.html">index-finished.html</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/style.css">style.css</a> и <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main-finished.js">main-finished.js</a> из предыдущей статьи в новую директорию на вашем компьютере.</p> + +<p>Для выполнения упражнения вы можете использовать сайт <a class="external external-icon" href="http://jsbin.com/">JSBin</a> или <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a>. Вы можете вставлять HTML, CSS и JavaScript код в один из этих онлайн-редакторов. Если ваш онлайн-редактор не поддерживает раздельные панели для редактирования JavaScript/CSS кода, то вы можете встроить код в HTML с помощью тегов <code><script></code>/<code><style></code>.</p> + +<div class="note"> +<p><strong>Примечание</strong>. Если у вас что-то не получается — попросите о помощи. Более подробная информация находится в секции {{anch("Assessment or further help")}} в конце этой страницы.</p> +</div> + +<h2 id="Краткое_описание_проекта">Краткое описание проекта</h2> + +<p>Наша веселая демонстрация шаров - это весело, но теперь мы хотим сделать ее немного более интерактивной, добавив контролируемый пользователем злой круг, который будет есть шары, если он их поймает. Мы также хотим проверить ваши навыки создания объектов, создав общий объект <code>Shape()</code>, который могут наследовать наши шары и злой круг. Наконец, мы хотим добавить счетчик очков, чтобы отслеживать количество оставшихся шаров для захвата.</p> + +<p>Следующий скриншот дает вам представление о том, как должна выглядеть готовая программа:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13875/bouncing-evil-circle.png" style="display: block; margin: 0 auto;"></p> + +<ul> +</ul> + +<p>Чтобы дать вам больше идеи, посмотрите на <a href="https://mdn.github.io/learning-area/javascript/oojs/assessment/">законченный пример</a> (не заглядывая в исходный код!)</p> + +<h2 id="Шаги_по_завершению">Шаги по завершению</h2> + +<p>В следующих разделах описывается, что вам нужно делать.</p> + +<h3 id="Создание_наших_новых_объектов">Создание наших новых объектов</h3> + +<p>Прежде всего, измените существующий конструктор <code>Ball()</code> так, чтобы он стал конструктором <code>Shape()</code> и добавил новый конструктор <code>Ball()</code>:</p> + +<ol> + <li>Конструктор <code>Shape()</code> должен определять свойства <code>x</code>, <code>y</code>, <code>velX</code> и <code>velY</code>, так же, как и конструктор <code>Ball()</code>, но не свойства <code>color</code> и <code>size</code>.</li> + <li>Он также должен определить новое свойство<code>exists</code>, которое используется для отслеживания наличия шаров в программе (не было съедено злым кругом). Это должно быть логическое (<code>true</code> / <code>false</code>).</li> + <li>Конструктор <code>Ball()</code> должен наследовать свойства <code>x</code>, <code>y</code>, <code>velX</code>, <code>velY</code> и <code>exists</code> из конструктора <code>Shape()</code>.</li> + <li>Он также должен определить свойство <code>color</code> и <code>size</code>, как это сделал оригинальный конструктор <code>Ball()</code>.</li> + <li>Не забудьте установить <code>prototype</code> и <code>constructor</code> конструктора <code>Ball()</code> соответствующим образом.</li> +</ol> + +<p>Определения меток шара <code>draw()</code>, <code>update()</code> и <code>collisionDetect()</code> должны быть такими же, как и раньше.</p> + +<p>Вам также нужно добавить новый параметр в новый вызов конструктора <code>new Ball() ( ... )</code> - параметр <code>exists</code> должен быть 5-м параметром и ему должно быть присвоено значение <code>true</code>.</p> + +<p>На этом этапе попробуйте перезагрузить код - он должен работать так же, как и раньше, с нашими перепроектированными объектами.</p> + +<h3 id="Определение_EvilCircle">Определение EvilCircle()</h3> + +<p>Теперь пришло время встретить плохого парня - <code>EvilCircle()</code>! Наша игра будет включать только один злой круг, но мы все еще будем определять его с помощью конструктора, который наследует от <code>Shape()</code>, чтобы дать вам некоторую практику. Возможно, вам захочется добавить еще один круг в приложение, которое может контролироваться другим игроком или иметь несколько злобных окружений, управляемых компьютером. Вы, вероятно, не собираетесь захватить мир одним злым кругом, но он будет делать для этой оценки.</p> + +<p>Конструктор <code>EvilCircle()</code> должен наследовать <code>x</code>, <code>y</code>, <code>velX</code>, <code>velY</code> и <code>exists</code> из <code>Shape()</code>, но <code>velX</code> и <code>velY</code> должны всегда равняться 20.</p> + +<p>Вы должны сделать что-то вроде <code>Shape.call(this, x, y, 20, 20, exists);</code></p> + +<p>Он также должен определить свои собственные свойства следующим образом:</p> + +<ul> + <li><code>color</code> — <code>'white'</code></li> + <li><code>size</code> — <code>10</code></li> +</ul> + +<p>Опять же, не забудьте определить свои унаследованные свойства как параметры в конструкторе и правильно установить свойства <code>prototype</code> и <code>constructor</code>.</p> + +<h3 id="Defining_EvilCircles_methods">Defining EvilCircle()'s methods</h3> + +<p><code>EvilCircle()</code> должен иметь четыре метода, как описано ниже.</p> + +<h4 id="draw"><code>draw()</code></h4> + +<p>Этот метод имеет ту же цель, что и метод <code>draw()</code> метода <code>Ball()</code>: он рисует экземпляр объекта на холсте. Он будет работать очень схожим образом, поэтому вы можете начать с копирования определения <code>Ball.prototype.draw</code>. Затем вы должны внести следующие изменения:</p> + +<ul> + <li>Мы хотим, чтобы злой круг не был заполнен, а скорее имел внешнюю линию (удар). Вы можете добиться этого, обновив <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle">fillStyle</a></code> и <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fill">fill()</a></code> до <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle">strokeStyle</a></code> и s<code><a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/stroke">stroke()</a></code>.</li> + <li>Мы также хотим сделать ход немного толще, так что вы можете увидеть злой круг немного легче. Этого можно добиться, установив значение для <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineWidth">lineWidth</a></code> где-нибудь после вызова <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/beginPath">beginPath()</a></code> (3 будем делать).</li> +</ul> + +<h4 id="checkBounds"><code>checkBounds()</code></h4> + +<p>Этот метод будет делать то же самое, что и первая часть функции <code>Ball()</code>'s <code>update()</code>, чтобы посмотреть, не исчезнет ли злой круг от края экрана и не прекратит это делать. Опять же, вы можете просто скопировать определение <code>Ball.prototype.update</code>, но есть несколько изменений, которые вы должны сделать:</p> + +<ul> + <li>Избавьтесь от последних двух строк - мы не хотим автоматически обновлять позицию злого круга на каждом кадре, потому что мы будем перемещать его каким-то другим способом, как вы увидите ниже.</li> + <li>Внутри операторов <code>if()</code>, если тесты возвращают true, мы не хотим обновлять <code>velX</code> / <code>velY</code>; мы хотим вместо этого изменить значение <code>x</code> / <code>y</code>, так что злой круг возвращается на экран немного. Добавление или вычитание (по мере необходимости) свойства <code>size</code> злого круга имеет смысл.</li> +</ul> + +<h4 id="setControls"><code>setControls()</code></h4> + +<p>Этот метод добавит прослушиватель событий <code>onkeydown</code> к объекту <code>window</code>, чтобы при нажатии определенных клавиш клавиатуры мы могли перемещать злой круг вокруг. Следующий код должен быть помещен внутри определения метода:</p> + +<pre class="brush: js">var _this = this; +window.onkeydown = function(e) { + if (e.keyCode === 65) { + _this.x -= _this.velX; + } else if (e.keyCode === 68) { + _this.x += _this.velX; + } else if (e.keyCode === 87) { + _this.y -= _this.velY; + } else if (e.keyCode === 83) { + _this.y += _this.velY; + } + }</pre> + +<p>Поэтому, когда нажата клавиша, проконсультируется о свойствах <a href="https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode">keyCode</a> объекта события, чтобы увидеть, какая клавиша нажата. Если это один из четырех, представленных указанными ключевыми кодами, тогда злой круг будет перемещаться влево / вправо / вверх / вниз.</p> + +<ul> + <li>Для бонусного пункта сообщите нам, к каким ключам относятся указанные коды ключей.</li> + <li>В другой бонусной точке вы можете сказать нам, почему нам пришлось установить <code>var _this = this</code>; в позиции, в которой он находится? Это как-то связано с функциональной областью.</li> +</ul> + +<h4 id="collisionDetect"><code>collisionDetect()</code></h4> + +<p>Этот метод будет действовать очень похоже на метод <code>collisionDetect()</code> в <code>Ball()</code>, поэтому вы можете использовать его в качестве основы для этого нового метода. Но есть несколько отличий:</p> + +<ul> + <li>В внешнем выражении <code>if</code> вам больше не нужно проверять, совпадает ли текущий мяч на итерации с шаром, который выполняет проверку, потому что он больше не является мячиком, это злой круг! Вместо этого вам нужно выполнить проверку, чтобы проверить, существует ли проверенный шар (с каким свойством вы могли бы это сделать?). Если этого не существует, он уже был съеден злым кругом, поэтому нет необходимости проверять его снова.</li> + <li>Во внутреннем <code>if</code>-выражении вы больше не хотите, чтобы объекты меняли цвет при обнаружении столкновения - вместо этого вы хотите установить любые шары, которые сталкиваются с злым кругом, чтобы больше не существовать (опять же, как вы думаете, d сделать это?).</li> +</ul> + +<h3 id="Приведение_злого_круга_в_программу">Приведение злого круга в программу</h3> + +<p>Теперь мы определили злой круг, нам нужно на самом деле заставить его появиться на нашей сцене. Для этого вам нужно внести некоторые изменения в функцию <code>loop()</code>.</p> + +<ul> + <li>Прежде всего, создайте новый экземпляр объекта злого круга (указав необходимые параметры), затем вызовите его метод <code>setControls()</code>. Вам нужно только сделать эти две вещи один раз, а не на каждой итерации цикла.</li> + <li>В точке, где вы прокручиваете каждый шар и вызываете функции <code>draw()</code>, <code>update()</code> и <code>collisionDetect()</code> для каждого из них, делайте так, чтобы эти функции вызывались только в том случае, если текущий шар существует.</li> + <li>На каждой итерации цикла вызовите методы draw <code>draw()</code>, <code>checkBounds()</code> и <code>collisionDetect()</code> для злого шарика.</li> +</ul> + +<h3 id="Реализация_счетчика_баллов">Реализация счетчика баллов</h3> + +<p>Чтобы выполнить счетчик счетчиков, выполните следующие действия:</p> + +<ol> + <li>В своем HTML-файле добавьте элемент {{HTMLElement ("p")}} непосредственно под элементом {{HTMLElement ("h1")}}, содержащим текст «Ball count:».</li> + <li>В вашем файле CSS добавьте следующее правило внизу: + <pre class="brush: css">p { + position: absolute; + margin: 0; + top: 35px; + right: 5px; + color: #aaa; +}</pre> + </li> + <li>В своем JavaScript сделайте следующие обновления: + <ul> + <li>Создайте переменную, которая хранит ссылку на абзац.</li> + <li>Держите подсчет количества шаров на экране в некотором роде.</li> + <li>Увеличьте количество и покажите обновленное количество шаров каждый раз, когда шар добавляется в сцену.</li> + <li>Уменьшите счет и покажите обновленное количество мячей каждый раз, когда злой круг ест шарик (его не существует).</li> + </ul> + </li> +</ol> + +<h2 id="Советы_и_подсказки">Советы и подсказки</h2> + +<ul> + <li>Эта оценка довольно сложная. Делайте каждый шаг медленно и осторожно.</li> + <li>Может быть, идея сохранить отдельную копию демонстрации после того, как вы получите каждый этап работы, так что вы можете вернуться к ней, если позже окажетесь в беде.</li> +</ul> + +<h2 id="Assessment">Assessment</h2> + +<p>Если вы проводите эту оценку в рамках организованного курса, вы должны уметь отдать свою работу своему учителю / наставнику для маркировки. Если вы самообучаетесь, то вы можете получить руководство по маркировке довольно легко, задав <a href="https://discourse.mozilla.org/t/adding-features-to-our-bouncing-balls-demo-assessment/24689">тему обсуждения для этого упражнения</a> или в IRC-канале <a href="irc://irc.mozilla.org/mdn">#mdn</a> в <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Сначала попробуйте упражнение - ничего не выиграть от обмана!</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}</p> + + + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">Object basics</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">Object-oriented JavaScript for beginners</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Object prototypes</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Inheritance in JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Working with JSON data</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Adding features to our bouncing balls demo</a></li> +</ul> + + + +<div class="s3gt_translate_tooltip_mini_box" id="s3gt_translate_tooltip_mini" style="background: initial !important; border: initial !important; border-radius: initial !important; border-collapse: initial !important; direction: ltr !important; font-weight: initial !important; height: initial !important; letter-spacing: initial !important; max-width: initial !important; min-height: initial !important; margin: auto !important; outline: initial !important; padding: initial !important; position: absolute; text-align: initial !important; text-shadow: initial !important; width: initial !important; display: initial !important; color: inherit !important; font-size: 13px !important; font-family: X-LocaleSpecific, sans-serif, Tahoma, Helvetica !important; line-height: 13px !important; vertical-align: top !important; white-space: inherit !important; left: 112px; top: 698px; opacity: 0;"> +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_logo" style="width: 12px; height: 12px; border-radius: 4px;" title="Перевести выделенный фрагмент"></div> + +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_sound" style="width: 12px; height: 12px; border-radius: 4px;" title="Прослушать"></div> + +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_copy" style="width: 12px; height: 12px; border-radius: 4px;" title="Скопировать текст в буфер обмена"></div> +</div> diff --git a/files/ru/learn/javascript/objects/basics/index.html b/files/ru/learn/javascript/objects/basics/index.html new file mode 100644 index 0000000000..a4e7cc0071 --- /dev/null +++ b/files/ru/learn/javascript/objects/basics/index.html @@ -0,0 +1,257 @@ +--- +title: Основы объектов в JavaScript +slug: Learn/JavaScript/Объекты/Основы +tags: + - JavaScript + - ООП +translation_of: Learn/JavaScript/Objects/Basics +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">В этой статье мы рассмотрим объекты в JavaScript. Мы будем разбирать основы синтаксиса объектов JavaScript и заново изучим некоторый функционал JavaScript, который мы уже исследовали ранее на курсе, подтвердив тот факт, что большая часть функционала, с которым мы уже столкнулись, в действительности является объектами.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Необходимые знания:</th> + <td>Элементарная компьютерная грамотность, базовое понимание HTML и CSS, знакомство с основами JavaScript (см. <a href="/ru/docs/Learn/JavaScript/Первые_шаги">Первые шаги</a> и <a href="/ru/docs/Learn/JavaScript/Building_blocks">Структурные элементы</a>).</td> + </tr> + <tr> + <th scope="row">Цель:</th> + <td>Понимать основу теории перед началом объектно-ориентированного программирования, как это связано с JavaScript ("большинство сущностей являются объектами"), и как начать работу с объектами JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Основы_объектов">Основы объектов</h2> + +<p>Объект — это совокупность связанных данных и/или функциональных возможностей. Обычно состоят из нескольких переменных и функций, которые называются свойства и методы, если они находятся внутри объектов. Разберём пример, чтобы показать, как они выглядят.</p> + +<p>Чтобы начать, скопируйте себе <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs.html">oojs.html</a> файл. В нём содержится очень мало: {{HTMLElement("script")}} элемент для написания в нём исходного кода. Мы будем использовать это как основу для изучения основ синтаксиса объектов. Во время работы с этим примером у вас должна быть открытая <a href="/ru/docs/Learn/Discover_browser_developer_tools#%D0%9A%D0%BE%D0%BD%D1%81%D0%BE%D0%BB%D1%8C_JavaScript">консоль JavaScript инструментов разработчика</a>, готовая к вводу некоторых команд.</p> + +<p>Как и во многих случаях в JavaScript, создание объекта часто начинается с определения и инициализации переменной. Попробуйте ввести следующий код JavaScript в ваш файл, а затем сохраните файл и обновите страницу браузера:</p> + +<pre class="brush: js notranslate">const person = {};</pre> + +<p>Если Вы введёте <code>person</code> в текстовое JS консоль и нажмёте клавишу Enter, должен получиться следующий результат:</p> + +<pre class="brush: js notranslate"><code class="language-js">Object</code><code> </code>{ }</pre> + +<p>Поздравляем, Вы только что создали Ваш первый объект. Но это пустой объект, поэтому мы не можем с ним ничего сделать. Давайте обновим наш объект, чтобы он выглядел так:</p> + +<pre class="brush: js notranslate">const person = { + name: ['Bob', 'Smith'], + age: 32, + gender: 'male', + interests: ['music', 'skiing'], + bio: function() { + alert(this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.'); + }, + greeting: function() { + alert('Hi! I\'m ' + this.name[0] + '.'); + } +}; +</pre> + +<p>После сохранения и обновления, попробуйте ввести что-нибудь следующее в консоль JavaScript браузера:</p> + +<pre class="brush: js notranslate"><code class="language-js">person<span class="punctuation token">.</span>name</code> +person.name[0] +person.age +person.interests[1] +person.bio() +person.greeting()</pre> + +<p>Теперь внутри объекта есть некоторые данные и функционал, и теперь можно получить доступ к ним с помощью некоторого лёгкого и простого синтаксиса!</p> + +<div class="note"> +<p><strong>Примечание</strong>: Если у вас возникли проблемы с применением файла в работе, попробуйте сравнить ваш код с нашей версией — см. <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-finished.html">oojs-finished.html</a> (также <a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-finished.html">see it running live</a>). Одна из распространенных ошибок, когда Вы начинаете с объектами ставить запятую в конце последнего члена — это приводит к ошибке.</p> +</div> + +<p>Итак что здесь происходит? Объект состоит из нескольких элементов, каждый из которых имеет своё название (пример <code>name</code> и <code>age</code> выше), и значение (пример <code>['Bob', 'Smith']</code> и <code>32</code>). Каждая пара название/значение должны быть разделены запятой, а название и значение в каждом случае разделяются двоеточием. Синтаксис всегда следует этому образцу:</p> + +<pre class="brush: js notranslate">const objectName = { + member1Name: member1Value, + member2Name: member2Value, + member3Name: member3Value +};</pre> + +<p>Значение члена объекта может быть чем угодно — в нашем объекте person есть строка, число, два массива, и две функции. Первые четыре элемента это элементы данных, относящиеся к <strong>свойствам</strong> объекта. Последние два элемента являются функциями, которые позволяют объекту что-то сделать с элементами данных, и называются <strong>методами</strong> объекта.</p> + +<p>Такие объекты называются <strong>литералами объекта</strong> (<strong>object literal</strong>) — мы буквально вписали все содержимое объекта для его создания. Этот способ сильно отличается от объектов реализованных классами, которые мы рассмотрим позже.</p> + +<p>Очень часто для создания объекта используется литерал объекта когда вам нужно каким-то образом перенести ряд структурированных, связанных элементов данных, например, отправляя запрос на сервер, для размещения их в базе данных. Отправка одного объекта намного эффективнее, чем отправка нескольких элементов по отдельности, и с ним легче работать чем с массивом, если требуется идентифицировать отдельные элементы по имени. </p> + +<h2 id="Точечная_запись_Dot_notation">Точечная запись (Dot notation)</h2> + +<p>Выше Вы получили доступ к свойствам и методам используя <strong>точечную запись (dot notation). </strong>Имя объекта (person) действует как <strong>пространство имен (namespace) </strong>— оно должно быть введено первым, для того чтобы получить доступ ко всему что заключено (<strong>encapsulated)</strong> внутри объекта. Далее Вы пишете точку, затем элемент, к которому хотите получить доступ — это может быть имя простого свойства, элемент массива, или вызов одного из методов объекта, например:</p> + +<pre class="brush: js notranslate">person.age +person.interests[1] +person.bio()</pre> + +<h3 id="Внутренние_пространства_имен_Sub-namespaces">Внутренние пространства имен (Sub-namespaces)</h3> + +<p>Можно даже сделать значением элемента объекта другой объект. Например, попробуйте изменить значение свойства name с такого</p> + +<pre class="brush: js notranslate">name: ['Bob', 'Smith'],</pre> + +<p>на такое</p> + +<pre class="brush: js notranslate">name : { + first: 'Bob', + last: 'Smith' +},</pre> + +<p>Здесь мы фактически создаем <strong>внутреннее пространство имен (sub-namespace). </strong>Это звучит сложно, но на самом деле это не так — для доступа к этим элементам Вам нужно сделать один дополнительный шаг с еще одной точкой. Попробуйте в консоли браузера следующее: </p> + +<pre class="brush: js notranslate">person.name.first +person.name.last</pre> + +<p><strong>Важно</strong>: На этом этапе вам также нужно будет пересмотреть код метода и изменить все экземпляры с</p> + +<pre class="brush: js notranslate">name[0] +name[1]</pre> + +<p>на</p> + +<pre class="brush: js notranslate">name.first +name.last</pre> + +<p>Иначе ваши методы больше не будут работать.</p> + +<h2 id="Скобочная_запись_Bracket_notation">Скобочная запись (Bracket notation)</h2> + +<p>Существует другой способ получить свойства объекта — использовать скобочную запись (bracket notation). Вместо написания этого кода:</p> + +<pre class="brush: js notranslate">person.age +person.name.first</pre> + +<p>Вы можете использовать следующий</p> + +<pre class="brush: js notranslate">person['age'] +person['name']['first']</pre> + +<p>Это выглядит очень похоже на то, как Вы получаете элементы массива, и в принципе это так и есть — вместо использования числовых индексов для выбора элемента, Вы ассоциируете имя свойства для каждого значения. Ничего удивительного, что эти объекты иногда называют ассоциативными массивами — они сопоставляют строки со значениями так же, как массивы сопоставляют числовые индексы со значениями.</p> + +<h2 id="Запись_элементов_в_объект">Запись элементов в объект</h2> + +<p>До сих пор мы рассмастривали только возврат (или получение) элементов объекта — Вы так же можете установить (обновить) значение элемента объекта просто объявив элемент, который Вы хотите установить (используя точечную или скобочную запись), например:</p> + +<pre class="brush: js notranslate">person.age = 45; +person['name']['last'] = 'Cratchit';</pre> + +<p>Попробуйте ввести эти строки, а затем снова верните элементы, чтобы увидеть, как они изменились</p> + +<pre class="brush: js notranslate">person.age +person['name']['last']</pre> + +<p>Вы можете не просто обновлять и устанавливать значения свойств и методов объекта, а так же устанавливать совершенно новые элементы. Попробуйте их в консоли JS:</p> + +<pre class="brush: js notranslate">person['eyes'] = 'hazel'; +person.farewell = function() { alert("Bye everybody!"); }</pre> + +<p>Теперь Вы можете проверить ваши новые элементы:</p> + +<pre class="brush: js notranslate">person['eyes'] +person.farewell()</pre> + +<p>Одним из полезных аспектов скобочной записи является то, что с ее помощью можно динамически задавать не только значения элементов, но и их имена. Предположим, что мы хотим, чтобы пользователи могли хранить пользовательские типы данных, введя имя и значение элемента в два следующих поля? Мы могли бы получить эти значения следующим образом:</p> + +<pre class="brush: js notranslate">let myDataName = nameInput.value; +let myDataValue = nameValue.value;</pre> + +<p>Затем мы можем добавить имя и значение этого нового элемента в объект <code>person</code> таким образом:</p> + +<pre class="brush: js notranslate">person[myDataName] = myDataValue;</pre> + +<p>Чтобы проверить это, попробуйте добавить следующие строки в свой код, после закрывающей скобки объекта <code>person</code> :</p> + +<pre class="brush: js notranslate">let myDataName = 'height'; +let myDataValue = '1.75m'; +person[myDataName] = myDataValue;</pre> + +<p>Теперь попробуйте сохранить и обновить, затем введите следующее в консоль браузера:</p> + +<pre class="brush: js notranslate">person.height</pre> + +<p>Добавление свойства объекта с использованием вышеописанного метода невозможно с использованием точечной записи, которая может принимать только литеральное имя элемента, а не значение переменной указывающее на имя.</p> + +<h2 id="Что_такое_this">Что такое "this"?</h2> + +<p>Возможно, вы заметили что-то странное в наших методах. Посмотрите на этот пример:</p> + +<pre class="brush: js notranslate">greeting: function() { + alert('Hi! I\'m ' + this.name.first + '.'); +}</pre> + +<p>Вы, вероятно, задаетесь вопросом, что такое "this"? Ключевое слово <code>this</code>, ссылается на текущий объект, внутри которого пишется код — поэтому в нашем случае <code>this</code> равен объекту <code>person</code>. Но почему просто не написать <code>person</code>? Как Вы увидите в статье <a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">Object-oriented JavaScript for beginners</a> (Объектно-ориентированный JavaScript для начинающих), когда мы начинаем создавать конструкторы и т.д., <code>this</code> очень полезен — он всегда будет гарантировать, что используется верное значение, когда контекст элемента изменяется (например, два разных экземпляра объекта <code>person</code> могут иметь разные имена, но захотят использовать свое собственное имя при приветствии.</p> + +<p>Давайте проиллюстритуем, что мы имеем в виду, с упрощенной парой объектов <code>person</code> :</p> + +<pre class="brush: js notranslate">const person1 = { + name: 'Chris', + greeting: function() { + alert('Hi! I\'m ' + this.name + '.'); + } +} + +const person2 = { + name: 'Brian', + greeting: function() { + alert('Hi! I\'m ' + this.name + '.'); + } +}</pre> + +<p>В этом случае, <code>person1.greeting()</code> выведет "Hi! I'm Chris.". <code>person2.greeting()</code>, с другой стороны, выведет "Hi! I'm Brian.", хотя код метода одинаковый в обоих случаях. Как мы сказали ранее, <code>this</code> равен объекту, внутри которого находится код — это не очень полезно, когда Вы пишите литералы объектов вручную, но оно действительно помогает, когда Вы генерируете объекты динамически (например используя конструкторы). Это станет понятнее чуть позже.</p> + +<h2 id="Все_это_время_вы_использовали_объекты">Все это время вы использовали объекты</h2> + +<p>Пока Вы проходили эти примеры, Вы вероятно заметили, что точечная запись, которую Вы использовали, выглядит очень знакомо. Это потому, что Вы использовали ее на протяжении всего курса! Каждый раз, когда мы работаем над примером, использующим встроенный API браузера или объект JavaScript, мы использовали объекты, потому что такие функции построены с использованием тех же структур объектов, которые мы здесь рассматривали, хотя и более сложные, чем наши собственные пользовательские примеры. </p> + +<p>Поэтому, когда Вы использовали строковые методы, такие как:</p> + +<pre class="brush: js notranslate">myString.split(',');</pre> + +<p>Вы использовали метод доступный в экземпляре класса <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code>. Каждый раз создавая строку в вашем коде, эта строка автоматически создается как экземпляр <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code>, и поэтому имеет несколько общих методов/свойств, доступных на нем.</p> + +<p>Когда Вы обращались к объектной модели документа (DOM), используя следующие строки:</p> + +<pre class="brush: js notranslate">const myDiv = document.createElement('div'); +const myVideo = document.querySelector('video');</pre> + +<p>Вы использовали методы доступные в экземпляре класса <code><a href="/en-US/docs/Web/API/Document">Document</a></code>. Для каждой загруженной веб-страницы создается экземпляр <code><a href="/en-US/docs/Web/API/Document">Document</a></code>, называемый <code>document</code>, который представляет всю структуру страницы, ее содержимое и другие функции, такие как URL-адрес. Опять же, это означает, что он имеет несколько общих методов/свойств, доступных на нем.</p> + +<p>То же самое относится и к любому другому встроенному объекту/API, который вы использовали — <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a></code>, <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math">Math</a></code>, и т. д.</p> + +<p>Обратите внимание, что встроенные объекты/API не всегда создают экземпляры объектов автоматически. Как пример, <a href="/ru/docs/Web/API/Notifications_API">Notifications API</a> — который позволяет новым браузерам запускать системные уведомления, требует, чтобы Вы создавали новый экземпляр объекта с помощью конструктора для каждого уведомления, которое Вы хотите запустить. Попробуйте ввести следующее в консоль JavaScript:</p> + +<pre class="brush: js notranslate">const myNotification = new Notification('Hello!');</pre> + +<p>Опять же, мы рассмотрим конструкторы в следующей статье.</p> + +<div class="note"> +<p><strong>Примечание</strong>: Полезно подумать о том, как объекты взаимодействуют посредством передачи сообщений - когда объекту требуется другой объект для выполнения какого-либо действия, он часто отправляет сообщение другому объекту через один из его методов и ждет ответа, который мы знаем как возвращаемое (return) значение.</p> +</div> + +<h2 id="Резюме">Резюме</h2> + +<p>Поздравляем, Вы достигли конца нашей первой статьи о объектах JS, теперь у вас должно быть хорошее представление о том, как работать с объектами в JavaScript - в том числе создавать свои собственные простые объекты. Вы также должны понимать, что объекты очень полезны в качестве структур для хранения связанных данных и функциональности - если бы мы пытались отслеживать все свойства и методы в нашем объекте <code>person</code> как отдельные переменные и функции, это было неэффективно, и мы бы рисковали столкнуться с другими переменными и функциями с такими же именами. Объекты позволяют нам безопасно хранить информацию в своем собственном блоке, вне опасности.</p> + +<p>В следующей статье мы начнем рассматривать теорию объектно-ориентированного программирования (OOП) и как эти техники могут быть использованны в JavaScript </p> + +<p>{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}</p> + +<h2 id="В_этом_модуле">В этом модуле</h2> + +<ul> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B">Основы объекта</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Object-oriented_JS">Объектно-ориентированный JavaScript для начинающих</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Object_prototypes">Прототипы объектов</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Inheritance">Наследование в JavaScript</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/JSON">Работа с данными JSON</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Object_building_practice">Практика построения объектов</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Adding_bouncing_balls_features">Добавление функций в нашу демонстрацию прыгающих шаров</a></li> +</ul> diff --git a/files/ru/learn/javascript/objects/index.html b/files/ru/learn/javascript/objects/index.html new file mode 100644 index 0000000000..9acc354feb --- /dev/null +++ b/files/ru/learn/javascript/objects/index.html @@ -0,0 +1,47 @@ +--- +title: Введение в объекты JavaScript +slug: Learn/JavaScript/Объекты +tags: + - JavaScript + - Начинающим + - Объекты + - Руководства +translation_of: Learn/JavaScript/Objects +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">В JavaScript большинство сущностей являются объектами, начиная с самого основного функционала JavaScript, такого как строки (strings) и массивы (array), и заканчивая встроенными в браузер API. Вы можете даже создавать свои собственные объекты, чтобы инкапсулировать связанные между собой функции и переменные в эффективные пакеты и действовать как удобные хранилища данных. Понимание объектно-ориентированной природы JavaScript очень важно, если Вы хотите продолжить дальнейшее более углубленное изучение языка. Поэтому мы предоставляем Вам данный модуль, чтобы помочь Вам разобраться в этом. Здесь мы детально обучим Вас теории и синтаксису объектов, а затем рассмотрим, как создавать свои собственные объекты. </p> + +<h2 id="Необходимые_знания">Необходимые знания</h2> + +<p>Перед тем, как начать изучение данного модуля, Вы должны иметь некоторое представление о HTML и CSS. Мы советуем Вам поработать над разделами <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Introduction">Введение в HTML</a> и <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS">Введение в CSS</a> перед изучением этого модуля JavaScript.</p> + +<p>Также Вам необходимо знать основы JavaScript перед подробным изучением объектов JavaScript. Предварительно поработайте с разделами <a href="/en-US/docs/Learn/JavaScript/First_steps">Первые шаги в JavaScript</a> и <a href="/en-US/docs/Learn/JavaScript/Building_blocks">Структурные элементы в JavaScript</a> перед началом изучения данного модуля.</p> + +<div class="note"> +<p><span style="font-size: 14px;"><strong>Примечание</strong></span>: Если Вы работаете за компьютером/планшетом/другим устройством, на котором у Вас нет возможности создавать собственные файлы, постарайтесь поработать с примерами кода на платформах онлайн-программирования, таких, как <a href="http://jsbin.com/">JSBin</a> or <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Руководства">Руководства</h2> + +<dl> + <dt><a href="/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B">Основы объектов</a></dt> + <dd>В первой статье мы рассмотрим объекты в JavaScript. Мы будем разбирать основы синтаксиса объектов JavaScript и заново изучим некоторый функционал JavaScript, который мы уже исследовали ранее на курсе, подтвердив тот факт, что большая часть функционала, с которым мы уже столкнулись, в действительности является объектами.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">Объектно-ориентированный JavaScript для начинающих</a></dt> + <dd>Закончив с основами, мы сфокусируемся на объектно-ориентированном JavaScript (OOJS) — эта статья представляет основы теории объектно-ориентированного программирования (ООП). Затем мы изучим, как JavaScript эмулирует классы объектов через конструктор функций, и как создавать экземпляры объектов.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Прототипы объектов</a></dt> + <dd>Прототипы - это механизм, благодаря которому объекты в JavaScript наследуют функционал друг друга, но при этом они работают иначе по сравнению с механизмами наследования в классических объектно-ориентированных языках. В этой статье мы изучим эти отличия, объясним, как работает цепочка прототипов, и рассмотрим, как свойство прототипа может быть использовано для добавления методов к существующим конструкторам.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Наследование в JavaScript</a></dt> + <dd>После знакомства с самыми жуткими подробностями OOJS, эта статья покажет, как создавать "дочерные" классы объектов (конструкторы), которые наследуют функционал от своих "родительских" классов. В дополнении, мы дадим Вам пару советов о том, где и когда можно использовать OOJS.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Работа с JSON-данными</a></dt> + <dd>Представление объектов в JavaScript (JavaScript Object Notation) (JSON) - это стандартный формат для представления структурированных данных в виде объектов JavaScript, который обычно используется для представления и передачи данных на веб-сайтах (т.е. передача некоторых данных от сервера к клиенту - таким образом они могут быть отображены на веб-странице). Вы довольно часто будете с этим сталкиваться, поэтому в данной статье мы предоставим вам все, что необходимо для работы с JSON с помощью JavaScript, в том числе доступ к элементам данных в объекте JSON и написания собственного JSON-кода.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Практика построения объектов</a></dt> + <dd>В предыдущих статьях мы рассматривали самые основные моменты в теории и синтаксисе объектов в JavaScript, дав Вам твердую основу для начала. В этой статье мы погрузимся в практические занятия, получим больше практической работы в построении собственных объектов в JavaScript, чтобы сделать кое-что веселое и красочное - несколько цветных прыгающих шариков.</dd> +</dl> + +<h2 id="Задания">Задания</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Добавление функционала к демо с прыгающими шариками</a></dt> + <dd>В этом задании, мы ожидаем, что Вы, используя демо с прыгающими шариками из предыдущей статьи как отправную точку, добавите немного нового и интересного функционала в него.</dd> +</dl> diff --git a/files/ru/learn/javascript/objects/inheritance/index.html b/files/ru/learn/javascript/objects/inheritance/index.html new file mode 100644 index 0000000000..c1565cd72f --- /dev/null +++ b/files/ru/learn/javascript/objects/inheritance/index.html @@ -0,0 +1,266 @@ +--- +title: Наследование в JavaScript +slug: Learn/JavaScript/Объекты/Inheritance +tags: + - JavaScript + - Наследование + - ООП +translation_of: Learn/JavaScript/Objects/Inheritance +--- +<p> + <audio class="audio-for-speech"></audio> +</p> + +<div class="translate-tooltip-mtz hidden"> +<div class="header"> +<div class="header-controls"></div> + +<div class="translate-icons"><img class="from" src=""> <img class="arrow"> <img class="to" src=""></div> +</div> + +<div class="translated-text"> +<div class="words"></div> + +<div class="sentences"></div> +</div> +</div> + +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">Теперь, когда объясняется большая часть подробностей OOJS, эта статья показывает, как создавать «дочерние» классы объектов (конструкторы), которые наследуют признаки из своих «родительских» классов. Кроме того, мы дадим некоторые советы о том, когда и где вы можете использовать OOJS , и посмотрим, как классы рассматриваются в современном синтаксисе ECMAScript.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Необходимые знания:</th> + <td> + <p>Базовая компьютерная грамотность, понимание основ HTML и CSS, знакомство с основами JavaScript (см. <a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9F%D0%B5%D1%80%D0%B2%D1%8B%D0%B5_%D1%88%D0%B0%D0%B3%D0%B8">Первые шаги</a> и <a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Building_blocks">Структурные элементы</a>) and основы Объектно-ориентированного JS (см. <a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B">Введение в объекты</a>).</p> + </td> + </tr> + <tr> + <th scope="row">Цель:</th> + <td>Понять, как можно реализовать наследование в JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Прототипное_наследование">Прототипное наследование</h2> + +<p>До сих пор мы видели некоторое наследование в действии - мы видели, как работают прототипы и как элементы наследуются, поднимаясь по цепочке. Но в основном это связано с встроенными функциями браузера. Как создать объект в JavaScript, который наследует от другого объекта?</p> + +<p>Давайте рассмотрим, как это сделать на конкретном примере.</p> + +<h2 id="Начало_работы">Начало работы</h2> + +<p>Прежде всего сделайте себе локальную копию нашего файла <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-start.html">oojs-class-inheritance-start.html</a> (он также работает <a href="https://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-start.html">в режиме реального времени</a>). В файле вы найдете тот же пример конструктора <code>Person()</code>, который мы использовали на протяжении всего модуля, с небольшим отличием - мы определили внутри конструктора только лишь свойства:</p> + +<pre class="brush: js notranslate">function Person(first, last, age, gender, interests) { + this.name = { + first, + last + }; + this.age = age; + this.gender = gender; + this.interests = interests; +};</pre> + +<p><em>Все</em> методы определены в прототипе конструктора. Например:</p> + +<pre class="brush: js notranslate">Person.prototype.greeting = function() { + alert('Hi! I\'m ' + this.name.first + '.'); +};</pre> + +<div class="note"> +<p><strong>Примечание</strong>. В исходном коде вы также увидите определенные методы <code>bio()</code> и <code>farewell()</code>. Позже вы увидите, как они могут быть унаследованы другими конструкторами.</p> +</div> + +<p>Скажем так, мы хотели создать класс <code>Teacher</code>, подобный тому, который мы описали в нашем первоначальном объектно-ориентированном определении, которое наследует всех членов от <code>Person</code>, но также включает в себя:</p> + +<ol> + <li>Новое свойство, <code>subject</code> - оно будет содержать предмет, который преподает учитель.</li> + <li>Обновленный метод <code>greeting()</code>, который звучит немного более формально, чем стандартный метод <code>greeting()</code>— более подходит для учителя, обращающегося к некоторым ученикам в школе.</li> +</ol> + +<h2 id="Определение_функции-конструктора_Teacher">Определение функции-конструктора Teacher()</h2> + +<p>Первое, что нам нужно сделать, это создать конструктор <code>Teacher()</code> - добавьте ниже следующий код:</p> + +<pre class="brush: js notranslate">function Teacher(first, last, age, gender, interests, subject) { + Person.call(this, first, last, age, gender, interests); + + this.subject = subject; +}</pre> + +<p>Это похоже на конструктор Person во многих отношениях, но здесь есть что-то странное, что мы не видели раньше - функцию <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call">call()</a></code>. Эта функция в основном позволяет вам вызывать функцию, определенную где-то в другом месте, но в текущем контексте. Первый параметр указывает значение <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this">this</a></code>, которое вы хотите использовать при выполнении функции, а остальные параметры - те, которые должны быть переданы функции при ее вызове.</p> + +<p>Мы хотим, чтобы конструктор <code>Teacher()</code> принимал те же параметры, что и конструктор <code>Person()</code>, от которго он наследуется, поэтому мы указываем их как параметры в вызове <code>call()</code>.</p> + +<p>Последняя строка внутри конструктора просто определяет новое свойство <code>subject</code>, которое будут иметь учителя, и которого нет у Person().</p> + +<p>В качестве примечания мы могли бы просто сделать это:</p> + +<pre class="brush: js notranslate">function Teacher(first, last, age, gender, interests, subject) { + this.name = { + first, + last + }; + this.age = age; + this.gender = gender; + this.interests = interests; + this.subject = subject; +}</pre> + +<p>Но это просто переопределяет свойства заново, а не наследует их от <code>Person()</code>, так что теряется смысл того, что мы пытаемся сделать. Он также занимает больше строк кода.</p> + +<h3 id="Наследование_от_конструктора_без_параметров">Наследование от конструктора без параметров</h3> + +<p>Обратите внимание, что если конструктор, от которого вы наследуете, не принимает значения своего свойства из параметров, вам не нужно указывать их в качестве дополнительных аргументов в <code>call()</code>. Так, например, если у вас было что-то действительно простое:</p> + +<pre class="brush: js notranslate">function Brick() { + this.width = 10; + this.height = 20; +}</pre> + +<p>Вы можете наследовать свойства <code>width</code> и <code>height</code>, выполнив это (как и другие шаги, описанные ниже, конечно):</p> + +<pre class="brush: js notranslate">function BlueGlassBrick() { + Brick.call(this); + + this.opacity = 0.5; + this.color = 'blue'; +}</pre> + +<p>Обратите внимание, что мы указали только <code>this</code> внутри <code>call()</code> - никаких других параметров не требуется, поскольку мы не наследуем никаких свойств родителя, которые задаются через параметры.</p> + +<h2 id="Установка_Teachers_prototype_и_конструктор_ссылок">Установка Teacher()'s prototype и конструктор ссылок</h2> + +<p>Пока все хорошо, но у нас есть проблема. Мы определили новый конструктор и у него есть свойство <code>prototype</code>, которое по умолчанию просто содержит ссылку на саму конструкторскую функцию. Он не содержит методов свойства <code>prototype</code> конструктора <code>Person</code>. Чтобы увидеть это, введите <code>Object.getOwnPropertyNames(Teacher.prototype)</code> в поле ввода текста или в вашу консоль JavaScript. Затем введите его снова, заменив <code>Teacher</code> на <code>Person</code>. Новый конструктор <em>не наследует</em> эти методы. Чтобы увидеть это, сравните выводы в консоль <code>Person.prototype.greeting</code> и <code>Teacher.prototype.greeting</code>. Нам нужно заставить <code>Teacher()</code> наследовать методы, определенные на прототипе <code>Person()</code>. Итак, как мы это делаем?</p> + +<ol> + <li>Добавьте следующую строку ниже своего предыдущего добавления: + <pre class="brush: js notranslate">Teacher.prototype = Object.create(Person.prototype);</pre> + Здесь наш друг <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create">create()</a></code> снова приходит на помощь. В этом случае мы используем его для создания нового объекта и делаем его значением <code>Teacher.prototype</code>. Новый объект имеет свой прототип <code>Person.prototype</code> и, следовательно, наследует, если и когда это необходимо, все доступные методы <code>Person.prototype</code>.</li> + <li>Нам нужно сделать еще одну вещь, прежде чем двигаться дальше. После добавления последней строки, <code>Teacher.prototype.constructor</code> стало равным <code>Person()</code>, потому что мы просто устанавливаем <code>Teacher.prototype</code> для ссылки на объект, который наследует его свойства от <code>Person.prototype</code>! Попробуйте сохранить код, загрузите страницу в браузере и введите <code>Teacher.prototype.constructor</code> в консоль для проверки.</li> + <li>Это может стать проблемой, поэтому нам нужно сделать это правильно. Вы можете сделать это, вернувшись к исходному коду и добавив следующие строки внизу: + <pre class="notranslate"><code>Object.defineProperty(Teacher.prototype, 'constructor', { + value: Teacher, + enumerable: false, // false, чтобы данное свойство не появлялось в цикле for in + writable: true });</code></pre> + </li> + <li>Теперь, если вы сохраните и обновите, введите <code>Teacher.prototype.constructor</code>, чтобы вернуть <code>Teacher()</code>, плюс мы теперь наследуем <code>Person()</code>!</li> +</ol> + +<h2 id="Предоставление_Teacher_новой_функции_greeting">Предоставление Teacher() новой функции greeting()</h2> + +<p>Чтобы завершить наш код, нам нужно определить новую функцию <code>greeting()</code> в конструкторе <code>Teacher()</code>.</p> + +<p>Самый простой способ сделать это - определить его на прототипе <code>Teacher()</code> - добавить в нижнюю часть кода следующее:</p> + +<pre class="brush: js notranslate">Teacher.prototype.greeting = function() { + var prefix; + + if (this.gender === 'male' || this.gender === 'Male' || this.gender === 'm' || this.gender === 'M') { + prefix = 'Mr.'; + } else if (this.gender === 'female' || this.gender === 'Female' || this.gender === 'f' || this.gender === 'F') { + prefix = 'Mrs.'; + } else { + prefix = 'Mx.'; + } + + alert('Hello. My name is ' + prefix + ' ' + this.name.last + ', and I teach ' + this.subject + '.'); +};</pre> + +<p>Это выводит на экран приветствие учителя, в котором используется соответствующий префикс имени для своего пола, разработанный с использованием условного оператора.</p> + +<h2 id="Попробуйте_пример">Попробуйте пример</h2> + +<p>Теперь, когда вы ввели весь код, попробуйте создать экземпляр объекта из <code>Teacher()</code>, поставив ниже вашего JavaScript кода (или что-то похожее по вашему выбору):</p> + +<pre class="brush: js notranslate">var teacher1 = new Teacher('Dave', 'Griffiths', 31, 'male', ['football', 'cookery'], 'mathematics');</pre> + +<p>Теперь сохраните, обновите, и попробуйте получить доступ к свойствам и методам вашего нового объекта <code>teacher1</code>, например:</p> + +<pre class="brush: js notranslate">teacher1.name.first; +teacher1.interests[0]; +teacher1.bio(); +teacher1.subject; +teacher1.greeting(); +teacher1.farewell();</pre> + +<p>Все должно работать нормально. Запросы в строках 1, 2, 3 и 6 унаследованны от общего конструктора <code>Person()</code> (класса). Запрос в строке 4 обращается к <code>subject</code>, доступному только для более специализированного конструктора (класса) <code>Teacher()</code>. Запрос в строке 5 получил бы доступ к методу <code>greeting()</code>, унаследованному от <code>Person()</code>, но <code>Teacher()</code> имеет свой собственный метод <code>greeting()</code> с тем же именем, поэтому запрос обращается к этому методу.</p> + +<div class="note"> +<p><strong>Примечание</strong>. Если вам не удается заставить это работать, сравните свой код с нашей <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-finished.html">готовой версией</a> (см. также <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-student.html">рабочее демо</a>).</p> +</div> + +<p>Методика, которую мы здесь рассмотрили, - это не единственный способ создания наследующих классов в JavaScript, но он работает нормально и это дает вам представление о том, как реализовать наследование в JavaScript.</p> + +<p>Вам также может быть интересно узнать некоторые из новых функций {{glossary("ECMAScript")}}, которые позволяют нам делать наследование более чисто в JavaScript (см. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes">Classes</a>). Мы не рассматривали их здесь, поскольку они пока не поддерживаются очень широко в браузерах. Все остальные конструкторы кода, которые мы обсуждали в этом наборе статей, поддерживаются еще в IE9 или ранее и есть способы добиться более ранней поддержки, чем это.</p> + +<p>Обычный способ - использовать библиотеку JavaScript - большинство популярных опций имеют простой набор функций, доступных для выполнения наследования более легко и быстро. <a href="http://coffeescript.org/#classes">CoffeeScript</a> , например, предоставляет класс, расширяет и т.д.</p> + +<h2 id="Дальнейшее_упражнение">Дальнейшее упражнение</h2> + +<p>В нашем <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS#Object-oriented_programming_from_10000_meters">руководстве по Объектно-ориентированному JavaScript для начинающих</a> мы также включили класс <code>Student</code> как концепцию, которая наследует все особенности <code>Person</code>, а также имеет другой метод <code>greeting()</code> от <code>Person</code>, который гораздо более неформален, чем приветствие <code>Teacher</code>. Посмотрите, как выглядит приветствие ученика в этом разделе, и попробуйте реализовать собственный конструктор <code>Student()</code>, который наследует все функции <code>Person()</code> и реализует другую функцию <code>greeting()</code>.</p> + +<div class="note"> +<p><strong>Примечание</strong>. Если вам не удается заставить это работать, сравните свой код с нашей <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-student.html">готовой версией</a> (см. также <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-student.html">рабочее демо</a>).</p> +</div> + +<h2 id="Object_member_summary">Object member summary</h2> + +<p>Подводя итог, вы в основном получили три типа свойств / методов, о которых нужно беспокоиться:</p> + +<ol> + <li>Те, которые определены внутри функции-конструктора, которые присваиваются экземплярам объекта. Их довольно легко заметить - в вашем собственном коде они представляют собой элементы, определенные внутри конструктора, используя строки <code>this.x = x</code>; в встроенном коде браузера они являются членами, доступными только для экземпляров объектов (обычно создаются путем вызова конструктора с использованием ключевого слова <code>new</code>, например <code>var myInstance = new myConstructor ()</code>.</li> + <li>Те, которые определяются непосредственно самим конструктором, которые доступны только для конструктора. Они обычно доступны только для встроенных объектов браузера и распознаются путем непосредственной привязки к конструктору, а не к экземпляру. Например, <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys">Object.keys()</a></code>.</li> + <li>Те, которые определены в прототипе конструктора, которые наследуются всеми экземплярами и наследуют классы объектов. К ним относятся любой член, определенный в свойстве прототипа конструктора, например. <code>myConstructor.prototype.x()</code>.</li> +</ol> + +<p>Если вы не уверены, что это такое, не беспокойтесь об этом, пока вы еще учитесь и знание придет с практикой.</p> + +<h2 id="Когда_вы_используете_наследование_в_JavaScript">Когда вы используете наследование в JavaScript?</h2> + +<p>В частности, после этой последней статьи вы можете подумать: «У-у-у, это сложно». Ну, ты прав. Прототипы и наследование представляют собой некоторые из самых сложных аспектов JavaScript, но многие возможности и гибкость JavaScript вытекают из его структуры объектов и наследования и стоит понять, как это работает.</p> + +<p>В некотором смысле вы используете наследование все время. Всякий раз, когда вы используете различные функции веб-API или методы/свойства, определенные во встроенном объекте браузера, который вы вызываете в своих строках, массивах и т.д., вы неявно используете наследование.</p> + +<p>Что касается использования наследования в вашем собственном коде, вы, вероятно, не будете часто его использовать, особенно для начала и в небольших проектах. Это пустая трата времени на использование объектов и наследование только ради этого, когда они вам не нужны. Но по мере того, как ваши базы кода становятся больше, вы с большей вероятностью найдете необходимость в этом. Если вы начинаете создавать несколько объектов с подобными функциями, то создание универсального типа объекта, содержащего все общие функции и наследование этих функций в более специализированных типах объектов, может быть удобным и полезным.</p> + +<div class="note"> +<p><strong>Примечание</strong>. Из-за того, как работает JavaScript, с цепочкой прототипов и т.д., совместное использование функций между объектами часто называется <strong>делегированием</strong>. Специализированные объекты делегируют функциональность универсальному типу объекта.</p> +</div> + +<p>При использовании наследования вам рекомендуется не иметь слишком много уровней наследования и тщательно отслеживать, где вы определяете свои методы и свойства. Можно начать писать код, который временно изменяет прототипы встроенных объектов браузера, но вы не должны этого делать, если у вас нет действительно веской причины. Слишком много наследования могут привести к бесконечной путанице и бесконечной боли при попытке отладки такого кода.</p> + +<p>В конечном счете, объекты - это еще одна форма повторного использования кода, например функций или циклов, со своими конкретными ролями и преимуществами. Если вы обнаруживаете, что создаете кучу связанных переменных и функций и хотите отслеживать их все вместе и аккуратно их упаковывать, объект является хорошей идеей. Объекты также очень полезны, когда вы хотите передать коллекцию данных из одного места в другое. Обе эти вещи могут быть достигнуты без использования конструкторов или наследования. Если вам нужен только один экземпляр объекта, вам лучше всего использовать литерал объекта и вам, разумеется, не нужно наследование.</p> + +<h2 id="Резюме">Резюме</h2> + +<p>В этой статье мы рассмотрели оставшуюся часть основной теории и синтаксиса OOJS, которые, как мы думаем, вам следует знать сейчас. На этом этапе вы должны понимать основы JavaScript, ООП, прототипы и прототипное наследование, как создавать классы (конструкторы) и экземпляры объектов, добавлять функции в классы и создавать подклассы, которые наследуются от других классов.</p> + +<p>В следующей статье мы рассмотрим, как работать с JavaScript Object Notation (JSON), общим форматом обмена данными, написанным с использованием объектов JavaScript.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="http://www.objectplayground.com/">ObjectPlayground.com</a> — A really useful interactive learning site for learning about objects.</li> + <li><a href="https://www.amazon.com/gp/product/193398869X/">Secrets of the JavaScript Ninja</a>, Chapter 6 — A good book on advanced JavaScript concepts and techniques, by John Resig and Bear Bibeault. Chapter 6 covers aspects of prototypes and inheritance really well; you can probably track down a print or online copy fairly easily.</li> + <li><a href="https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/README.md#you-dont-know-js-this--object-prototypes">You Don't Know JS: this & Object Prototypes</a> — Part of Kyle Simpson's excellent series of JavaScript manuals, Chapter 5 in particular looks at prototypes in much more detail than we do here. We've presented a simplified view in this series of articles aimed at beginners, whereas Kyle goes into great depth and provides a more complex but more accurate picture.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</p> + +<h2 id="В_этом_модуле">В этом модуле</h2> + +<ul> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/Основы">Основы объекта</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/Object-oriented_JS">Объектно-ориентированный JavaScript для начинающих</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/Object_prototypes">Прототипы объектов</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/Inheritance">Наследование в JavaScript</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/JSON">Работа с данными JSON</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/Object_building_practice">Практика построения объектов</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/Adding_bouncing_balls_features">Добавление функций в нашу демонстрацию прыгающих шаров</a></li> +</ul> diff --git a/files/ru/learn/javascript/objects/json/index.html b/files/ru/learn/javascript/objects/json/index.html new file mode 100644 index 0000000000..371f254ec6 --- /dev/null +++ b/files/ru/learn/javascript/objects/json/index.html @@ -0,0 +1,353 @@ +--- +title: Работа с JSON +slug: Learn/JavaScript/Объекты/JSON +tags: + - Beginner + - JSON + - JavaScript +translation_of: Learn/JavaScript/Objects/JSON +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">Обозначение объектов JavaScript (JSON - JavaScript Object Notation) - стандартный текстовый формат для представления структурированных данных на основе синтаксиса объекта JavaScript. Он обычно используется для передачи данных в веб-приложениях (например, отправка некоторых данных с сервера клиенту,таким образом чтобы это могло отображаться на веб-странице или наоборот). Вы будете сталкиваться с этим довольно часто, поэтому в этой статье мы даем вам все, что вам нужно для работы с JSON используя JavaScript, включая парсинг JSON, чтобы вы могли получить доступ к данным внутри него при создании JSON.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Необходимые знания:</th> + <td>Базовая компьютерная грамотность, базовые знания HTML и CSS, знакомство с основами JavaScript (см. <a href="/en-US/docs/Learn/JavaScript/First_steps">First steps</a> и <a href="/en-US/docs/Learn/JavaScript/Building_blocks">Building blocks</a>) и основами OOJS (see <a href="/en-US/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction to objects</a>).</td> + </tr> + <tr> + <th scope="row">Цель:</th> + <td>Понять, как работать с данными, хранящимися в JSON, и создавать свои собственные объекты JSON.</td> + </tr> + </tbody> +</table> + +<h2 id="Нет_действительно_что_такое_JSON">Нет, действительно, что такое JSON?</h2> + +<p>{{glossary("JSON")}} - текстовый формат данных, следующий за синтаксисом объекта JavaScript, который был популяризирован <a href="https://en.wikipedia.org/wiki/Douglas_Crockford">Дугласом Крокфордом</a>. Несмотря на то, что он очень похож на буквенный синтаксис объекта JavaScript, его можно использовать независимо от JavaScript, и многие среды программирования имеют возможность читать (анализировать) и генерировать JSON.</p> + +<p>JSON существует как строка,что необходимо при передаче данных по сети. Он должен быть преобразован в собственный объект JavaScript, если вы хотите получить доступ к данным. Это не большая проблема. JavaScript предоставляет глобальный объект <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON</a>, который имеет методы для преобразования между ними.</p> + +<div class="note"> +<p><strong>Примечание</strong>: Преобразование строки в родной объект называется десериализацией (преобразование из последовательной формы в параллельную<em>)</em>, в то время как преобразовании родного объекта в строку, таким образом ,чтобы он мог быть передан через сеть, называется сериализацией(преобразование в последовательную форму).</p> +</div> + +<p>Объект JSON может быть сохранен в собственном файле, который в основном представляет собой текстовый файл с расширением <code>.json</code> и {{glossary("MIME type")}} <code>application/json</code>.</p> + +<h3 id="Структура_JSON">Структура JSON</h3> + +<p>Как описано выше, JSON представляет собой строку, формат которой очень похож на буквенный формат объекта JavaScript. Вы можете включать одни и те же базовые типы данных внутри JSON, так же как и в стандартном объекте JavaScript - строки, числа, массивы, булевы и другие объектные литералы. Это позволяет построить иерархию данных, к примеру, так:</p> + +<pre class="brush: json">{ + "squadName": "Super hero squad", + "homeTown": "Metro City", + "formed": 2016, + "secretBase": "Super tower", + "active": true, + "members": [ + { + "name": "Molecule Man", + "age": 29, + "secretIdentity": "Dan Jukes", + "powers": [ + "Radiation resistance", + "Turning tiny", + "Radiation blast" + ] + }, + { + "name": "Madame Uppercut", + "age": 39, + "secretIdentity": "Jane Wilson", + "powers": [ + "Million tonne punch", + "Damage resistance", + "Superhuman reflexes" + ] + }, + { + "name": "Eternal Flame", + "age": 1000000, + "secretIdentity": "Unknown", + "powers": [ + "Immortality", + "Heat Immunity", + "Inferno", + "Teleportation", + "Interdimensional travel" + ] + } + ] +}</pre> + +<p>Если бы мы загрузили этот объект в программу JavaScript, создали переменную с названием <code>superHeroes</code>, мы могли бы затем получить доступ к данным внутри нее, используя те же самые точечную и скобочную нотации, которые мы рассмотрели в статье <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics">JavaScript object basics</a>. Например:</p> + +<pre class="brush: js">superHeroes.homeTown +superHeroes['active']</pre> + +<p>Чтобы получить доступ к последующим данным по иерархии, вам просто нужно объединить требуемые имена свойств и индексы массивов. Например, чтобы получить доступ к третьей сверхспособности второго героя, указанного в списке участников, вы должны сделать следующее:</p> + +<pre class="brush: js">superHeroes['members'][1]['powers'][2]</pre> + +<ol> + <li>Сначала у нас есть имя переменной - <code>superHeroes</code>.</li> + <li>Внутри мы хотим получить доступ к свойству <code>members</code>, поэтому мы используем <code>['members']</code>.</li> + <li><code>members</code> содержат массив, заполненный объектами. Мы хотим получить доступ ко второму объекту внутри массива, поэтому мы используем <code>[1]</code>.</li> + <li>Внутри этого объекта мы хотим получить доступ к свойству <code>powers</code>, поэтому мы используем <code>['powers']</code>.</li> + <li>Внутри свойства <code>powers</code> находится массив, содержащий сверхспособности выбранного героя. Нам нужен третий, поэтому мы используем <code>[2]</code>.</li> +</ol> + +<div class="note"> +<p><strong>Примечание</strong>. Мы сделали JSON, видимый выше, доступным внутри переменной в нашем примере <a href="http://mdn.github.io/learning-area/javascript/oojs/json/JSONTest.html">JSONTest.html</a> (см. <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/JSONTest.html">исходный код</a>). Попробуйте загрузить это, а затем получить доступ к данным внутри переменной через консоль JavaScript вашего браузера.</p> +</div> + +<h3 id="Массивы_как_JSON">Массивы как JSON</h3> + +<p>Выше мы упоминали ,что JSON текст выглядит практически так же как и JavaScript объект,и это почти правильно.Причина,по которой мы говорим почти правильно заключается в том ,что массив также валиден JSON например:</p> + +<pre class="brush: json">[ + { + "name": "Molecule Man", + "age": 29, + "secretIdentity": "Dan Jukes", + "powers": [ + "Radiation resistance", + "Turning tiny", + "Radiation blast" + ] + }, + { + "name": "Madame Uppercut", + "age": 39, + "secretIdentity": "Jane Wilson", + "powers": [ + "Million tonne punch", + "Damage resistance", + "Superhuman reflexes" + ] + } +]</pre> + +<p>Вышесказанное вполне справедливо для JSON. Вам просто нужно получить доступ к элементам массива (в его анализируемой версии), начиная с индекса массива, например <code>[0]["powers"][0]</code>.</p> + +<h3 id="Другие_примечания">Другие примечания</h3> + +<ul> + <li>JSON - это чисто формат данных - он содержит только свойства, без методов.</li> + <li>JSON требует двойных кавычек, которые будут использоваться вокруг строк и имен свойств. Одиночные кавычки недействительны.</li> + <li>Даже одна неуместная запятая или двоеточие могут привести к сбою JSON-файла и не работать. Вы должны быть осторожны, чтобы проверить любые данные, которые вы пытаетесь использовать (хотя сгенерированный компьютером JSON с меньшей вероятностью включает ошибки, если программа генератора работает правильно). Вы можете проверить JSON с помощью приложения вроде <a href="http://jsonlint.com/">JSONLint</a>.</li> + <li>JSON может принимать форму любого типа данных, допустимого для включения в JSON, а не только массивов или объектов. Так, например, одна строка или номер будут действительным объектом JSON.</li> + <li>В отличие от кода JavaScript, в котором свойства объекта могут не заключаться в двойные кавычки, в JSON в качестве свойств могут использоваться только строки заключенные в двойные кавычки.</li> +</ul> + +<h2 id="Активное_обучение_Работа_с_примером_JSON">Активное обучение: Работа с примером JSON</h2> + +<p>Итак, давайте рассмотрим пример, чтобы показать то, как мы можем использовать некоторые данные JSON на веб-сайте.</p> + +<h3 id="Начало_работы">Начало работы</h3> + +<p>Для начала создайте локальные копии наших файлов <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes.html">heroes.html</a> и <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/style.css">style.css</a>. Последний содержит простой CSS для стилизации нашей страницы, в то время как первый содержит очень простой HTML-код сущности:</p> + +<pre class="brush: html"><header> +</header> + +<section> +</section></pre> + +<p>Плюс {{HTMLElement("script")}}, чтобы содержать код JavaScript, который мы будем писать в этом упражнении. На данный момент он содержит только две строки, которые захватывают ссылки на элементы {{HTMLElement("header")}} и {{HTMLElement("section")}} и сохраняют их в переменных:</p> + +<pre class="brush: js">var header = document.querySelector('header'); +var section = document.querySelector('section');</pre> + +<p>Мы предоставили данные JSON на нашем GitHub, на <a href="https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json">https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json</a>.</p> + +<p>Мы собираемся загрузить его на нашу страницу и использовать некоторые изящные манипуляции DOM, чтобы отобразить их, например:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13857/json-superheroes.png" style="display: block; margin: 0 auto;"></p> + +<h3 id="Получение_JSON">Получение JSON</h3> + +<p>Чтобы получить JSON, мы будем использовать API, называемый {{domxref("XMLHttpRequest")}} (часто называемый <strong>XHR</strong>). Это очень полезный объект JavaScript, который позволяет нам делать сетевые запросы для извлечения ресурсов с сервера через JavaScript (например, изображения, текст, JSON, даже фрагменты HTML), что означает, что мы можем обновлять небольшие разделы контента без необходимости перезагрузки всей страницы. Это привело к более отзывчивым веб-страницам и звучит захватывающе, но, к сожалению, выходит за рамки этой статьи, чтобы изучить это гораздо более подробно.</p> + +<ol> + <li>Начнем с того, что мы собираемся сохранить URL-адрес JSON, который мы хотим получить в переменной. Добавьте нижеследующий код JavaScript: + <pre class="brush: js">var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';</pre> + </li> + <li>Чтобы создать запрос, нам нужно создать новый экземпляр объекта запроса из конструктора <code>XMLHttpRequest</code>, используя ключевое слово <code>new</code>. Добавьте следующую ниже свою последнюю строку: + <pre class="brush: js">var request = new XMLHttpRequest();</pre> + </li> + <li>Теперь нам нужно открыть новый запрос, используя метод <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open">open()</a></code>. Добавьте следующую строку: + <pre class="brush: js">request.open('GET', requestURL);</pre> + + <p>Это занимает не менее двух параметров - есть другие доступные параметры. Нам нужно только два обязательных для этого простого примера:</p> + + <ul> + <li>Метод HTTP, который следует использовать при выполнении сетевого запроса. В этом случае <code><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET">GET</a></code> самый подходящий, так как мы просто извлекаем некоторые простые данные.</li> + <li>URL-адрес для запроса - это URL-адрес файла JSON, который мы сохранили ранее.</li> + </ul> + </li> + <li>Затем добавьте следующие две строки: здесь мы устанавливаем <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType">responseType</a></code> в JSON, так что XHR знает, что сервер будет возвращать JSON и, что это должно быть преобразовано за кулисами в объект JavaScript. Затем мы отправляем запрос методом <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send">send()</a></code>: + <pre class="brush: js">request.responseType = 'json'; +request.send();</pre> + </li> + <li>Последний бит этого раздела предполагает ожидание ответа на возврат с сервера, а затем работы с ним. Добавьте следующий код ниже вашего предыдущего кода: + <pre class="brush: js">request.onload = function() { + var superHeroes = request.response; + populateHeader(superHeroes); + showHeroes(superHeroes); +}</pre> + </li> +</ol> + +<p>Здесь мы сохраняем ответ на наш запрос (доступный в свойстве <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/response">response</a></code>) в переменной <code>superHeroes</code>; эта переменная теперь будет содержать объект JavaScript, основанный на JSON! Затем мы передаем этот объект двум вызовам функций - первый из них заполнит <code><header></code> правильными данными, а второй создаст информационную карту для каждого героя в команде и вставляет ее в <code><section></code>.</p> + +<p>Мы свернули код в обработчик событий, который запускается, когда событие загрузки запускается в объекте запроса (см. <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequestEventTarget/onload">onload</a></code>) - это связано с тем, что событие загрузки запускается, когда ответ успешно возвращается; поступая таким образом,это гарантия того, что <code>request.response</code> определенно будет доступен, когда мы начнем работу с ним.</p> + +<p>Заполнение заголовка</p> + +<p>Теперь мы извлекли данные JSON и превратили его в объект JavaScript, давайте воспользуемся им, написав две функции, на которые мы ссылались выше. Прежде всего, добавьте следующее определение функции ниже предыдущего кода:</p> + +<pre class="brush: js">function populateHeader(jsonObj) { + var myH1 = document.createElement('h1'); + myH1.textContent = jsonObj['squadName']; + header.appendChild(myH1); + + var myPara = document.createElement('p'); + myPara.textContent = 'Hometown: ' + jsonObj['homeTown'] + ' // Formed: ' + jsonObj['formed']; + header.appendChild(myPara); +}</pre> + +<p>Мы назвали параметр <code>jsonObj</code>, чтобы напомнить себе, что этот объект JavaScript возник из JSON. Здесь мы сначала создаем элемент {{HTMLElement("h1")}} с <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement">createElement()</a></code>, устанавливаем его <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent">textContent</a></code> равным свойству <code>squadName</code> объекта, а затем добавляем его в заголовок с помощью <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild">appendChild()</a></code>. Затем мы выполняем очень похожую операцию с абзацем: создаем его, устанавливаем его текстовое содержимое и добавляем его в заголовок. Единственное различие заключается в том, что его текст задан, как конкатенированная строка, содержащая как <code>homeTown</code>, так и <code>formed</code> свойства объекта.</p> + +<h3 id="Создание_информационных_карт_героя">Создание информационных карт героя</h3> + +<p>Затем добавьте следующую функцию внизу кода, которая создает и отображает карты супергероев:</p> + +<pre class="brush: js">function showHeroes(jsonObj) { + var heroes = jsonObj['members']; + + for (var i = 0; i < heroes.length; i++) { + var myArticle = document.createElement('article'); + var myH2 = document.createElement('h2'); + var myPara1 = document.createElement('p'); + var myPara2 = document.createElement('p'); + var myPara3 = document.createElement('p'); + var myList = document.createElement('ul'); + + myH2.textContent = heroes[i].name; + myPara1.textContent = 'Secret identity: ' + heroes[i].secretIdentity; + myPara2.textContent = 'Age: ' + heroes[i].age; + myPara3.textContent = 'Superpowers:'; + + var superPowers = heroes[i].powers; + for (var j = 0; j < superPowers.length; j++) { + var listItem = document.createElement('li'); + listItem.textContent = superPowers[j]; + myList.appendChild(listItem); + } + + myArticle.appendChild(myH2); + myArticle.appendChild(myPara1); + myArticle.appendChild(myPara2); + myArticle.appendChild(myPara3); + myArticle.appendChild(myList); + + section.appendChild(myArticle); + } +}</pre> + +<p>Для начала сохраним свойство <code>members</code> объекта JavaScript в новой переменной. Этот массив содержит несколько объектов, которые содержат информацию для каждого героя.</p> + +<p>Затем мы используем <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code#The_standard_for_loop">for loop</a> для циклического прохождения каждого объекта в массиве. Для каждого из них мы:</p> + +<ol> + <li>Создаем несколько новых элементов: <code><article></code>, <code><h2></code>, три <code><p></code> и <code><ul></code>.</li> + <li>Установливаем <code><h2></code>, чтобы содержать <code>name</code> текущего героя.</li> + <li>Заполняем три абзаца своей <code>secretIdentity</code>, <code>age</code> и строкой, в которой говорится: «Суперспособности:», чтобы ввести информацию в список.</li> + <li>Сохраняем свойство <code>powers</code> в другой новой переменной под названием <code>superPowers</code> - где содержится массив, в котором перечислены сверхспособности текущего героя.</li> + <li>Используем другой цикл <code>for</code>, чтобы прокрутить сверхспособности текущего героя , для каждого из них мы создаем элемент <code><li></code>, помещаем в него сверхспособности, а затем помещаем <code>listItem</code> внутри элемента <code><ul></code> (<code>myList</code>) с помощью <code>appendChild()</code>.</li> + <li>Последнее, что мы делаем, это добавляем <code><h2></code>, <code><p></code> и <code><ul></code> внутри <code><article></code> (<code>myArticle</code>), а затем добавляем <code><article></code> в <code><section></code>. Важное значение имеет порядок, в котором добавляются элементы, так как это порядок, который они будут отображать внутри HTML.</li> +</ol> + +<div class="note"> +<p><strong>Примечание</strong>. Если вам не удается заставить этот пример работать, попробуйте обратиться к нашему исходному коду <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished.html">heroes-finished.html</a> (см. также он работает <a href="https://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished.html">в режиме live</a>).</p> +</div> + +<div class="note"> +<p><strong>Примечание</strong>. Если у вас возникли проблемы после нотации точек / скобок, которые мы используем для доступа к объекту JavaScript, в этом поможет открытие файла <a href="http://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json">superheroes.json</a> на другой вкладке или в текстовом редакторе ,и обращаться к нему каждый раз, когда вам нужен JavaScript. Вы также можете обратиться к нашей статье <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics">JavaScript objectbasics</a> чтобы получить дополнительную информацию о нотации точек и скобок.</p> +</div> + +<h2 id="Преобразование_между_объектами_и_текстом">Преобразование между объектами и текстом</h2> + +<p>Вышеприведенный пример был прост с точки зрения доступа к объекту JavaScript, потому что мы задали XHR-запрос для прямого преобразования ответа JSON в объект JavaScript, используя:</p> + +<pre class="brush: js">request.responseType = 'json';</pre> + +<p>Но иногда нам не так везет - иногда мы получаем сырую строку JSON и нам нужно преобразовать ее в объект самостоятельно. И когда мы хотим отправить объект JavaScript по сети, нам нужно преобразовать его в JSON (строку) перед отправкой. К счастью, эти две проблемы настолько распространены в веб-разработке, что встроенный объект <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON</a> доступен в браузерах, которые содержат следующие два метода:</p> + +<ul> + <li><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse">parse()</a></code>: принимает строку JSON в качестве параметра и возвращает соответствующий объект JavaScript.</li> + <li><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">stringify()</a></code>: принимает объект, как параметр и возвращает эквивалентную строковую JSON строку.</li> +</ul> + +<p>Вы можете увидеть первый метод в действии в нашем примере <a href="http://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished-json-parse.html">heroes-finished-json-parse.html</a> (см. <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished-json-parse.html">исходный код</a>) - это то же самое, что и в примере, который мы создали ранее, за исключением того, что мы установили XHR для возврата сырого JSON текста, затем используется <code>parse()</code>, чтобы преобразовать его в фактический объект JavaScript. Ключевой фрагмент кода находится здесь:</p> + +<pre class="brush: js">request.open('GET', requestURL); +request.responseType = 'text'; // now we're getting a string! +request.send(); + +request.onload = function() { + var superHeroesText = request.response; // get the string from the response + var superHeroes = JSON.parse(superHeroesText); // convert it to an object + populateHeader(superHeroes); + showHeroes(superHeroes); +}</pre> + +<p>Как вы могли догадаться, <code>stringify()</code> работает обратным образом. Попробуйте ввести следующие строки в консоль JavaScript браузера один за другим, чтобы увидеть его в действии:</p> + +<pre class="brush: js">var myJSON = { "name": "Chris", "age": "38" }; +myJSON +var myString = JSON.stringify(myJSON); +myString</pre> + +<p>Здесь мы создаем объект JavaScript, затем проверяем, что он содержит, а затем преобразуем его в строку JSON, используя <code>stringify()</code> , сохраняя возвращаемое значение в новой переменной, а затем снова проверяем его.</p> + +<h2 id="Резюме">Резюме</h2> + +<p>В этой статье мы предоставили вам простое руководство по использованию JSON в ваших программах, в том числе о том, как создавать и анализировать JSON, и как получить доступ к данным, заблокированным внутри него. В следующей статье мы рассмотрим объектно-ориентированный JavaScript.</p> + +<h2 id="Смотрите_также">Смотрите также</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON object reference page</a></li> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest">XMLHttpRequest object reference page</a></li> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest">Using XMLHttpRequest</a></li> + <li><a href="/en-US/docs/Web/HTTP/Methods">HTTP request methods</a></li> + <li><a href="http://json.org">Official JSON web site with link to ECMA standard</a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}</p> + +<h2 id="В_этом_модуле">В этом модуле</h2> + +<ul> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B">Основы объекта</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Object-oriented_JS">Объектно-ориентированный JavaScript для начинающих</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Object_prototypes">Прототипы объектов</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Inheritance">Наследование в JavaScript</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/JSON">Работа с данными JSON</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Object_building_practice">Практика построения объектов</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Adding_bouncing_balls_features">Добавление функций в нашу демонстрацию прыгающих шаров</a></li> +</ul> + +<div class="s3gt_translate_tooltip_mini_box" id="s3gt_translate_tooltip_mini" style="background: initial !important; border: initial !important; border-radius: initial !important; border-collapse: initial !important; direction: ltr !important; font-weight: initial !important; height: initial !important; letter-spacing: initial !important; max-width: initial !important; min-height: initial !important; margin: auto !important; outline: initial !important; padding: initial !important; position: absolute; text-align: initial !important; text-shadow: initial !important; width: initial !important; display: initial !important; color: inherit !important; font-size: 13px !important; font-family: X-LocaleSpecific, sans-serif, Tahoma, Helvetica !important; line-height: 13px !important; vertical-align: top !important; white-space: inherit !important; left: 124px; top: 1171px; opacity: 0;"> +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_logo" style="width: 12px; height: 12px; border-radius: 4px;" title="Перевести выделенный фрагмент"></div> + +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_sound" style="width: 12px; height: 12px; border-radius: 4px;" title="Прослушать"></div> + +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_copy" style="width: 12px; height: 12px; border-radius: 4px;" title="Скопировать текст в буфер обмена"></div> +</div> diff --git a/files/ru/learn/javascript/objects/object-oriented_js/index.html b/files/ru/learn/javascript/objects/object-oriented_js/index.html new file mode 100644 index 0000000000..0299268a90 --- /dev/null +++ b/files/ru/learn/javascript/objects/object-oriented_js/index.html @@ -0,0 +1,286 @@ +--- +title: Объектно-ориентированный JavaScript для начинающих +slug: Learn/JavaScript/Объекты/Object-oriented_JS +tags: + - Constructor + - Create + - JavaScript + - OOJS + - Object + - Новичку + - ООП + - экземпляр +translation_of: Learn/JavaScript/Objects/Object-oriented_JS +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">Разобравшись с основами, сосредоточимся на объектно-ориентированном JavaScript (OOJS) — данная статья дает базовое представление о теории объектно-ориентированного программирования (ООП), далее рассмотрено как JavaScript эмулирует классы объектов с помощью функции-конструктора и как создаются экземпляры объектов.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Необходимые знания:</th> + <td> + <p class="brush: html">Базовая компьютерная грамотность, базовое понимание HTML и CSS, знакомство с основами JavaScript (см. <a href="/en-US/docs/Learn/JavaScript/First_steps">Первые шаги</a> и <a href="/en-US/docs/Learn/JavaScript/Building_blocks">C</a>труктурные элементы JavaScript) и основы OOJS (см. <a href="/en-US/docs/Learn/JavaScript/Object-oriented/Introduction">Введение в объекты</a>).</p> + </td> + </tr> + <tr> + <th scope="row">Цель:</th> + <td>Понять основную теорию объектно-ориентированного программирования, как это относится к JavaScript («все является объектом») и как создавать конструкторы и экземпляры объектов.</td> + </tr> + </tbody> +</table> + +<h2 id="Объектно-ориентированное_программирование_основы">Объектно-ориентированное программирование: основы</h2> + +<p>Начнём с упрощённого высокоуровневого представления о том, что такое <em>объектно-ориентированное программирование</em> <em>(ООП)</em>. Мы говорим упрощённого, потому что ООП может быстро стать очень сложным, и если сейчас дать полный курс, вероятно, можно запутать больше, чем помочь. Основная идея ООП заключается в том, что мы используем объекты для отображения моделей из реального мира в наших программах и/или упрощения доступа к функциям, которые в противном случае было бы трудно или невозможно использовать.</p> + +<p>Объекты могут содержать данные и код, представляющие информацию о том, что вы пытаетесь смоделировать, а также о том, какие у этих объектов должны быть функциональные возможности или поведение. Данные объекта (а часто так же и функции) могут быть точно сохранены (официальный термин "<strong>инкапсулированы"</strong>) внутри пакета объекта, упрощая структуру и доступ к ним. Пакету объекта может быть присвоено определенное имя, на которое можно сослаться и которое иногда называют <strong>пространством имен.</strong> Объекты также широко используются в качестве хранилищ данных, которые могут быть легко отправлены по сети.</p> + +<h3 id="Определение_шаблона_объекта">Определение шаблона объекта</h3> + +<p>Рассмотрим простую программу, которая отображает информацию об учениках и учителях в школе. Здесь мы рассмотрим теорию ООП в целом, а не в контексте какого-либо конкретного языка программирования.</p> + +<p>Вернёмся к объекту Person из нашей статьи <a href="/ru/docs/Learn/JavaScript/Объекты/Основы">Основы объектов</a>, который определяет общие сведения и функциональные возможности человека. Есть много вещей, которые вы <em>можете</em> узнать о человеке (его адрес, рост, размер обуви, профиль ДНК, номер паспорта, значимые черты личности ...), но в данном случае нас интересует только имя, возраст, пол и интересы, а также мы хотим иметь возможность написать краткую информацию о нём, основываясь на этих данных, и сделать так, чтобы он поздоровался. Это известно как <strong>абстракция</strong> — создание простой модели более сложной сущности, которая представляет её наиболее важные аспекты таким образом, чтобы с ней было удобно работать для выполнения целей нашей программы.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13889/person-diagram.png" style="display: block; height: 219px; margin: 0px auto; width: 610px;"></p> + +<p>В некоторых языках ООП, это общее определение типа объекта называется <strong>class</strong> (JavaScript использует другой механизм и терминологию, как вы увидите ниже) — это на самом деле не объект, а шаблон, который определяет, какие характеристики должен иметь объект.</p> + +<h3 id="Создание_реальных_объектов">Создание реальных объектов</h3> + +<p>Из нашего класса мы можем создать <strong>экземпляры объектов</strong> — объекты, содержащие данные и функциональные возможности, определённые в классе. Из нашего класса Person мы теперь можем создавать модели реальных людей:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13883/MDN-Graphics-instantiation-2.png" style="display: block; height: 743px; margin: 0px auto; width: 700px;"></p> + +<p>Когда экземпляр объекта создается из класса, для его создания выполняется <strong>функция-конструктор </strong>класса. Этот процесс создания экземпляра объекта из класса называется <strong>создание экземпляра (instantiation)</strong> — из класса <strong>создается</strong> экземпляр объекта.</p> + +<h3 id="Специализированные_классы">Специализированные классы</h3> + +<p>В нашем случае нам не нужны все люди — нам требуются учителя и ученики, которые являются более конкретными типами людей. В ООП мы можем создавать новые классы на основе других классов — эти новые <strong>дочерние классы</strong> могут быть созданы для <strong>наследования</strong> данных и характеристик <strong>родительского класса</strong>, так чтобы можно было использовать функциональные возможности, общие для всех типов объекта, вместо того чтобы дублировать их. Когда функциональность различается между классами, можно по мере необходимости определять специализированные функции непосредственно на них.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13881/MDN-Graphics-inherited-3.png" style="display: block; height: 743px; margin: 0px auto; width: 700px;"></p> + +<p>Это действительно полезно — преподаватели и студенты имеют много общих характеристик, таких как имя, пол и возраст, и удобно определить их только один раз. Вы можете также задать одну и ту же характеристику отдельно в разных классах, поскольку каждое определение этой характеристики будет находиться в отдельном пространстве имен. Например, приветствие студента может быть в форме "Yo, I'm [firstName]" (например <em>Yo, I'm Sam</em>), в то время как учитель может использовать что-то более формальное, такое как "Hello, my name is [Prefix] [lastName], and I teach [Subject]." (например <em>Hello, My name is Mr Griffiths, and I teach Chemistry</em>).</p> + +<div class="note"> +<p><strong>Примечание</strong>: Если вам интересно, существует специальный термин <strong>Polymorphism (Полиморфизм)</strong> - это забавное слово, обозначающее реализацию той же функциональности для нескольких типов объекта. </p> +</div> + +<p>Теперь вы можете создавать экземпляры объекта из дочерних классов. Например:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13885/MDN-Graphics-instantiation-teacher-3.png" style="display: block; height: 743px; margin: 0px auto; width: 700px;"></p> + +<p>Далее мы рассмотрим, как ООП теорию можно применить на практике в JavaScript.</p> + +<h2 id="Конструкторы_и_экземпляры_объектов">Конструкторы и экземпляры объектов</h2> + +<p>JavaScript использует специальные функции, называемые функциями конструктора (<strong>constructor functions</strong>) для определения объектов и их свойств. Они полезны, потому что вы часто будете сталкиваться с ситуациями, в которых не известно, сколько объектов вы будете создавать; конструкторы позволяют создать столько объектов, сколько нужно эффективным способом, прикреплением данных и функций для объектов по мере необходимости.</p> + +<p>Рассмотрим создание классов через конструкторы и создание экземпляров объектов из них в JavaScript. Прежде всего, мы хотели бы, чтобы вы создали новую локальную копию файла <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs.html">oojs.html</a>, который мы видели в нашей первой статье «Объекты».</p> + +<h3 id="Простой_пример">Простой пример</h3> + +<ol> + <li>Давайте рассмотрим как можно определить человека с нормальной функцией. Добавьте эту функцию в элемент <code>script</code>: + + <pre class="brush: js notranslate">function createNewPerson(name) { + const obj = {}; + obj.name = name; + obj.greeting = function() { + alert('Hi! I\'m ' + this.name + '.'); + }; + return obj; +}</pre> + </li> + <li>Теперь вы можете создать нового человека, вызвав эту функцию - попробуйте следующие строки в консоли JavaScript браузера: + <pre class="brush: js notranslate">const salva = createNewPerson('Salva'); +salva.name; +salva.greeting();</pre> + Это работает достаточно хорошо, но код излишне многословен; если мы знаем, что хотим создать объект, зачем нам явно создавать новый пустой объект и возвращать его? К счастью, JavaScript предоставляет нам удобный способ в виде функций-конструкторов - давайте сделаем это сейчас!</li> + <li>Замените предыдущую функцию следующей: + <pre class="brush: js notranslate">function Person(name) { + this.name = name; + this.greeting = function() { + alert('Hi! I\'m ' + this.name + '.'); + }; +}</pre> + </li> +</ol> + +<p>Функция-конструктор - это JavaScript версия класса. Вы заметите, что в нем есть все признаки, которые вы ожидаете от функции, хотя он ничего не возвращает и явно не создает объект - он в основном просто определяет свойства и методы. Вы также увидите, что ключевое слово this также используется здесь, - это в основном говорит о том, что всякий раз, когда создается один из этих экземпляров объектов, свойство имени объекта будет равно значению <code>name</code>, переданному вызову конструктора, и метод <code>greeting()</code> будет использовать значение имени, переданное также вызову конструктора.</p> + +<div class="note"> +<p><strong>Примечание:</strong> Имя функции конструктора обычно начинается с заглавной буквы - это соглашение используется для упрощения распознавания функций конструктора в коде.</p> +</div> + +<p>Итак, как мы вызываем конструктор для создания некоторых объектов?</p> + +<ol> + <li>Добавьте следующие строки под предыдущим добавлением кода: + <pre class="brush: js notranslate">let person1 = new Person('Bob'); +let person2 = new Person('Sarah');</pre> + </li> + <li>Сохраните код и перезагрузите его в браузере и попробуйте ввести следующие строки в консоль JS: + <pre class="brush: js notranslate">person1.name +person1.greeting() +person2.name +person2.greeting()</pre> + </li> +</ol> + +<p>Круто! Теперь, как вы видите, у нас есть два новых объекта на странице, каждый из которых хранится в отдельном пространстве имен - при доступе к их свойствам и методам вы должны начинать вызовы с <code>person1</code> или <code>person2</code>; функциональность, содержащаяся внутри, аккуратно упакована, поэтому она не будет конфликтовать с другими функциями. Тем не менее, у них есть одно и то же свойство <code>name</code> и <code>greeting()</code>. Обратите внимание, что они используют свое собственное значение <code>name</code>, которое было присвоено им, когда они были созданы; это одна из причин, почему очень важно использовать <code>this</code>, таким образом они будут использовать свои собственные значения, а не какие-либо другие.</p> + +<p>Давайте снова посмотрим на вызовы конструктора:</p> + +<pre class="brush: js notranslate">let person1 = new Person('Bob'); +let person2 = new Person('Sarah');</pre> + +<p>В каждом случае ключевое слово <code>new</code> используется, чтобы сообщить браузеру, что мы хотим создать экземпляр нового объекта, за которым следует имя функции с ее необходимыми параметрами, содержащимися в круглых скобках, и результат сохраняется в переменной - очень похоже на то, как вызывается стандартная функция. Каждый экземпляр создается в соответствии с этим определением:</p> + +<pre class="brush: js notranslate">function Person(name) { + this.name = name; + this.greeting = function() { + alert('Hi! I\'m ' + this.name + '.'); + }; +}</pre> + +<p>После создания новых объектов переменные <code>person1</code> и <code>person2</code> содержат следующие объекты:</p> + +<pre class="brush: js notranslate">{ + name: 'Bob', + greeting: function() { + alert('Hi! I\'m ' + this.name + '.'); + } +} + +{ + name: 'Sarah', + greeting: function() { + alert('Hi! I\'m ' + this.name + '.'); + } +}</pre> + +<p>Обратите внимание, что когда мы вызываем нашу функцию-конструктор, мы определяем <code>greeting()</code> каждый раз, что не является идеальным. Чтобы этого избежать, вместо этого мы можем определить функции на прототипе, о которых мы поговорим позже.</p> + +<h3 id="Создавая_наш_готовый_конструктор">Создавая наш готовый конструктор</h3> + +<p>Пример, рассмотренный выше, был лишь наглядным примером, чтобы вы поняли суть. Теперь, давайте создадим нашу конечную функцию-конструктор <code>Person()</code>.</p> + +<ol> + <li>Замените весь предыдущий код новой функцией конструктора - это, в принципе, тот же самое что и в наглядном примере, но несколько сложнее: + <pre class="brush: js notranslate">function Person(first, last, age, gender, interests) { + this.name = { + first : first, + last: last + }; + this.age = age; + this.gender = gender; + this.interests = interests; + this.bio = function() { + alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.'); + }; + this.greeting = function() { + alert('Hi! I\'m ' + this.name.first + '.'); + }; +};</pre> + </li> + <li>Теперь добавьте следующую строку ниже, чтобы создать экземпляр объекта из него: + <pre class="brush: js notranslate">let person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);</pre> + </li> +</ol> + +<p>Как вы могли заметить, вы можете получить доступ к свойствам и методам, как это было ранее, - попробуйте использовать их в консоли JS:</p> + +<pre class="brush: js notranslate">person1['age'] +person1.interests[1] +person1.bio() +// etc.</pre> + +<div class="note"><strong>Примечание</strong>: Если у Вас возникли проблемы с работой кода, попробуйте сравнить его с нашей версией - см. <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-finished.html">oojs-class-finished.html</a> (также смотрите, как он работает <a href="https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-finished.html">в прямом эфире</a>).</div> + +<h3 id="Дальнейшие_упражнения">Дальнейшие упражнения</h3> + +<p>Для начала, попробуйте добавить еще пару собственных строк создания объекта и попробуйте получить и установить элементы полученных экземпляров объектов.</p> + +<p>Кроме того, есть несколько проблем с нашим методом <code>bio()</code> - вывод всегда включает местоимение «He» ("Он" в пер. с англ.), даже если ваш человек является женщиной или какой-либо другой предпочтительной гендерной классификацией. И <code>bio</code> будет включать только два интереса, даже если в массиве <code>interests</code> указано больше. Можете ли Вы решить, как исправить это в определении класса (конструкторе)? Вы можете поместить любой код, который вам нравится внутри конструктора (вам, вероятно, понадобятся несколько условий и цикл). Подумайте о том, как предложения должны быть структурированы по-разному в зависимости от пола и в зависимости от того, имеет ли число перечисленных интересов 1, 2 или более 2.</p> + +<div class="note"> +<p><strong>Примечание</strong>: Если у Вас возникли трудности с решением задачи, мы предоставили <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">ответ в нашем репозитории GitHub</a> (<a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html">см. это в действии</a>) — но сначала попробуйте написать сами!</p> +</div> + +<h2 id="Другие_способы_создания_экземпляров_объектов">Другие способы создания экземпляров объектов</h2> + +<p>До сих пор мы видели два разных способа создания экземпляра объекта - <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#Object_basics">объявление объектного литерала</a> и использование функции конструктора (см. выше).</p> + +<p>Это имеет смысл, но есть и другие способы - мы бы хотели ознакомить Вас с ними на случай, если Вы встретите их в своих путешествиях по Сети.</p> + +<h3 id="Конструктор_Object">Конструктор Object ()</h3> + +<p>Прежде всего, вы можете использовать конструктор <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">Object()</a></code> для создания нового объекта. Да, даже общие объекты имеют конструктор, который генерирует пустой объект.</p> + +<ol> + <li>Попробуйте ввести это в консоль JavaScript вашего браузера: + <pre class="brush: js notranslate">let person1 = new Object();</pre> + </li> + <li>Это сохраняет ссылку на пустой объект в переменную <code>person1</code>. Затем вы можете добавить свойства и методы к этому объекту с использованием точечной или скобочной нотации по желанию; попробуйте эти примеры в консоли: + <pre class="brush: js notranslate">person1.name = 'Chris'; +person1['age'] = 38; +person1.greeting = function() { + alert('Hi! I\'m ' + this.name + '.'); +};</pre> + </li> + <li>Вы также можете передать литерал объекта конструктору <code>Object()</code> в качестве параметра, чтобы заполнить его свойствами / методами. Попробуйте это в консоли JS: + <pre class="brush: js notranslate">let person1 = new Object({ + name: 'Chris', + age: 38, + greeting: function() { + alert('Hi! I\'m ' + this.name + '.'); + } +});</pre> + </li> +</ol> + +<h3 id="Использование_метода_create">Использование метода create()</h3> + +<p>Конструкторы могут помочь вам определить порядок кода - вы можете создать конструктор в одном месте, а затем создавать экземпляры по мере необходимости, и их происхождение будет понятным.</p> + +<p>Однако некоторые люди предпочитают создавать экземпляры объектов без предварительного создания конструкторов, особенно если они создают только несколько экземпляров объекта. JavaScript имеет встроенный метод <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create">create()</a></code>, который позволяет вам это делать. С его помощью вы можете создать новый объект на основе любого существующего объекта.</p> + +<ol> + <li>Закончив упражнение из предыдущего раздела, загруженное в браузер, попробуйте это в консоли JavaScript: + <pre class="brush: js notranslate">let person2 = Object.create(person1);</pre> + </li> + <li>Теперь попробуйте: + <pre class="brush: js notranslate">person2.name +person2.greeting()</pre> + </li> +</ol> + +<p>Вы увидите, что <code>person2</code> был создан на основе <code>person1</code> - он имеет те же свойства и метод, доступные для него.</p> + +<p>Одно ограничение метода <code>create()</code> заключается в том, что IE8 не поддерживает его. Поэтому конструкторы могут быть более эффективными, если вы хотите поддерживать старые браузеры.</p> + +<p>Подробнее мы рассмотрим особенности метода <code>create()</code> немного позже.</p> + +<h2 id="Сводка">Сводка</h2> + +<p>В этой статье представлен упрощенный взгляд на объектно-ориентированную теорию — это еще не вся история, но она дает представление о том, с чем мы имеем дело. Кроме того, мы начали рассматривать различные способы создания экземпляров объектов.</p> + +<p>В следующей статье мы рассмотрим прототипы объектов JavaScript.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}</p> + +<h2 id="В_этом_модуле">В этом модуле</h2> + +<ul> + <li><a href="/ru/docs/Learn/JavaScript/Объекты/Основы">Основы объекта</a></li> + <li><a href="/ru/docs/Learn/JavaScript/Объекты/Object-oriented_JS">Объектно-ориентированный JavaScript для начинающих</a></li> + <li><a href="/ru/docs/Learn/JavaScript/Объекты/Object_prototypes">Прототипы объектов</a></li> + <li><a href="/ru/docs/Learn/JavaScript/Объекты/Inheritance">Наследование в JavaScript</a></li> + <li><a href="/ru/docs/Learn/JavaScript/Объекты/JSON">Работа с данными JSON</a></li> + <li><a href="/ru/docs/Learn/JavaScript/Объекты/Object_building_practice">Практика построения объектов</a></li> + <li><a href="/ru/docs/Learn/JavaScript/Объекты/Adding_bouncing_balls_features">Добавление функций в нашу демонстрацию прыгающих шаров</a></li> +</ul> diff --git a/files/ru/learn/javascript/objects/object_building_practice/index.html b/files/ru/learn/javascript/objects/object_building_practice/index.html new file mode 100644 index 0000000000..b06b769ca4 --- /dev/null +++ b/files/ru/learn/javascript/objects/object_building_practice/index.html @@ -0,0 +1,302 @@ +--- +title: Практика построения объектов +slug: Learn/JavaScript/Объекты/Object_building_practice +tags: + - Guide + - JavaScript +translation_of: Learn/JavaScript/Objects/Object_building_practice +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">В предыдущих статьях мы рассмотрели всю существенную теорию объектов JavaScript и детали синтаксиса, давая вам прочную основу для начала. В этой статье мы погружаемся в практическое упражнение, давая вам больше практики в создании пользовательских объектов JavaScript, с веселым и красочным результатом.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Необходимые знания:</th> + <td>Базовая компьютерная грамотность, базовые знания HTML и CSS, знакомство с основами JavaScript (see <a href="/en-US/docs/Learn/JavaScript/First_steps">First steps</a> and <a href="/en-US/docs/Learn/JavaScript/Building_blocks">Building blocks</a>) и основами OOJS (см. <a href="/en-US/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction to objects</a>).</td> + </tr> + <tr> + <th scope="row">Цель:</th> + <td>Получение некоторой практики в использовании объектов и объектно-ориентированных методов в реальном мире.</td> + </tr> + </tbody> +</table> + +<h2 id="Давайте_подбросим_несколько_мячей">Давайте подбросим несколько мячей</h2> + +<p>В этой статье мы напишем классическую демонстрацию «прыгающих шаров», чтобы показать вам, насколько полезными могут быть объекты в JavaScript. Наши маленькие шары будут подпрыгивать на экране и менять цвет, когда они касаются друг друга. Готовый пример будет выглядеть примерно так:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13865/bouncing-balls.png" style="display: block; height: 614px; margin: 0px auto; width: 800px;"></p> + +<ol> +</ol> + +<p>В этом примере будет использоваться <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Canvas API</a> для рисования шаров на экране и API <a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame</a> для анимации всего экрана - вам не нужно иметь никаких предыдущих знаний об этих API, и мы надеемся, что к тому моменту, когда вы закончите эту статью, вам будет интересно изучить их больше. По пути мы воспользуемся некоторыми изящными объектами и покажем вам пару хороших приемов, таких как отскоки шаров от стен и проверка того, попали ли они друг в друга (иначе известный как <strong>обнаружение столкновения</strong>).</p> + +<h2 id="Начало_работы">Начало работы</h2> + +<p>Для начала создайте локальные копии наших файлов<code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/index.html">index.html</a></code>, <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/style.css">style.css</a></code> и <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main.js">main.js</a></code>. Они содержат следующее:</p> + +<ol> + <li>Очень простой HTML-документ, содержащий элемент {{HTMLElement("h1")}}, элемент {{HTMLElement("canvas")}} для рисования наших шаров и элементы для применения нашего CSS и JavaScript в нашем HTML.</li> + <li>Некоторые очень простые стили, которые в основном служат для стилизации и позиционирования <code><h1></code>, и избавляются от любых полос прокрутки или отступы по краю страницы (так что это выглядит красиво и аккуратно).</li> + <li>Некоторые JavaScript, которые служат для настройки элемента <code><canvas></code> и предоставляют общую функцию, которую мы собираемся использовать.</li> +</ol> + +<p>Первая часть скрипта выглядит так:</p> + +<pre class="brush: js notranslate">var canvas = document.querySelector('canvas'); + +var ctx = canvas.getContext('2d'); + +var width = canvas.width = window.innerWidth; +var height = canvas.height = window.innerHeight;</pre> + +<p>Этот скрипт получает ссылку на элемент <code><canvas></code>, а затем вызывает метод <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext">getContext()</a></code>, чтобы дать нам контекст, по которому мы можем начать рисовать. Результирующая переменная (ctx) - это объект, который непосредственно представляет область рисования холста и позволяет рисовать на ней 2D-фигуры.</p> + +<p>Затем мы устанавливаем переменные, называемые <code>width</code> и <code>height</code>, а также ширину и высоту элемента canvas (представленные свойствами <code>canvas.width</code> и <code>canvas.height</code>), чтобы равняться ширине и высоте окна просмотра браузера (область, на которой отображается веб-страница - это можно получить из свойств {{domxref("Window.innerWidth")}} и {{domxref("Window.innerHeight")}}).</p> + +<p>Вы увидите здесь, что мы объединяем несколько назначений вместе, чтобы все переменные были установлены быстрее - это совершенно нормально.</p> + +<p>Последний бит исходного скрипта выглядит следующим образом:</p> + +<pre class="brush: js notranslate">function random(min, max) { + var num = Math.floor(Math.random() * (max - min + 1)) + min; + return num; +}</pre> + +<p>Эта функция принимает два числа в качестве аргументов и возвращает случайное число в диапазоне между ними.</p> + +<h2 id="Моделирование_мяча_в_нашей_программе">Моделирование мяча в нашей программе</h2> + +<p>В нашей программе будет много шаров, подпрыгивающих вокруг экрана. Поскольку эти шары будут вести себя одинаково, имеет смысл представлять их в виде объекта. Начнем с добавления следующего конструктора в конец нашего кода.</p> + +<pre class="brush: js notranslate">function Ball(x, y, velX, velY, color, size) { + this.x = x; + this.y = y; + this.velX = velX; + this.velY = velY; + this.color = color; + this.size = size; +}</pre> + +<p>Здесь мы включаем некоторые параметры, которые определяют свойства, которым должен соответствовать каждый шар в нашей программе:</p> + +<ul> + <li><code>x</code> и <code>y</code> координаты - горизонтальные и вертикальные координаты, где мяч будет запускаться на экране. Координаты могут находиться в диапазоне от 0 (верхний левый угол) до ширины и высоты окна просмотра браузера (нижний правый угол).</li> + <li>горизонтальная и вертикальная скорость (<code>velX</code> и <code>velY</code>) - каждому шару задана горизонтальная и вертикальная скорость; в реальном выражении эти значения будут регулярно добавляться к значениям координат <code>x</code>/<code>y</code>, когда мы начнем анимировать шары, чтобы их перемещать на каждом кадре.</li> + <li><code>color</code> - каждый мяч получает цвет.</li> + <li><code>size</code> - каждый мяч получает размер - это будет его радиус в пикселях.</li> +</ul> + +<p>Этим мы сортируем свойства, но что насчет методов? Мы хотим заставить эти шары на самом деле сделать что-то в нашей программе.</p> + +<h3 id="Рисование_шара">Рисование шара</h3> + +<p>Сначала добавьте следующий метод <code>draw()</code> к <code>Ball()</code>'s <code>prototype</code>:</p> + +<pre class="brush: js notranslate">Ball.prototype.draw = function() { + ctx.beginPath(); + ctx.fillStyle = this.color; + ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); + ctx.fill(); +}</pre> + +<p>Используя эту функцию, мы можем сказать нашему шару нарисовать себя на экране, вызвав ряд членов контекста двумерного холста, который мы определили ранее (<code>ctx</code>). Контекст похож на бумагу, и теперь мы хотим, чтобы наше перо рисовало что-то на нем:</p> + +<ul> + <li>Во-первых, мы используем <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/beginPath">beginPath()</a></code>, чтобы указать, что мы хотим нарисовать фигуру на бумаге.</li> + <li>Затем мы используем <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle">fillStyle</a></code> для определения того, какой цвет нам нужен, - мы устанавливаем его в свойство цвета нашего шара.</li> + <li>Затем мы используем метод <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc">arc()</a></code> для отслеживания формы дуги на бумаге. Его параметры: + <ul> + <li>Положение <code>x</code> и <code>y</code> центра дуги - мы указываем свойства <code>x</code> и <code>y</code> нашего шара.</li> + <li>Радиус нашей дуги - мы указываем свойство <code>size</code> шарика.</li> + <li>Последние два параметра определяют начальное и конечное число градусов по кругу, по которому проходит дуга. Здесь мы указываем 0 градусов и <code>2 * PI</code>, что эквивалентно 360 градусам в радианах (досадно, вы должны указать это в радианах). Это дает нам полный круг. Если вы указали только <code>1 * PI</code>, вы получите полукруг (180 градусов).</li> + </ul> + </li> + <li>В последнем случае мы используем метод <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fill">fill()</a></code>, который в основном утверждает: «Закончите рисование пути, начатого с <code>beginPath()</code>, и заполните область, которую он занимает с цветом, указанным ранее в <code>fillStyle</code>».</li> +</ul> + +<p>Теперь вы можете начать тестирование своего объекта..</p> + +<ol> + <li>Сохраните код и загрузите HTML-файл в браузер.</li> + <li>Откройте консоль JavaScript браузера, а затем обновите страницу, чтобы размер холста изменился в соответствии с новой шириной и высотой окна просмотра браузера после открытия консоли.</li> + <li>Чтобы создать новый экземпляр шара, введите следующее: + <pre class="brush: js notranslate">var testBall = new Ball(50, 100, 4, 4, 'blue', 10);</pre> + </li> + <li>Попробуйте вызвать его свойства и методы: + <pre class="brush: js notranslate">testBall.x +testBall.size +testBall.color +testBall.draw()</pre> + </li> + <li>После введения последней строки, вы должны увидеть, как мяч нарисовался где-то на вашем холсте.</li> +</ol> + +<h3 id="Обновление_данных_мяча">Обновление данных мяча</h3> + +<p>Мы можем нарисовать мяч в нужном положении, но чтобы начать движение мяча, нам нужна функция обновления. Добавьте следующий код внизу вашего файла JavaScript, чтобы добавить метод <code>update()</code> к <code>Ball()</code>'s <code>prototype</code>:</p> + +<pre class="brush: js notranslate">Ball.prototype.update = function() { + if ((this.x + this.size) >= width) { + this.velX = -(this.velX); + } + + if ((this.x - this.size) <= 0) { + this.velX = -(this.velX); + } + + if ((this.y + this.size) >= height) { + this.velY = -(this.velY); + } + + if ((this.y - this.size) <= 0) { + this.velY = -(this.velY); + } + + this.x += this.velX; + this.y += this.velY; +}</pre> + +<p>Первые четыре части функции проверяют, достиг ли шар края холста. Если это так, мы изменяем полярность соответствующей скорости, чтобы заставить шар двигаться в противоположном направлении. Так, например, если мяч двигался вверх (положительный <code>velY</code>), то вертикальная скорость изменяется так, что он начинает двигаться вниз (отрицательная величина <code>velY</code>).</p> + +<p>В этих четырех случаях мы:</p> + +<ul> + <li>Проверяем больше ли координата <code>x</code>, чем ширина холста (мяч уходит с правого края).</li> + <li>Проверяем будет ли координата <code>x</code> меньше 0 (мяч уходит с левого края).</li> + <li>Проверяем будет ли координата <code>y</code> больше высоты холста (мяч уходит с нижнего края).</li> + <li>Проверяем будет ли координата <code>y</code> меньше 0 (мяч уходит с верхнего края).</li> +</ul> + +<p>В каждом случае мы включаем <code>size</code> шарика в расчет, потому что координаты <code>x</code>/<code>y</code> находятся в центре шара, но мы хотим, чтобы край шара отскакивал от периметра - мы не хотим, чтобы мяч на половину заходил за границу экрана прежде чем он начнет возвращаться назад.</p> + +<p>Последние две строки добавляют значение <code>velX</code> к координате <code>x</code>, а значение <code>velY</code> - координате <code>y</code> - шар фактически перемещается при каждом вызове этого метода.</p> + +<p>На сейчас этого достаточно, давайте продолжим анимацию!</p> + +<h2 id="Анимация_мяча">Анимация мяча</h2> + +<p>Теперь давайте приступать к веселью! Сейчас мы начнем добавлять шары к холсту и анимировать их.</p> + +<ol> + <li>Во-первых, нам нужно где-то хранить все наши шары. Следующий массив выполнит это задание - добавьте его внизу кода: + <pre class="brush: js notranslate">var balls = [];</pre> + + <p>Все программы, которые оживляют вещи, обычно включают цикл анимации, который служит для обновления информации в программе, а затем визуализации результирующего представления для каждого кадра анимации; это основа для большинства игр и других подобных программ.</p> + </li> + <li>Добавьте ниже эту часть кода: + <pre class="brush: js notranslate">function loop() { + ctx.fillStyle = 'rgba(0, 0, 0, 0.25)'; + ctx.fillRect(0, 0, width, height); + + while (balls.length < 25) { + var ball = new Ball( + random(0,width), + random(0,height), + random(-7,7), + random(-7,7), + 'rgb(' + random(0,255) + ',' + random(0,255) + ',' + random(0,255) +')', + random(10,20) + ); + balls.push(ball); + } + + for (var i = 0; i < balls.length; i++) { + balls[i].draw(); + balls[i].update(); + } + + requestAnimationFrame(loop); +}</pre> + + <p>Наша функция <code>loop()</code> выполняет следующие действия:</p> + + <ul> + <li>Устанавливает цвет заливки на полупрозрачный черный, затем рисует прямоугольник цвета по всей ширине и высоте холста, используя <code>fillRect()</code> (четыре параметра обеспечивают начальную координату, а ширину и высоту для рисованного прямоугольника ). Это позволяет скрыть рисунок предыдущего кадра до того, как будет нарисован следующий. Если вы этого не сделаете, вы увидите, как длинные змеи пробираются вокруг холста, а не шары! Цвет заливки устанавливается на полупрозрачный, <code>rgba(0,0,0,0,25)</code>, чтобы позволить нескольким кадрам слегка просвечивать, создавая маленькие тропы за шариками по мере их перемещения. Если вы изменили 0.25 на 1, вы больше не увидите их. Попробуйте изменить это число, чтобы увидеть эффект, который он имеет.</li> + <li>Создает новый экземпляр нашего <code>Ball()</code>, используя случайные значения, сгенерированные с помощью нашей функции <code>random()</code>, затем <code>push()</code> на конец нашего массива шаров, но только в том случае, когда количество шаров в массиве меньше 25. Итак когда у нас есть 25 мячей на экране, больше не появляется шаров. Вы можете попробовать изменить число в <code>balls.length < 25</code>, чтобы получить больше или меньше шаров на экране. В зависимости от того, сколько вычислительной мощности имеет ваш компьютер / браузер, если указать несколько тысячь шаров, это может довольно существенно повлиять на производительность анимации. </li> + <li>перебирает все шары в массиве <code>balls</code> и запускает каждую функцию <code>draw()</code> и <code>update()</code> для рисования каждого из них на экране, а затем выполняет необходимые обновления по положению и скорости во времени для следующего кадра.</li> + <li>Выполняет функцию снова с помощью метода <code>requestAnimationFrame()</code> - когда этот метод постоянно запускается и передается одно и то же имя функции, он будет запускать эту функцию определенное количество раз в секунду для создания плавной анимации. Обычно это делается рекурсивно - это означает, что функция вызывает себя каждый раз, когда она запускается, поэтому она будет работать снова и снова.</li> + </ul> + </li> + <li>И последнее, но не менее важное: добавьте следующую строку в конец вашего кода - нам нужно вызвать функцию один раз, чтобы начать анимацию. + <pre class="brush: js notranslate">loop();</pre> + </li> +</ol> + +<p>Вот и все для основы - попробуйте сохранить и освежить, чтобы проверить свои прыгающие шары!</p> + +<h2 id="Добавление_обнаружения_столкновений">Добавление обнаружения столкновений</h2> + +<p>Теперь немного поиграем, давайте добавим в нашу программу обнаружение конфликтов, поэтому наши мячи узнают, когда они ударят по другому шару.</p> + +<ol> + <li>Прежде всего, добавьте следующее определение метода ниже, где вы определили метод <code>update()</code> (т.е. блок <code>Ball.prototype.update</code>). + + <pre class="brush: js notranslate">Ball.prototype.collisionDetect = function() { + for (var j = 0; j < balls.length; j++) { + if (!(this === balls[j])) { + var dx = this.x - balls[j].x; + var dy = this.y - balls[j].y; + var distance = Math.sqrt(dx * dx + dy * dy); + + if (distance < this.size + balls[j].size) { + balls[j].color = this.color = 'rgb(' + random(0, 255) + ',' + random(0, 255) + ',' + random(0, 255) +')'; + } + } + } +}</pre> + + <p>Этот метод немного сложный, поэтому не беспокойтесь, если вы не понимаете, как именно это работает. Ниже приводится объяснение:</p> + + <ul> + <li>Для каждого шара нам нужно проверить каждый другой шар, чтобы увидеть, столкнулся ли он с текущим мячом. Чтобы сделать это, мы открываем еще один цикл <code>for</code> через все шары в массиве <code>balls[]</code>.</li> + <li>Сразу же в нашем цикле for мы используем оператор <code>if</code>, чтобы проверить, проходит ли текущий шарик, тот же самый шар, что и тот, который мы сейчас проверяем. Мы не хотим проверять, что мяч столкнулся с самим собой! Для этого мы проверяем, является ли текущий мяч (т.е. мяч, метод которого вызван методом collisionDetect) такой же, как шар петли (т.е. шар, на который ссылается текущая итерация цикла for в collisionDetect метод). Затем мы используем <code>!</code> чтобы отменить проверку, чтобы код внутри оператора if выполнялся только в том случае, если они <strong>не</strong> совпадают.</li> + <li>Затем мы используем общий алгоритм для проверки столкновения двух окружностей. Мы в основном проверяем, перекрывается ли какая-либо из областей круга. Это объясняется далее <a href="https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection">2D collision detection</a>.</li> + <li>Если обнаружено столкновение, выполняется код внутри внутреннего оператора <code>if</code>. В этом случае мы просто устанавливаем свойство <code>color</code> обоих кругов на новый случайный цвет. Мы могли бы сделать что-то гораздо более сложное, например, заставить шары отскакивать друг от друга реалистично, но это было бы гораздо сложнее реализовать. Для такого моделирования физики разработчики склонны использовать игры или библиотеку физики, такие как <a href="http://wellcaffeinated.net/PhysicsJS/">PhysicsJS</a>, <a href="http://brm.io/matter-js/">matter.js</a>, <a href="http://phaser.io/">Phaser</a> и т.д.</li> + </ul> + </li> + <li>Вы также должны вызвать этот метод в каждом кадре анимации. Добавьте следующий код после строки <code>balls[i].update();</code> + <pre class="brush: js notranslate">balls[i].collisionDetect();</pre> + </li> + <li>Сохраните и обновите демо снова, и вы увидите, как ваши мячи меняют цвет, когда они сталкиваются!</li> +</ol> + +<div class="note"> +<p><strong>Примечание</strong>. Если вам не удается заставить этот пример работать, попробуйте сравнить код JavaScript с нашей <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main-finished.js">готовой версией</a> (также смотрите, как он работает <a href="https://mdn.github.io/learning-area/javascript/oojs/bouncing-balls/index-finished.html">в прямом эфире</a>).</p> +</div> + +<h2 id="Резюме">Резюме</h2> + +<p>Мы надеемся, что вам понравилось писать собственный пример случайных прыгающих шаров в реальном мире, используя различные объектные и объектно-ориентированные методы из всего модуля! Это должно было дать вам некоторую полезную практику использования объектов и хорошего контекста реального мира.</p> + +<p>Вот и все для предметных статей - все, что осталось сейчас, - это проверить свои навыки в оценке объекта.</p> + +<h2 id="Смотрите_также">Смотрите также</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/Canvas_API/Tutorial">Canvas tutorial</a> — руководство для новичков по использованию 2D-холста.</li> + <li><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></li> + <li><a href="/en-US/docs/Games/Techniques/2D_collision_detection">2D collision detection</a></li> + <li><a href="/en-US/docs/Games/Techniques/3D_collision_detection">3D collision detection</a></li> + <li><a href="/en-US/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript">2D breakout game using pure JavaScript</a> — a great beginner's tutorial showing how to build a 2D game.</li> + <li><a href="/en-US/docs/Games/Tutorials/2D_breakout_game_Phaser">2D breakout game using Phaser</a> — explains the basics of building a 2D game using a JavaScript game library.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}</p> + +<h2 id="В_этом_модуле">В этом модуле</h2> + +<ul> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B">Основы объекта</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Object-oriented_JS">Объектно-ориентированный JavaScript для начинающих</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Object_prototypes">Прототипы объектов</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Inheritance">Наследование в JavaScript</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/JSON">Работа с данными JSON</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Object_building_practice">Практика построения объектов</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Adding_bouncing_balls_features">Добавление функций в нашу демонстрацию прыгающих шаров</a></li> +</ul> diff --git a/files/ru/learn/javascript/objects/object_prototypes/index.html b/files/ru/learn/javascript/objects/object_prototypes/index.html new file mode 100644 index 0000000000..0a76580d9c --- /dev/null +++ b/files/ru/learn/javascript/objects/object_prototypes/index.html @@ -0,0 +1,285 @@ +--- +title: Прототипы объектов +slug: Learn/JavaScript/Объекты/Object_prototypes +tags: + - JavaScript + - create() + - Конструктор + - Начинающий + - ООП + - Обучение + - Обьект + - Статья + - прототип +translation_of: Learn/JavaScript/Objects/Object_prototypes +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}</div> + +<div>Прототипы - это механизм, с помощью которого объекты JavaScript наследуют свойства друг от друга. В этой статье мы объясним, как работают цепочки прототипов, и рассмотрим, как свойство prototype можно использовать для добавления методов к существующим конструкторам.</div> + +<div></div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Необходимые знания:</th> + <td> + <p>Базовая компьютерная грамотность, базовое понимание HTML и CSS, знакомство с основами JavaScript (см. <a href="/ru/docs/Learn/JavaScript/%D0%9F%D0%B5%D1%80%D0%B2%D1%8B%D0%B5_%D1%88%D0%B0%D0%B3%D0%B8">Первые шаги</a> и <a href="ru/docs/Learn/JavaScript/Building_blocks">Строительные блоки</a>) и основы OOJS (см. <a href="/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B">Введение в объекты</a>).</p> + </td> + </tr> + <tr> + <th scope="row">Цель:</th> + <td> + <p>Понять прототипы объектов JavaScript, как работают прототипные цепочки и как добавить новые методы в <code>prototype</code> свойство.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Язык_основанный_на_прототипах">Язык основанный на прототипах?</h2> + +<p>JavaScript часто описывают как язык <strong>прототипного наследования</strong> — каждый объект, имеет <strong>объект-прототип</strong>, который выступает как шаблон, от которого объект наследует методы и свойства. Объект-прототип так же может иметь свой прототип и наследовать его свойства и методы и так далее. Это часто называется <strong>цепочкой прототипов </strong>и объясняет почему одним объектам доступны свойства и методы которые определены в других объектах.</p> + +<p>Точнее, свойства и методы определяются в свойстве <code>prototype</code> функции-конструктора объектов, а не в самих объектах.</p> + +<p>В JavaScript создается связь между экземпляром объекта и его прототипом (свойство <code>__proto__</code>, которое является производным от свойства <code>prototype</code> конструктора), а свойства и методы обнаруживаются при переходе по цепочке прототипов.</p> + +<div class="note"> +<p><strong>Примечание</strong>: Важно понимать, что существует различие между прототипом объекта (который доступен через <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf">Object.getPrototypeOf(obj)</a></code> или через устаревшее свойство <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto">__proto__</a></code>) и свойством <code>prototype</code> в функциях-конструкторах. Первое свойство является свойством каждого экземпляра, а второе - свойством конструктора. То есть <code>Object.getPrototypeOf(new Foobar())</code> относится к тому же объекту, что и <code>Foobar.prototype</code>.</p> +</div> + +<p>Давайте посмотрим на пример, чтобы стало понятнее.</p> + +<h2 id="Понимание_прототипа_объектов">Понимание прототипа объектов</h2> + +<p>Вернемся к примеру, когда мы закончили писать наш конструктор <code>Person()</code>- загрузите пример в свой браузер. Если у вас еще нет работы от последней статьи, используйте наш пример <a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html">oojs-class-further-exercises.html</a> (см. Также <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">исходный код</a>).</p> + +<p>В этом примере мы определили конструкторную функцию, например:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">function</span> <span class="function token">Person</span><span class="punctuation token">(</span>first<span class="punctuation token">,</span> last<span class="punctuation token">,</span> age<span class="punctuation token">,</span> gender<span class="punctuation token">,</span> interests<span class="punctuation token">)</span> <span class="punctuation token">{</span> + + <span class="comment token">// Определения методов и свойств</span> + </code><code> this.name = { + 'first': first, + 'last' : last + }; + this.age = age; + this.gender = gender; + //...см. </code><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B">Введение в объекты</a> для полного определения<code class="language-js"> +<span class="punctuation token">}</span></code></pre> + +<p>Затем мы создаём экземпляр объекта следующим образом:</p> + +<pre class="brush: js">var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);</pre> + +<p>Если вы наберете «<code>person1.</code>» в вашей консоли JavaScript, вы должны увидеть, что браузер пытается автоматически заполнить это с именами участников, доступных на этом объекте:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13853/object-available-members.png" style="display: block; margin: 0 auto;"></p> + +<p>В этом списке вы увидите элементы, определенные в конструкторе person 1 — Person() — <code>name</code>, <code>age</code>, <code>gender</code>, <code>interests</code>, <code>bio</code>, и <code>greeting</code>. Однако вы также увидите некоторые другие элементы — <code>watch</code>, <code>valueOf</code>и т. д. — они определены в объекте прототипа Person (), который является <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">Object</a></code>.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13891/MDN-Graphics-person-person-object-2.png" style="display: block; height: 150px; margin: 0px auto; width: 700px;"></p> + +<p>Итак, что произойдет, если вы вызываете метод в <code>person1</code>, который фактически определен в <code>Object</code>? Например:</p> + +<pre class="brush: js">person1.valueOf()</pre> + +<p>Этот метод — <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf">Object.valueOf()</a></code>наследуется <code>person1</code>, потому что его конструктором является <code>Person()</code>, а прототипом <code>Person()</code> является <code>Object()</code>. <code>valueOf()</code> возвращает значение вызываемого объекта — попробуйте и убедитесь! В этом случае происходит следующее:</p> + +<ul> + <li>Сначала браузер проверяет, имеет ли объект <code>person1</code> доступный в нем метод <code>valueOf()</code>, как определено в его конструкторе <code>Person()</code>.</li> + <li>Это не так, поэтому следующим шагом браузер проверяет, имеет ли прототип объекта (<code>Object()</code>) конструктора <code>Person()</code> доступный в нем метод <code>valueOf()</code>. Так оно и есть, поэтому он вызывается, и все хорошо!</li> +</ul> + +<div class="note"> +<p><strong>Примечание:</strong> Мы хотим повторить, что методы и свойства <strong>не</strong> копируются из одного объекта в другой в цепочке прототипов - к ним обращаются, поднимаясь по цепочке, как описано выше.</p> +</div> + +<div class="note"> +<p><strong>Примечание</strong>: Официально нет способа получить доступ к объекту прототипа объекта напрямую - «ссылки» между элементами в цепочке определены во внутреннем свойстве, называемом <code>[[prototype]]</code> в спецификации для языка JavaScript ( см. {{glossary("ECMAScript")}}). Однако у большинства современных браузеров есть свойство, доступное для них под названием <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto">__proto__</a></code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto"> </a>(это 2 подчеркивания с обеих сторон), который содержит объект-прототип объекта-конструктора. Например, попробуйте <code>person1.__proto__</code> и <code>person1.__proto__.__proto__</code>, чтобы увидеть, как выглядит цепочка в коде!</p> + +<p>С ECMAScript 2015 вы можете косвенно обращаться к объекту прототипа объекта <code>Object.getPrototypeOf (obj)</code>.</p> +</div> + +<h2 id="Свойство_prototype_Где_определены_унаследованные_экземпляры">Свойство prototype: Где определены унаследованные экземпляры</h2> + +<p>Итак, где определены наследуемые свойства и методы? Если вы посмотрите на страницу со ссылкой <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">Object</a></code>, вы увидите в левой части большое количество свойств и методов - это намного больше, чем количество унаследованных членов, доступных для объекта <code>person1</code>. Некоторые из них унаследованы, а некоторые нет - почему это?</p> + +<p>Как упоминалось выше, наследованные свойства это те, что определены в свойстве <code>prototype</code> (вы можете называть это подпространством имен), то есть те, которые начинаются с <code>Object.prototype.</code>, а не те, которые начинаются с простого <code>Object</code>. Значение свойства <code>prototype</code> - это объект, который в основном представляет собой контейнер для хранения свойств и методов, которые мы хотим наследовать объектами, расположенными дальше по цепочке прототипов.</p> + +<p>Таким образом <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/watch">Object.prototype.watch()</a></code>, <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf">Object.prototype.valueOf()</a></code> и т. д. доступны для любых типов объектов, которые наследуются от <code>Object.prototype</code>, включая новые экземпляры объектов, созданные из конструктора <code>Person()</code> .</p> + +<p><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is">Object.is()</a></code>, <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys">Object.keys()</a></code> и другие члены, не определенные в контейнере <code>prototype</code>, не наследуются экземплярами объектов или типами объектов, которые наследуются от <code>Object.prototype</code>. Это методы / свойства, доступные только в конструкторе <code>Object()</code>.</p> + +<div class="note"> +<p><strong>Примечание</strong>: Это кажется странным - как у вас есть метод, определенный для конструктора, который сам по себе является функцией? Ну, функция также является типом объекта - см. Ссылку на конструктор <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function">Function()</a></code>, если вы нам не верите.</p> +</div> + +<ol> + <li>Вы можете проверить существующие свойства прототипа для себя - вернитесь к нашему предыдущему примеру и попробуйте ввести следующее в консоль JavaScript: + <pre class="brush: js">Person.prototype</pre> + </li> + <li>Результат покажет вам не много, ведь мы ничего не определили в прототипе нашего конструктора! По умолчанию <code>prototype</code> конструктора всегда пуст. Теперь попробуйте следующее: + <pre class="brush: js">Object.prototype</pre> + </li> +</ol> + +<p>Вы увидите большое количество методов, определенных для свойства <code>prototype</code> <code>Object</code>'а , которые затем доступны для объектов, которые наследуются от <code>Object</code>, как показано выше.</p> + +<p>Вы увидите другие примеры наследования цепочек прототипов по всему JavaScript - попробуйте найти методы и свойства, определенные на прототипе глобальных объектов <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code>, <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date">Date</a></code>, <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">Number</a></code> и <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a></code>, например. Все они имеют несколько элементов, определенных на их прототипе, поэтому, например, когда вы создаете строку, вот так:</p> + +<pre class="brush: js">var myString = 'This is my string.';</pre> + +<p>В <code>myString</code> сразу есть множество полезных методов, таких как <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split">split()</a></code>, <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf">indexOf()</a></code>, <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace">replace()</a></code> и т. д.</p> + +<div class="warning"> +<p><strong>Важно</strong>: Свойство <code>prototype</code> является одной из наиболее противоречивых названий частей JavaScript - вы можете подумать, что <code>this</code> указывает на объект прототипа текущего объекта, но это не так (это внутренний объект, к которому можно получить доступ <code>__proto__</code>, помните ?). <code>prototype</code> вместо этого - свойство, содержащее объект, на котором вы определяете членов, которые вы хотите наследовать.</p> +</div> + +<h2 id="Снова_create">Снова create()</h2> + +<p>Ранее мы показали, как метод <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create">Object.create()</a></code> может использоваться для создания нового экземпляра объекта.</p> + +<ol> + <li>Например, попробуйте это в консоли JavaScript предыдущего примера: + <pre class="brush: js">var person2 = Object.create(person1);</pre> + </li> + <li>На самом деле <code>create()</code>создает новый объект из указанного объекта-прототипа. Здесь <code>person2</code> создается с помощью <code>person1</code> в качестве объекта-прототипа. Это можно проверить, введя в консоли следующее: + <pre class="brush: js">person2.__proto__</pre> + </li> +</ol> + +<p>Это вернет объект <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">person1</span></font>.</p> + +<h2 id="Свойство_constructor">Свойство constructor</h2> + +<p>Каждая функция-конструктор имеет свойство <code>prototype</code>, значением которого является объект, содержащий свойство <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor">constructor</a></code>. Это свойство <code>constructor</code> указывает на исходную функцию-конструктор. Как вы увидите в следующем разделе, свойства, определенные в свойстве <code>Person.prototype</code> (или в общем случае в качестве свойства прототипа функции конструктора, который является объектом, как указано в предыдущем разделе) становятся доступными для всех объектов экземпляра, созданных с помощью конструктор <code>Person()</code>. Следовательно, свойство конструктора также доступно для объектов <code>person1</code> и <code>person2</code>.</p> + +<ol> + <li>Например, попробуйте эти команды в консоли: + <pre class="brush: js">person1.constructor +person2.constructor</pre> + + <p>Они должны возвращать конструктор <code>Person()</code>, поскольку он содержит исходное определение этих экземпляров.</p> + + <p>Хитрый трюк заключается в том, что вы можете поместить круглые скобки в конец свойства <code>constructor</code> (содержащие любые требуемые параметры) для создания другого экземпляра объекта из этого конструктора. Конструктор - это функция в конце концов, поэтому ее можно вызвать с помощью круглых скобок; вам просто нужно включить ключевое слово <code>new</code>, чтобы указать, что вы хотите использовать эту функцию в качестве конструктора.</p> + </li> + <li>Попробуйте это в консоли: + <pre class="brush: js">var person3 = new person1.constructor('Karen', 'Stephenson', 26, 'female', ['playing drums', 'mountain climbing']);</pre> + </li> + <li>Теперь попробуйте получить доступ к функциям вашего нового объекта, например: + <pre class="brush: js">person3.name.first +person3.age +person3.bio()</pre> + </li> +</ol> + +<p>Это хорошо работает. Вам не нужно будет использовать его часто, но это может быть действительно полезно, если вы хотите создать новый экземпляр и не имеете ссылки на исходный конструктор, который легко доступен по какой-либо причине.</p> + +<p>Свойство <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor">constructor</a></code> имеет другие применения. Например, если у вас есть экземпляр объекта и вы хотите вернуть имя конструктора этого экземпляра, вы можете использовать следующее:</p> + +<pre class="brush: js">instanceName.constructor.name</pre> + +<p>Например, попробуйте это:</p> + +<pre class="brush: js">person1.constructor.name +</pre> + +<div class="note"> +<p><strong>Примечание</strong>: Значение <code>constructor.name</code> может измениться (из-за прототипического наследования, привязки, препроцессоров, транспилеров и т. д.), Поэтому для более сложных примеров вы захотите использовать оператор <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof">instanceof</a></code>.</p> +</div> + +<ol> +</ol> + +<h2 id="Изменение_прототипов">Изменение прототипов</h2> + +<p>Давайте рассмотрим пример изменения свойства <code>prototype</code> функции-конструктора — методы, добавленные в прототип, затем доступны для всех экземпляров объектов, созданных из конструктора.</p> + +<ol> + <li>Вернитесь к нашему примеру <a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html">oojs-class-further-exercises.html</a> и создайте локальную копию <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">исходного кода</a>. Ниже существующего JavaScript добавьте следующий код, который добавляет новый метод в свойство <code>prototype</code> конструктора: + + <pre class="brush: js">Person.prototype.farewell = function() { + alert(this.name.first + ' has left the building. Bye for now!'); +};</pre> + </li> + <li>Сохраните код и загрузите страницу в браузере и попробуйте ввести следующее в текстовый ввод: + <pre class="brush: js">person1.farewell();</pre> + </li> +</ol> + +<p>Должно появиться всплывающее окно, с именем пользователя, определенным в конструкторе. Это действительно полезно, но ещё более полезно то, что вся цепочка наследования обновляется динамически, автоматически делая этот новый метод доступным для всех экземпляров объектов, полученных из конструктора.</p> + +<p>Подумайте об этом на мгновение. В нашем коде мы определяем конструктор, затем мы создаем экземпляр объекта из конструктора, <em>затем</em> добавляем новый метод к прототипу конструктора:</p> + +<pre class="brush: js">function Person(first, last, age, gender, interests) { + + // определения свойств и методов + +} + +var person1 = new Person('Tammi', 'Smith', 32, 'neutral', ['music', 'skiing', 'kickboxing']); + +Person.prototype.farewell = function() { + alert(this.name.first + ' has left the building. Bye for now!'); +};</pre> + +<p>Но метод <code>farewell()</code> <em>по-прежнему</em> доступен в экземпляре объекта <code>person1</code> - его элементы были автоматически обновлены, чтобы включить недавно определенный метод <code>farewell()</code>.</p> + +<div class="note"> +<p><strong>Примечание:</strong> Если у вас возникли проблемы с получением этого примера для работы, посмотрите на наш пример <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-prototype.html">oojs-class-prototype.html</a> (см. также это <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-prototype.html">running live</a>).</p> +</div> + +<p>Вы редко увидите свойства, определенные в свойстве <code>prototype</code>, потому что они не очень гибки при таком определении. Например, вы можете добавить свойство следующим образом:</p> + +<pre class="brush: js">Person.prototype.fullName = 'Bob Smith';</pre> + +<p>Это не очень гибко, так как человека нельзя назвать так. Было бы намного лучше сделать это, создав <code>fullName</code> из <code>name.first</code> и <code>name.last</code>:</p> + +<pre class="brush: js">Person.prototype.fullName = this.name.first + ' ' + this.name.last;</pre> + +<p>Однако это не работает, поскольку в этом случае <code>this</code> будет ссылаться на глобальную область, а не на область функции. Вызов этого свойства вернет <code>undefined undefined</code>. Это отлично работало с методом, который мы определили ранее в прототипе, потому что он находится внутри области функций, которая будет успешно перенесена в область экземпляра объекта. Таким образом, вы можете определить постоянные свойства прототипа (т. е. те, которые никогда не нуждаются в изменении), но обычно лучше определять свойства внутри конструктора.</p> + +<p>Фактически, довольно распространенный шаблон для большего количества определений объектов - это определение свойств внутри конструктора и методов в прототипе. Это упрощает чтение кода, поскольку конструктор содержит только определения свойств, а методы разделены на отдельные блоки. Например:</p> + +<pre class="brush: js">// Определение конструктора и его свойств + +function Test(a, b, c, d) { + // определение свойств... +} + +// Определение первого метода + +Test.prototype.x = function() { ... }; + +// Определение второго метода + +Test.prototype.y = function() { ... }; + +//...и так далее</pre> + +<p>Этот образец можно увидеть в действии в примере <a href="https://github.com/zalun/school-plan-app/blob/master/stage9/js/index.js">приложения плана школы </a>Петра Залевы.</p> + +<h2 id="Резюме">Резюме</h2> + +<p>В этой статье рассмотрены прототипы объектов JavaScript (в том числе и то, как прототип цепочки объектов позволяет объектам наследовать функции друг от друга), свойство прототипа и как его можно использовать для добавления методов к конструкторам и другие связанные с этой статьёй темы.</p> + +<p>В следующей статье мы рассмотрим то, как вы можете реализовать наследование функциональности между двумя собственными настраиваемыми объектами.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}</p> + + + +<h2 id="В_этом_модуле">В этом модуле</h2> + +<ul> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/Основы">Основы объекта</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/Object-oriented_JS">Объектно-ориентированный JavaScript для начинающих</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/Object_prototypes">Прототипы объектов</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/Inheritance">Наследование в JavaScript</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/JSON">Работа с данными JSON</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/Object_building_practice">Практика построения объектов</a></li> + <li><a href="https://developer.mozilla.org/ru/docs/Learn/JavaScript/Объекты/Adding_bouncing_balls_features">Добавление функций в нашу демонстрацию прыгающих шаров</a></li> +</ul> |