Skip to content

Commit 645f1e3

Browse files
committed
fixes
1 parent ce7a22a commit 645f1e3

File tree

3 files changed

+48
-38
lines changed

3 files changed

+48
-38
lines changed

1-js/06-advanced-functions/12-arrow-functions/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# И ещё про стрелочные функции
1+
# Повторяем стрелочные функции
22

33
Давайте вернёмся к стрелочным функциям.
44

1-js/07-object-properties/01-property-descriptors/article.md

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33

44
Как мы знаем, объекты могут содержать свойства.
55

6-
До этого момента мы рассматривали свойство только как пару "ключ-значение". Но на самом деле свойство объекта - это гораздо более гибкое и мощное средство.
6+
До этого момента мы рассматривали свойство только как пару "ключ-значение". Но на самом деле свойство объекта гораздо мощнее и гибче.
77

8-
В этой главе мы изучим дополнительные опции конфигурации для свойств, а в следующей увидим, как можно незаметно превратить их в специальные функции - геттеры и сеттеры.
8+
В этой главе мы изучим дополнительные флаги конфигурации для свойств, а в следующей увидим, как можно незаметно превратить их в специальные функции - геттеры и сеттеры.
99

1010
## Флаги свойств
1111

12-
Помимо **`значения`**, свойства объекта имеют три специальных атрибута (так называемые "флаги").
12+
Помимо значения **`value`**, свойства объекта имеют три специальных атрибута (так называемые "флаги").
1313

1414
- **`writable`** -- если `true`, свойство можно изменить, иначе оно только для чтения.
1515
- **`enumerable`** -- если `true`, свойство перечисляется в циклах, в противном случае циклы его игнорируют.
@@ -63,14 +63,14 @@ Object.defineProperty(obj, propertyName, descriptor)
6363
```
6464

6565
`obj`, `propertyName`
66-
: Объект и свойство, с которыми мы будем работать.
66+
: Объект и его свойство, для которого нужно применить дескриптор.
6767

6868
`descriptor`
6969
: Применяемый дескриптор.
7070

7171
Если свойство существует, `defineProperty` обновит его флаги. В противном случае метод создает новое свойство с указанным значением и флагами; если какой-либо флаг не указан явно, ему присваивается значение `false`.
7272

73-
Например, все флаги свойства `name` в коде ниже создаются со значением `false`:
73+
Например, здесь создаётся свойство `name`, все флаги которого имеют значение `false`:
7474

7575
```js run
7676
let user = {};
@@ -116,40 +116,39 @@ Object.defineProperty(user, "name", {
116116
});
117117

118118
*!*
119-
user.name = "Pete"; // Ошибка: Невозможно изменить доступное только для чтения свойство 'name'...
119+
user.name = "Pete"; // Ошибка: Невозможно изменить доступное только для чтения свойство 'name'
120120
*/!*
121121
```
122122

123123
Теперь никто не сможет изменить имя пользователя, если только не обновит соответствующий флаг новым вызовом `defineProperty`.
124124

125125
```smart header="Ошибки появляются только в строгом режиме"
126-
В нестрогом режиме, без `use strict`, мы не увидим никаких ошибок при записи в свойства "только для чтения" и т.п. Эти операции всё равно не будут выполнены успешно. Действия, нарушающие ограничения флагов, в нестрогом режиме просто молча игнорируются.
126+
В нестрогом режиме, без `use strict`, мы не увидим никаких ошибок при записи в свойства "только для чтения" и т.п. Но эти операции всё равно не будут выполнены успешно. Действия, нарушающие ограничения флагов, в нестрогом режиме просто молча игнорируются.
127127
```
128128

129-
Вот та же самая операция, но в ситуации, когда свойства не существует:
129+
Вот тот же пример, но свойство создано "с нуля":
130130

131131
```js run
132132
let user = { };
133133

134134
Object.defineProperty(user, "name", {
135135
*!*
136-
value: "Pete",
136+
value: "John",
137137
// для нового свойства необходимо явно указывать все флаги, для которых значение true
138138
enumerable: true,
139139
configurable: true
140140
*/!*
141141
});
142142

143-
alert(user.name); // Pete
144-
user.name = "Alice"; // Ошибка
143+
alert(user.name); // John
144+
user.name = "Pete"; // Ошибка
145145
```
146146

147-
148147
## Неперечислимое свойство
149148

150149
Теперь добавим собственный метод `toString` к объекту `user`.
151150

152-
Обычно встроенный метод `toString` в объектах - неперечислимый, его не видно в цикле `for..in`. Но если мы напишем свой собственный метод `toString`, цикл `for..in` будет выводить его по умолчанию:
151+
Встроенный метод `toString` в объектах - неперечислимый, его не видно в цикле `for..in`. Но если мы напишем свой собственный метод `toString`, цикл `for..in` будет выводить его по умолчанию:
153152

154153
```js run
155154
let user = {
@@ -185,7 +184,7 @@ Object.defineProperty(user, "toString", {
185184
for (let key in user) alert(key); // name
186185
```
187186

188-
Неперечислимые свойства также исключаются из `Object.keys`:
187+
Неперечислимые свойства также не возвращаются `Object.keys`:
189188

190189
```js
191190
alert(Object.keys(user)); // name

1-js/07-object-properties/02-property-accessors/article.md

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,23 @@
99

1010
## Геттеры и сеттеры
1111

12-
Свойства-аксессоры записываются как методы: так называемый "геттер" - для чтения и "сеттер" - для записи. При литеральном объявлении объекта они обозначены `get` и `set`:
12+
Свойства-аксессоры представлены методами: "геттер" - для чтения и "сеттер" - для записи. При литеральном объявлении объекта они обозначаются `get` и `set`:
1313

1414
```js
1515
let obj = {
1616
*!*get propName()*/!* {
17-
// геттер, код получения obj.propName
17+
// геттер, срабатывает при чтении obj.propName
1818
},
1919

2020
*!*set propName(value)*/!* {
21-
// сеттер, код присвоения obj.propName = value
21+
// сеттер, срабатывает при записи obj.propName = value
2222
}
2323
};
2424
```
2525

2626
Геттер срабатывает, когда `obj.propName` читается, сеттер -- когда значение назначается.
2727

28-
Для примера, у нас есть объект `user` со свойствами `name` и `surname`:
28+
Например, у нас есть объект `user` со свойствами `name` и `surname`:
2929

3030
```js run
3131
let user = {
@@ -34,7 +34,7 @@ let user = {
3434
};
3535
```
3636

37-
А теперь добавим свойство объекта "fullName" для полного имени, которое в нашем случае: "John Smith". Само собой, мы не хотим дублировать уже имеющуюся информацию, так что реализуем его при помощи аксессора:
37+
А теперь добавим свойство объекта `fullName` для полного имени, которое в нашем случае: `"John Smith"`. Само собой, мы не хотим дублировать уже имеющуюся информацию, так что реализуем его при помощи аксессора:
3838

3939
```js run
4040
let user = {
@@ -55,7 +55,19 @@ alert(user.fullName); // John Smith
5555

5656
Снаружи свойство-аксессор выглядит как обычное свойство. В этом и заключается смысл свойств-аксессоров. Мы не *вызываем* `user.fullName` как функцию, а *читаем* как обычное свойство: геттер выполнит всю работу за кулисами.
5757

58-
На данный момент `fullName` имеет только геттер. Если попытаться присвоить значение свойству `user.fullName`, то это вызовет ошибку.
58+
На данный момент `fullName` имеет только геттер. Если попытаться присвоить значение свойству `user.fullName`, то это вызовет ошибку:
59+
60+
```js run
61+
let user = {
62+
get fullName() {
63+
return `...`;
64+
}
65+
};
66+
67+
*!*
68+
user.fullName = "Тест"; // Ошибка (у свойства есть только геттер)
69+
*/!*
70+
```
5971

6072
Давайте исправим это, добавив сеттер для `user.fullName`:
6173

@@ -82,15 +94,10 @@ alert(user.name); // Alice
8294
alert(user.surname); // Cooper
8395
```
8496

85-
В итоге мы получили "виртуальное" свойство fullName. Его можно прочитать и изменить, но по факту его не существует.
86-
87-
```smart header="Accessor properties are only accessible with get/set"
88-
Как только свойство определено с помощью `get prop()` или `set prop()`, оно становится свойством-аксессором, а не свойством-данных.
97+
В итоге мы получили "виртуальное" свойство `fullName`. Его можно прочитать и изменить, но по факту его не существует.
8998

90-
- Если определен геттер -- мы можем прочитать свойство `object.prop`, иначе нет.
91-
- Если определен сеттер -- мы можем установить свойство `object.prop=...`, иначе нет.
92-
93-
В обоих случаях мы не можем удалить свойство-аксессор.
99+
```smart header="Нет поддержки для `delete`"
100+
При попытке удалить свойство-аксессор оператором `delete` будет ошибка.
94101
```
95102
96103
@@ -100,14 +107,14 @@ alert(user.surname); // Cooper
100107
101108
Свойства-аксессоры не имеют `value` и `writable`, но взамен предлагают функции `get` и `set`.
102109
103-
Таким образом, дескриптор аксессора может иметь:
110+
То есть, дескриптор аксессора может иметь:
104111
105112
- **`get`** -- функция без аргументов, которая сработает при чтении свойства,
106113
- **`set`** -- функция, принимающая один аргумент, вызываемая при присвоении свойства,
107114
- **`enumerable`** -- то же самое, что и для свойств-данных,
108115
- **`configurable`** -- то же самое, что и для свойств-данных.
109116
110-
Например, для создания аксессора `fullName` при помощи `defineProperty`, мы можем передать дескриптор с использованием `get` и `set`:
117+
Например, для создания аксессора `fullName` при помощи `defineProperty` мы можем передать дескриптор с использованием `get` и `set`:
111118
112119
```js run
113120
let user = {
@@ -132,7 +139,7 @@ alert(user.fullName); // John Smith
132139
for(let key in user) alert(key); // name, surname
133140
```
134141

135-
Обратите внимание, что свойство объекта может быть только свойством-аксессора или свойством-данных.
142+
Ещё раз заметим, что свойство объекта может быть только свойством-аксессором (с методами `get/set`) или свойством-данных (со значением `value`).
136143

137144
При попытке указать и `get` и `value` в одном дескрипторе будет ошибка:
138145

@@ -151,9 +158,9 @@ Object.defineProperty({}, 'prop', {
151158

152159
## Умные геттеры/сеттеры
153160

154-
Геттеры/сеттеры можно использовать как обёртки над "реальными" значениями свойств, чтобы получить больше контроля над ними.
161+
Геттеры/сеттеры можно использовать как обёртки над "реальными" значениями свойств, чтобы получить больше контроля над операциями с ними.
155162

156-
Например, если мы хотим запретить устанавливать короткое имя для `user`, мы можем хранить `name` в специальном свойстве `_name`, отфильтровав значение в сеттере:
163+
Например, если мы хотим запретить устанавливать короткое имя для `user`, мы можем использовать сеттер `name` для проверки, а само значение хранить в отдельном свойстве `_name`:
157164

158165
```js run
159166
let user = {
@@ -176,14 +183,16 @@ alert(user.name); // Pete
176183
user.name = ""; // Имя слишком короткое...
177184
```
178185

186+
Таким образом, само имя хранится в `_name`, доступ к которому производится через геттер и сеттер.
187+
179188
Технически, внешний код всё ещё может получить доступ к имени напрямую с помощью `user._name`, но существует широко известное соглашение о том, что свойства, которые начинаются с символа `"_"`, являются внутренними, и к ним не следует обращаться извне пределов объекта.
180189

181190

182191
## Использование для совместимости
183192

184-
Одна из хороших идей, стоящих за геттерами и сеттерами -- они позволяют в любой момент взять "обычное" свойство и изменить его поведение, поменяв на геттер и сеттер.
193+
У аксессоров есть интересная область применения - они позволяют в любой момент взять "обычное" свойство и изменить его поведение, поменяв на геттер и сеттер.
185194

186-
Например, мы начали реализовывать объект `user`, используя свойства-данные `name` и `age`:
195+
Например, представим, что мы начали реализовывать объект `user`, используя свойства-данные имя `name` и возраст `age`:
187196

188197
```js
189198
function User(name, age) {
@@ -196,7 +205,7 @@ let john = new User("John", 25);
196205
alert( john.age ); // 25
197206
```
198207

199-
...Но рано или поздно всё может измениться. Взамен `age` мы можем решить хранить `birthday`, потому что так более точно и удобно:
208+
...Но рано или поздно всё может измениться. Взамен возраста `age` мы можем решить хранить дату рождения `birthday`, потому что так более точно и удобно:
200209

201210
```js
202211
function User(name, birthday) {
@@ -209,7 +218,9 @@ let john = new User("John", new Date(1992, 6, 1));
209218

210219
Что нам делать со старым кодом, который использует свойство `age`?
211220

212-
Мы можем попытаться найти все такие места и изменить их, но это отнимает время и может быть выполнимо, если код был написан/используется многими другими людьми. И кроме того, `age` -- это отличное свойство для `user`, верно? В некоторых ситуациях это то, что нам нужно.
221+
Мы можем попытаться найти все такие места и изменить их, но это отнимает время и может быть невыполнимо, если код был используется многими другими людьми. И кроме того, `age` -- это отличное свойство для `user`, верно?
222+
223+
Давайте его сохраним.
213224

214225
Добавление геттера для `age` решит проблему:
215226

0 commit comments

Comments
 (0)