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