Skip to content

Commit ba36b3a

Browse files
committed
Update mixins article
1 parent 6fbb125 commit ba36b3a

File tree

2 files changed

+61
-57
lines changed

2 files changed

+61
-57
lines changed
Lines changed: 56 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
# Mixins
22

3-
In JavaScript we can only inherit from a single object. There can be only one `[[Prototype]]` for an object. And a class may extend only one other class.
3+
Em JavaScript, só podemos herdar de um único objeto. Pode existir apenas um único `[[Prototype]]` para um objeto. E uma classe pode estender apenas uma outra classe.
44

5-
But sometimes that feels limiting. For instance, we have a class `StreetSweeper` and a class `Bicycle`, and want to make their mix: a `StreetSweepingBicycle`.
5+
Porém, algumas vezes isso parece limitante. Por exemplo, temos uma classe `StreetSweeper` e uma classe `Bicycle`, e queremos fazer uma mistura delas: uma classe `StreetSweepingBicycle`;
66

7-
Or we have a class `User` and a class `EventEmitter` that implements event generation, and we'd like to add the functionality of `EventEmitter` to `User`, so that our users can emit events.
7+
Ou temos uma classe `User` e uma classe `EventEmitter` que implementa a geração de eventos, e gostaríamos de adicionar a funcionalidade de `EventEmitter` à `User`, para que nossos usuários possam emitir eventos.
88

9-
There's a concept that can help here, called "mixins".
9+
Existe um conceito que pode ajudar aqui, chamado "mixins".
1010

11-
As defined in Wikipedia, a [mixin](https://en.wikipedia.org/wiki/Mixin) is a class containing methods that can be used by other classes without a need to inherit from it.
11+
Como definido no Wikipedia, um [mixin](https://en.wikipedia.org/wiki/Mixin) é uma classe contendo métodos que podem ser usados por outras classes sem a necessidade de herdar dela.
1212

13-
In other words, a *mixin* provides methods that implement a certain behavior, but we do not use it alone, we use it to add the behavior to other classes.
13+
Em outras palavras, um *mixin* fornece métodos que implementam um determinado comportamento, mas não o utilizamos sozinho, utilizamos ele para adicionar o comportamento a outras classes.
14+
## Um exemplo de mixin
1415

15-
## A mixin example
16+
A maneira mais simples de implementar um mixin em JavaScript é criando um objeto com métodos úteis, para que possamos facilmente mesclá-los em um prototype de qualquer classe.
1617

17-
The simplest way to implement a mixin in JavaScript is to make an object with useful methods, so that we can easily merge them into a prototype of any class.
18-
19-
For instance here the mixin `sayHiMixin` is used to add some "speech" for `User`:
18+
Por exemplo, aqui onde o mixin `sayHiMixin` é usado para adicionar alguma "fala" para `User`:
2019

2120
```js run
2221
*!*
@@ -32,22 +31,22 @@ let sayHiMixin = {
3231
};
3332

3433
*!*
35-
// usage:
34+
// Utilização:
3635
*/!*
3736
class User {
3837
constructor(name) {
3938
this.name = name;
4039
}
4140
}
4241

43-
// copy the methods
42+
// copia os métodos
4443
Object.assign(User.prototype, sayHiMixin);
4544

46-
// now User can say hi
45+
// agora User pode dizer oi
4746
new User("Dude").sayHi(); // Hello Dude!
4847
```
4948

50-
There's no inheritance, but a simple method copying. So `User` may inherit from another class and also include the mixin to "mix-in" the additional methods, like this:
49+
Não existe herança, mas uma simples cópia de método. Portanto, `User` pode herdar de uma outra classe e também incluir o mixin para "misturar" os métodos adicionais, assim:
5150

5251
```js
5352
class User extends Person {
@@ -57,9 +56,9 @@ class User extends Person {
5756
Object.assign(User.prototype, sayHiMixin);
5857
```
5958

60-
Mixins can make use of inheritance inside themselves.
59+
Mixins usar herança dentro deles mesmos.
6160

62-
For instance, here `sayHiMixin` inherits from `sayMixin`:
61+
Por exemplo, aqui `sayHiMixin` herda de `sayMixin`:
6362

6463
```js run
6564
let sayMixin = {
@@ -69,11 +68,11 @@ let sayMixin = {
6968
};
7069

7170
let sayHiMixin = {
72-
__proto__: sayMixin, // (or we could use Object.setPrototypeOf to set the prototype here)
71+
__proto__: sayMixin, // (ou poderíamos usar Object.setPrototypeOf para definir o prototype aqui)
7372

7473
sayHi() {
7574
*!*
76-
// call parent method
75+
// chama o método pai
7776
*/!*
7877
super.say(`Hello ${this.name}`); // (*)
7978
},
@@ -88,43 +87,47 @@ class User {
8887
}
8988
}
9089

91-
// copy the methods
90+
// copia os métodos
9291
Object.assign(User.prototype, sayHiMixin);
9392

94-
// now User can say hi
93+
// agora User pode dizer oi
9594
new User("Dude").sayHi(); // Hello Dude!
9695
```
9796

98-
Please note that the call to the parent method `super.say()` from `sayHiMixin` (at lines labelled with `(*)`) looks for the method in the prototype of that mixin, not the class.
9997

100-
Here's the diagram (see the right part):
98+
Observe que a chamada do método pai `super.say()` por `sayHiMixin` (las linhas marcadas com `(*)`) procura pelo método no prototype desse mixin, não na classe.
99+
100+
Aqui o diagrama (veja a parte direita):
101101

102102
![](mixin-inheritance.svg)
103103

104-
That's because methods `sayHi` and `sayBye` were initially created in `sayHiMixin`. So even though they got copied, their `[[HomeObject]]` internal property references `sayHiMixin`, as shown in the picture above.
104+
Isso porque os métodos `sayHi` e `sayBye` foram inicialmente criados em `sayHiMixin`. Portanto, mesmo que tenha sido copiados, suas propriedades internas `[[HomeObject]]` referencia a `sayHiMixin`, como mostrado na figura acima.
105+
105106

106-
As `super` looks for parent methods in `[[HomeObject]].[[Prototype]]`, that means it searches `sayHiMixin.[[Prototype]]`.
107+
Como `super` procura por métodos pais em `[[HomeObject]].[[Prototype]]`, isso significa que procura `sayHiMixin.[[Prototype]]`.
107108

108109
## EventMixin
109110

110-
Now let's make a mixin for real life.
111+
Vamos criar um mixin para a vida real.
111112

112-
An important feature of many browser objects (for instance) is that they can generate events. Events are a great way to "broadcast information" to anyone who wants it. So let's make a mixin that allows us to easily add event-related functions to any class/object.
113+
Uma característica importante de muitos objetos do navegador (por exemplo) é que eles podem gerar eventos. Eventos são uma ótima maneira de "transmitir informação" para qualquer um que a quiser. Então, vamos criar um mixin que nos permita adicionar facilmente funções relacionadas a eventos a qualquer classe/objeto.
113114

114-
- The mixin will provide a method `.trigger(name, [...data])` to "generate an event" when something important happens to it. The `name` argument is a name of the event, optionally followed by additional arguments with event data.
115-
- Also the method `.on(name, handler)` that adds `handler` function as the listener to events with the given name. It will be called when an event with the given `name` triggers, and get the arguments from the `.trigger` call.
116-
- ...And the method `.off(name, handler)` that removes the `handler` listener.
115+
- O mixin vai fornecer um método `.trigger(name, [...data])` para "gerar um evento" quando algo importante acontecer com ele. O argumento `name` é o nome do evento, opcionalmente seguido de argumentos adicionais com dados do evento.
117116

118-
After adding the mixin, an object `user` will be able to generate an event `"login"` when the visitor logs in. And another object, say, `calendar` may want to listen for such events to load the calendar for the logged-in person.
117+
- Além do método `.on(name, handler)` que adiciona a função `handler` como ouvinte de eventos com o dado nome. Ele será chamado quando um evento com o dado `name` disparar, e irá obter os argumentos da chamada de `.trigger`
119118

120-
Or, a `menu` can generate the event `"select"` when a menu item is selected, and other objects may assign handlers to react on that event. And so on.
119+
- ...E o método `.off(name, handler)` que remove o listener `handler`.
121120

122-
Here's the code:
121+
Após adicionar o mixin, um objeto `user` será capaz de gerar um evento `"login"` quando o visitante fizer login. Um outro objeto, digamos, `calendar` pode querer ouvir por tais eventos para carregar o calendário para a pessoa logada.
122+
123+
Ou, um `menu` pode gerar o evento `"select" quando um item do menu for selecionado`, e outros objetos podem atribuir manipuladores (handlers) para reagir aquele evento.
124+
125+
Aqui está o código:
123126

124127
```js run
125128
let eventMixin = {
126129
/**
127-
* Subscribe to event, usage:
130+
* Se inscreve ao evento, utilização:
128131
* menu.on('select', function(item) { ... }
129132
*/
130133
on(eventName, handler) {
@@ -136,7 +139,7 @@ let eventMixin = {
136139
},
137140

138141
/**
139-
* Cancel the subscription, usage:
142+
* Cancela a inscrição, utilização:
140143
* menu.off('select', handler)
141144
*/
142145
off(eventName, handler) {
@@ -150,59 +153,60 @@ let eventMixin = {
150153
},
151154

152155
/**
153-
* Generate an event with the given name and data
156+
* Gera o evento e anexa os dados a ele
154157
* this.trigger('select', data1, data2);
155158
*/
156159
trigger(eventName, ...args) {
157160
if (!this._eventHandlers?.[eventName]) {
158-
return; // no handlers for that event name
161+
return; // sem manipuladores (handlers) para esse nome de evento
159162
}
160163

161-
// call the handlers
164+
// chama o manipulador de eventos (handler)
162165
this._eventHandlers[eventName].forEach(handler => handler.apply(this, args));
163166
}
164167
};
165168
```
166169
170+
- `.on(eventName, handler)` -- atribui a função `handler` para executar quando o evento com aquele nome ocorre. Tecnicamente, existe uma propriedade `_eventHandlers` que armazena um array de manipuladores de evento para cada nome de evento, e apenas o adiciona a lista.
171+
172+
- `.off(eventName, handler)` -- remove a função da lista de manipuladores de evento.
167173
168-
- `.on(eventName, handler)` -- assigns function `handler` to run when the event with that name occurs. Technically, there's an `_eventHandlers` property that stores an array of handlers for each event name, and it just adds it to the list.
169-
- `.off(eventName, handler)` -- removes the function from the handlers list.
170-
- `.trigger(eventName, ...args)` -- generates the event: all handlers from `_eventHandlers[eventName]` are called, with a list of arguments `...args`.
174+
- `.trigger(eventName, ...args)` -- gera o evento: todos os manipuladores de eventos de `_eventHandlers[eventName]` são chamados, com a lista de argumentos `...args`.
171175
172-
Usage:
176+
Utilização:
173177
174178
```js run
175-
// Make a class
179+
// Cria uma classe
176180
class Menu {
177181
choose(value) {
178182
this.trigger("select", value);
179183
}
180184
}
181-
// Add the mixin with event-related methods
185+
// Adiciona o mixin com os métodos relacionados aos eventos.
182186
Object.assign(Menu.prototype, eventMixin);
183187

184188
let menu = new Menu();
185189

186-
// add a handler, to be called on selection:
190+
// adiciona um manipulador de eventos, para ser chamado na seleção:
187191
*!*
188192
menu.on("select", value => alert(`Value selected: ${value}`));
189193
*/!*
190194

191-
// triggers the event => the handler above runs and shows:
195+
// dispara o evento => o manipulador de evento acima executa e mostra:
192196
// Value selected: 123
193197
menu.choose("123");
194198
```
195199
196-
Now, if we'd like any code to react to a menu selection, we can listen for it with `menu.on(...)`.
200+
Agora, se quisermos que qualquer código reaja á uma seleção de menu, podemos ouvir com `menu.on(...)`;
197201
198-
And `eventMixin` mixin makes it easy to add such behavior to as many classes as we'd like, without interfering with the inheritance chain.
202+
E o mixin `eventMixin` facilita a adição do tal comportamento para tantas classes quanto quisermos, sem interferir na cadeia de herança.
199203
200-
## Summary
204+
## Conclusão
201205
202-
*Mixin* -- is a generic object-oriented programming term: a class that contains methods for other classes.
206+
*Mixin* -- é um termo genérico de programação orientada a objetos: uma classe que contém métodos para outras classes.
203207
204-
Some other languages allow multiple inheritance. JavaScript does not support multiple inheritance, but mixins can be implemented by copying methods into prototype.
208+
Algumas outras linguagens permitem herança múltipla. JavaScript não suporta herança múltipla, porém os mixins podem ser implementados copiando métodos para prototype.
205209
206-
We can use mixins as a way to augment a class by adding multiple behaviors, like event-handling as we have seen above.
210+
Podemos usar mixins como uma maneira de incrementar uma classe adicionando múltiplos comportamentos, como manipulação de eventos como vimos acima.
207211
208-
Mixins may become a point of conflict if they accidentally overwrite existing class methods. So generally one should think well about the naming methods of a mixin, to minimize the probability of that happening.
212+
Mixins podem se tornar um ponto de conflito se eles acidentalmente sobrescreverem métodos existentes da classe. Então geralmente deve-se pensar bem sobre a nomenclatura de um mixin, para minimizar a probabilidade disso acontecer.

1-js/09-classes/07-mixins/head.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
let eventMixin = {
33

44
/**
5-
* Subscribe to event, usage:
5+
* Se inscreve ao evento, utilização:
66
* menu.on('select', function(item) { ... }
77
*/
88
on(eventName, handler) {
@@ -14,7 +14,7 @@
1414
},
1515

1616
/**
17-
* Cancel the subscription, usage:
17+
* Cancela a inscrição, utilização:
1818
* menu.off('select', handler)
1919
*/
2020
off(eventName, handler) {
@@ -28,15 +28,15 @@
2828
},
2929

3030
/**
31-
* Generate the event and attach the data to it
31+
* Gera o evento e anexa os dados a ele
3232
* this.trigger('select', data1, data2);
3333
*/
3434
trigger(eventName, ...args) {
3535
if (!this._eventHandlers || !this._eventHandlers[eventName]) {
36-
return; // no handlers for that event name
36+
return; // // sem manipuladores (handlers) para esse nome de evento
3737
}
3838

39-
// call the handlers
39+
// chama o manipulador de eventos (handler)
4040
this._eventHandlers[eventName].forEach(handler => handler.apply(this, args));
4141
}
4242
};

0 commit comments

Comments
 (0)