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/09-classes/07-mixins/article.md
+93-90Lines changed: 93 additions & 90 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,102 +1,105 @@
1
1
# Примесь
2
2
3
-
В JavaScript мы можем использовать наследование только от одного объекта. Объект имеет единственный [[Prototype]]. И класс может расширить только один другой класс.
3
+
В JavaScript мы можем использовать наследование только от одного объекта. Объект имеет единственный `[[Prototype]]`. И класс может расширить только один другой класс.
4
4
5
-
Иногда это может ограничивать нас. Например, у нас есть класс StreetSweeper и класс Bicycle, и хотим создать StreetSweepingBicycle.
5
+
Иногда это может ограничивать нас. Например, у нас есть класс `StreetSweeper` и класс `Bicycle`, и хотим создать `StreetSweepingBicycle`.
6
6
7
-
Или, поговорим о программировании, у нас есть класс Renderer, который реализует шаблон и класс EventEmitter реализующий событие. И мы хотим объединить их функционалы вместе в классе Page. Создадим страницу, которая будет использовать шаблон, и использовать событие.
7
+
Или, поговорим о программировании, у нас есть класс `Renderer`, который реализует шаблон и класс `EventEmitter` реализующий событие. И мы хотим объединить их функционалы вместе в классе `Page`. Создадим страницу, которая будет использовать шаблон, и использовать событие.
8
8
9
9
Для таких случаев существует "примесь".
10
10
11
11
Как говориться в Википедии [примесь](https://ru.wikipedia.org/wiki/Mixin) является классом, который имеет методы и мы можем их использовать в других классов, без необходимости быть родителем этих классов.
12
12
13
-
Другими словами примесь определяет методы, которые реализуют определенное поведение. Мы не используем его в одиночку, а используем его, чтобы добавить другим классам больше функционала.
13
+
Другими словами *примесь* определяет методы, которые реализуют определенное поведение. Мы не используем его в одиночку, а используем его, чтобы добавить другим классам больше функционала.
14
14
15
15
## Пример примеси
16
16
17
17
Простой путь создать примесь в JavaScript - это создать объект с использующимися методами, так что мы легко можем объединить их в прототип любого класса.
18
18
19
-
В примере ниже примесь sayHiMixin имеет методы для речи User'a:
19
+
В примере ниже примесь `sayHiMixin` имеет методы для речи класса `User`:
20
20
21
-
js run
21
+
```js run
22
22
*!*
23
23
// примесь
24
24
*/!*
25
25
let sayHiMixin = {
26
-
sayHi() {
27
-
alert(Hello ${this.name});
28
-
},
29
-
sayBye() {
30
-
alert(Bye ${this.name});
31
-
}
26
+
sayHi() {
27
+
alert(`Hello ${this.name}`);
28
+
},
29
+
sayBye() {
30
+
alert(`Bye ${this.name}`);
31
+
}
32
32
};
33
33
34
34
*!*
35
35
// использование:
36
36
*/!*
37
37
classUser {
38
-
constructor(name) {
39
-
this.name = name;
40
-
}
38
+
constructor(name) {
39
+
this.name= name;
40
+
}
41
41
}
42
42
43
43
// копируем методы
44
44
Object.assign(User.prototype, sayHiMixin);
45
45
46
46
// сейчас User можем сказать hi
47
47
newUser("Dude").sayHi(); // Hello Dude!
48
+
```
48
49
49
-
Это не наследование, а простой способ скопировать методы. Таким образом, класс User может расширять другие классы и так же содержать в себе методы от примеси, например:
50
+
Это не наследование, а простой способ скопировать методы. Таким образом, класс `User` может расширять другие классы и так же содержать в себе методы от примеси, например:
50
51
51
-
js
52
+
```js
52
53
classUserextendsPerson {
53
54
// ...
54
55
}
55
56
56
57
Object.assign(User.prototype, sayHiMixin);
58
+
```
57
59
58
60
Примеси могут использовать наследование между собой.
59
61
60
-
В примере ниже sayHiMixin наследуется от sayMixin :
62
+
В примере ниже `sayHiMixin` наследуется от `sayMixin` :
61
63
62
-
js run
64
+
```js run
63
65
let sayMixin = {
64
-
say(phrase) {
65
-
alert(phrase);
66
-
}
66
+
say(phrase) {
67
+
alert(phrase);
68
+
}
67
69
};
68
70
69
71
let sayHiMixin = {
70
-
__proto__: sayMixin, // (или мы можем использовать Object.create для определения прототипа)
71
-
72
-
sayHi() {
73
-
*!*
74
-
// вызываем метод родителя
75
-
*/!*
76
-
super.say(Hello ${this.name});
77
-
},
78
-
sayBye() {
79
-
super.say(Bye ${this.name});
80
-
}
72
+
__proto__: sayMixin, // (или мы можем использовать Object.create для определения прототипа)
73
+
74
+
sayHi() {
75
+
*!*
76
+
// вызываем метод родителя
77
+
*/!*
78
+
super.say(`Hello ${this.name}`);
79
+
},
80
+
sayBye() {
81
+
super.say(`Bye ${this.name}`);
82
+
}
81
83
};
82
84
83
85
classUser {
84
-
constructor(name) {
85
-
this.name = name;
86
-
}
86
+
constructor(name) {
87
+
this.name= name;
88
+
}
87
89
}
88
90
89
91
// копируем методы
90
92
Object.assign(User.prototype, sayHiMixin);
91
93
92
94
// сейчас User может сказать hi
93
95
newUser("Dude").sayHi(); // Hello Dude!
96
+
```
94
97
95
-
Обратите внимание, что мы вызвали родительский метод super.say() из 'sayHiMixin' в прототипе другой примеси, а не в классе.
98
+
Обратите внимание, что мы вызвали родительский метод `super.say()` из `sayHiMixin` в прототипе другой примеси, а не в классе.
96
99
97
100

98
101
99
-
Это связано с тем, что методы из sayHiMixin имеют установку [[HomeObject]]. А super на самом деле означает sayHiMixin.__ proto__, а не User.__ proto__.
102
+
Это связано с тем, что методы из `sayHiMixin` имеют установку `[[HomeObject]]`. А `super` на самом деле означает `sayHiMixin.__ proto__`, а не `User.__ proto__`.
100
103
101
104
## Примесь события
102
105
@@ -108,72 +111,71 @@ new User("Dude").sayHi(); // Hello Dude!
108
111
109
112
Событие может иметь имя, необязательно, и связь между некоторыми дополнительными данными.
110
113
111
-
Например объект user может генерировать события "login", когда посетитель входит. А другой объект calendar может захотеть получать его события, чтобы загрузить календарь для вошедшего человека.
114
+
Например объект `user` может генерировать события `"login"`, когда посетитель входит. А другой объект `calendar` может захотеть получать его события, чтобы загрузить календарь для вошедшего человека.
112
115
113
-
Или menu может генерировать событие "select", когда меню элемент выбран, или другие объекты могут захотеть получить эту информацию и отреагировать на это событие.
116
+
Или `menu` может генерировать событие `"select"`, когда меню элемент выбран, или другие объекты могут захотеть получить эту информацию и отреагировать на это событие.
114
117
115
118
События — это способ «поделиться информацией» со всеми, кто этого захочет. Они могут быть полезны в любом классе, поэтому давайте сделаем для них пример:
116
119
117
-
js run
120
+
```js run
118
121
let eventMixin = {
119
-
/**
120
-
* Опишем события, используя:
121
-
* menu.on('select', function(item) { ... }
122
-
*/
123
-
on(eventName, handler) {
124
-
if (!this._eventHandlers) this._eventHandlers = {};
125
-
if (!this._eventHandlers[eventName]) {
126
-
this._eventHandlers[eventName] = [];
127
-
}
128
-
this._eventHandlers[eventName].push(handler);
129
-
},
130
-
131
-
/**
132
-
* Закроем событие, используя:
133
-
* menu.off('select', handler)
134
-
*/
135
-
off(eventName, handler) {
136
-
let handlers = this._eventHandlers && this._eventHandlers[eventName];
137
-
if (!handlers) return;
138
-
for (let i = 0; i< handlers.length; i++) {
139
-
if (handlers[i] === handler) {
140
-
handlers.splice(i--, 1);
141
-
}
142
-
}
143
-
},
144
-
145
-
/**
146
-
* Создадим событие и прикрепим данные
147
-
* this.trigger('select', data1, data2);
148
-
*/
149
-
trigger(eventName, ...args) {
150
-
if (!this._eventHandlers || !this._eventHandlers[eventName]) {
0 commit comments