You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/04-object-basics/01-object/article.md
+58-38Lines changed: 58 additions & 38 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -103,7 +103,9 @@ let user = {
103
103
user.likes birds =true
104
104
```
105
105
106
-
Так происходит, потому что точка требует, чтобы ключ был именован по правилам именования переменных. То есть не имел пробелов, не начинался с цифры и не содержал специальные символы, кроме `$` и `_`.
106
+
JavaScript видит, что мы обращаемся к свойству `user.likes`, а затем идёт непонятное слово `birds`. В итоге синтаксическая ошибка.
107
+
108
+
Точка требует, чтобы ключ был именован по правилам именования переменных. То есть не имел пробелов, не начинался с цифры и не содержал специальные символы, кроме `$` и `_`.
107
109
108
110
Для таких случаев существует альтернативный способ доступа к свойствам через квадратные скобки. Такой способ сработает с любым именем свойства:
109
111
@@ -208,42 +210,6 @@ let bag = {
208
210
209
211
Подведём итог: в большинстве случаев, когда имена свойств известны и просты, используется запись через точку. Если же нам нужно что-то более сложное, то мы используем квадратные скобки.
210
212
211
-
````smart header="Зарезервированные слова разрешено использовать как имена свойств"
212
-
213
-
Имя переменной не может совпадать с зарезервированными словами, такими как "for", "let", "return" и т.д.
214
-
215
-
Но для свойств объекта такого ограничения нет:
216
-
217
-
```js run
218
-
let obj = {
219
-
for: 1,
220
-
let: 2,
221
-
return: 3
222
-
};
223
-
224
-
alert( obj.for + obj.let + obj.return ); // 6
225
-
```
226
-
227
-
В принципе, разрешены любые имена свойств, но есть специальное свойство `__proto__`, которое по историческим причинам имеет особое поведение. Например, его значение всегда должно быть объектом, и мы не можем установить для него никакое другое значение:
228
-
229
-
```js run
230
-
let obj = {};
231
-
obj.__proto__ = 5;
232
-
alert(obj.__proto__); // [object Object], работает не так, как мы ожидали
233
-
```
234
-
235
-
Как мы видим, присвоение примитивного значения `5` игнорируется.
236
-
237
-
Это может стать источником ошибок и даже уязвимостей, если мы намереваемся хранить в объекте произвольные пары "ключ:значение" и позволяем посетителям указывать ключи.
238
-
239
-
Посетитель может указать `__proto__` в качестве ключа, и логика присваивания будет нарушена (как показано выше).
240
-
241
-
Есть способ заставить объекты обрабатывать `__proto__` как обычное свойство. Мы поговорим о нём позже, а пока нам нужно узнать больше об объектах.
242
-
243
-
Также существует другая структура данных [Map](info:map-set), которая поддерживает произвольные ключи. Мы изучим её в главе <info:map-set>.
244
-
````
245
-
246
-
247
213
## Свойство из переменной
248
214
249
215
В реальном коде часто нам необходимо использовать существующие переменные как значения для свойств с тем же именем.
@@ -288,7 +254,61 @@ let user = {
288
254
};
289
255
```
290
256
291
-
## Проверка существования свойства
257
+
## Ограничения на имена свойств
258
+
259
+
Мы можем использовать только строки и символы в качестве ключей свойств. Все другие типы данных будут автоматически преобразованы к строке.
260
+
261
+
Например, если использовать как ключ число `0`, то оно превратится в строку `"0"`:
262
+
263
+
```js run
264
+
let obj = {
265
+
0:"Тест"// то же самое что и "0": "Тест"
266
+
};
267
+
268
+
// обе функции alert выведут одно и то же свойство (число 0 преобразуется в строку "0")
269
+
alert( obj["0"] ); // Тест
270
+
alert( obj[0] ); // Тест (то же свойство)
271
+
```
272
+
273
+
**Зарезервированные слова разрешено использовать как имена свойств.**
274
+
275
+
Как мы уже знаем, имя переменной не может совпадать с зарезервированными словами, такими как "for", "let", "return" и т.д.
276
+
277
+
Но для свойств объекта такого ограничения нет:
278
+
279
+
```js run
280
+
let obj = {
281
+
for:1,
282
+
let:2,
283
+
return:3
284
+
};
285
+
286
+
alert( obj.for+obj.let+obj.return ); // 6
287
+
```
288
+
289
+
**В принципе, разрешены любые имена свойств, но есть специальное свойство `__proto__`, которое по историческим причинам имеет особое поведение.**
290
+
291
+
Например, его значение всегда должно быть объектом:
292
+
293
+
```js run
294
+
let obj = {};
295
+
obj.__proto__=5;
296
+
alert(obj.__proto__); // [object Object], работает не так, как мы ожидали
297
+
```
298
+
299
+
Как мы видим, присвоение примитивного значения `5` игнорируется.
300
+
301
+
Мы более подробно исследуем происходящее свойство `__proto__` позже, в главе [](info:prototype-inheritance).
302
+
303
+
Сейчас важно знать, что такое поведение `__proto__` может стать источником ошибок и даже уязвимостей, если мы намереваемся хранить в объекте произвольные данные и позволяем посетителям указывать ключи.
304
+
305
+
Посетитель может указать `"__proto__"` в качестве ключа, и логика присваивания будет нарушена (как показано выше).
306
+
307
+
Позже мы изучим, как обойти эту проблему:
308
+
1. Можно заставить объект обрабатывать `__proto__` как обычное свойство, мы это увидим в главе [](info:prototype-methods).
309
+
2. Есть другая структура данных [Map](info:map-set), которую мы изучим в главе <info:map-set>, она поддерживает произвольные ключи.
310
+
311
+
## Проверка существования свойства, оператор "in"
292
312
293
313
Особенность объектов в том, что можно получить доступ к любому свойству. Даже если свойства не существует - ошибки не будет! При обращении к свойству, которого нет, возвращается `undefined`. Это позволяет просто проверить существование свойства - сравнением его с `undefined`:
Copy file name to clipboardExpand all lines: 1-js/04-object-basics/03-symbol/article.md
-16Lines changed: 0 additions & 16 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -179,22 +179,6 @@ alert( clone[id] ); // 123
179
179
180
180
Здесь нет никакого парадокса или противоречия. Так и задумано. Идея заключается в том, что, когда мы клонируем или объединяем объекты, мы обычно хотим скопировать *все* свойства (включая такие свойства с ключами-символами, как, например, `id` в примере выше).
181
181
182
-
````smart header="Ключи других типов принудительно преобразуются к строке"
183
-
Мы можем использовать только строки и символы в качестве ключей свойств. Все другие типы данных будут автоматически преобразованы к строке.
184
-
185
-
Например, число `0`, будучи использованным как ключ свойства, превратится в строку `"0"`:
186
-
187
-
```js run
188
-
let obj = {
189
-
0: "Тест" // то же самое что и "0": "Тест"
190
-
};
191
-
192
-
// обе функции alert выведут одно и то же свойство (число 0 преобразовывается в строку "0")
193
-
alert( obj["0"] ); // Тест
194
-
alert( obj[0] ); // Тест (то же свойство)
195
-
```
196
-
````
197
-
198
182
## Глобальные символы
199
183
200
184
Итак, как мы видели, обычно все символы уникальны, даже если их имена совпадают. Но иногда мы наоборот хотим, чтобы символы с одинаковыми именами были одной сущностью. Например, разные части нашего приложения хотят получить доступ к символу `"id"`, подразумевая именно одно и то же свойство.
0 commit comments