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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
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.
Em JavaScript, só se pode herdar de um único objeto. Pode apenas existir um único `[[Prototype]]`para um objeto. E uma classe pode estender apenas uma outra classe.
But sometimes that feels limiting. For instance, we have a class`StreetSweeper`and a class `Bicycle`,and want to make their mix: a`StreetSweepingBicycle`.
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`;
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.
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.
There's a concept that can help here, called "mixins".
Existe um conceito que nos pode ajudar aqui, chamado "mixins".
As defined in Wikipedia,a [mixin](https://en.wikipedia.org/wiki/Mixin)is a class containing methods that can be used by other classeswithout aneed to inherit from it.
Como definido no Wikipedia,um [mixin](https://en.wikipedia.org/wiki/Mixin)é uma classe contendo métodos que podem ser usados por outras classessem anecessidade de herdar dela.
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.
Em outras palavras, um *mixin*fornece métodos que implementam um determinado comportamento, mas não é utilizado sozinho, nós o utilizamos para adicionar o comportamento a outras classes.
##A mixin example
##Um exemplo de mixin
The simplest way to implement amixinin JavaScriptis to make an object with useful methods, so that we can easily merge them into aprototypeof any class.
A maneira mais simples de implementar ummixinem JavaScripté criando um objeto com métodos úteis, para que possamos facilmente mesclá-los em umprototypede outra classe.
For instance here the mixin `sayHiMixin`is used to add some "speech" for `User`:
Por exemplo, aqui o mixin `sayHiMixin`é usado para adicionar alguma "fala" para `User`:
```js run
*!*
// mixin
*/!*
let sayHiMixin = {
sayHi() {
alert(`Hello ${this.name}`);
alert(`Olá ${this.name}`);
},
sayBye() {
alert(`Bye ${this.name}`);
alert(`Adeus ${this.name}`);
}
};
*!*
//usage:
//Utilização:
*/!*
class User {
constructor(name) {
this.name = name;
}
}
//copy the methods
//copia os métodos
Object.assign(User.prototype, sayHiMixin);
//now Usercan say hi
new User("Dude").sayHi(); //Hello Dude!
//agora Userpode dizer oi
new User("Dude").sayHi(); //Olá Dude!
```
There's no inheritance, but a simple method copying. So `User`may inherit from another class and also include the mixinto "mix-in" the additional methods, like this:
Não existe herança, mas uma simples cópia de métodos. Portanto, `User`pode herdar de outra classe e também incluir o mixinpara "misturar" (mix-in) os métodos adicionais, assim:
```js
class User extends Person {
Expand All
@@ -57,9 +55,9 @@ class User extends Person {
Object.assign(User.prototype, sayHiMixin);
```
Mixinscan make use of inheritance inside themselves.
Mixinspodem usar herança dentro deles mesmos.
For instance, here `sayHiMixin`inherits from `sayMixin`:
Por exemplo, aqui `sayHiMixin`herda de `sayMixin`:
```js run
let sayMixin = {
Expand All
@@ -69,16 +67,16 @@ let sayMixin = {
};
let sayHiMixin = {
__proto__: sayMixin, // (or we could useObject.setPrototypeOfto set the prototypehere)
__proto__: sayMixin, // (ou poderíamos usarObject.setPrototypeOfpara definir o prototypeaqui)
sayHi() {
*!*
//call parent method
//chama o método pai
*/!*
super.say(`Hello ${this.name}`); // (*)
super.say(`Olá ${this.name}`); // (*)
},
sayBye() {
super.say(`Bye ${this.name}`); // (*)
super.say(`Adeus ${this.name}`); // (*)
}
};
Expand All
@@ -87,44 +85,43 @@ class User {
this.name = name;
}
}
// copy the methods
// copia os métodos
Object.assign(User.prototype, sayHiMixin);
//now Usercan say hi
new User("Dude").sayHi(); //Hello Dude!
//agora Userpode dizer oi
new User("Dude").sayHi(); //Olá Dude!
```
Please note that the call to the parent method`super.say()`from `sayHiMixin` (at lines labelled with `(*)`)looks for the method in theprototypeof thatmixin,not the class.
Observe que a chamada do método pai`super.say()`por `sayHiMixin` (nas linhas marcadas com `(*)`)procura pelo método noprototypedessemixin,não na classe.
Here's the diagram (see the right part):
Aqui está o diagrama (veja a parte direita):

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.
Isso porque os métodos`sayHi`e `sayBye`foram inicialmente criados em `sayHiMixin`.Portanto, mesmo que tenham sido copiados, suas propriedades internas`[[HomeObject]]`referenciam a`sayHiMixin`,como mostrado na figura acima.
As `super`looks for parent methods in `[[HomeObject]].[[Prototype]]`,that means it searches `sayHiMixin.[[Prototype]]`.
Como `super`procura por métodos pais em `[[HomeObject]].[[Prototype]]`,isso significa que procura em `sayHiMixin.[[Prototype]]`.
## EventMixin
Now let's make amixinfor real life.
Vamos criar ummixinpara a vida real.
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 mixinthat allows us to easily add event-related functions to any class/object.
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 mixinque nos permita facilmente adicionar funções relacionadas a eventos a qualquer classe/objeto.
-The mixinwill 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.
-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.
- ...And the method `.off(name, handler)`that removes the`handler` listener.
-O mixinvai fornecer um método `.trigger(name, [...data])`para "gerar um evento" quando algo importante acontecer com ele. O argumento`name`é o nome do evento, e é opcionalmente seguido de argumentos provendo dados do evento.
-E também o método`.on(name, handler)`que adiciona a função`handler`como ouvinte de eventos com o dado nome. Ela será chamada quando um evento com o dado`name`disparar, e irá obter os argumentos da chamada de`.trigger`
- ...E o método `.off(name, handler)`que remove o ouvinte`handler`.
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.
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.
Or, a `menu`can generate the event `"select"`when a menuitemis selected, and other objects may assignhandlers to react on that event. And so on.
Ou, um `menu`pode gerar o evento `"select"`quando umitemdo menu for selecionado`, e outros objetos podem atribuir manipuladores (handlers) para reagir àquele evento. E assim por diante.
Here's the code:
Aqui está o código:
```js run
let eventMixin = {
/**
*Subscribe to event, usage:
*Se inscreve ao evento, utilização:
* menu.on('select', function(item) { ... }
*/
on(eventName, handler) {
Expand All
@@ -136,7 +133,7 @@ let eventMixin = {
},
/**
*Cancel the subscription, usage:
*Cancela a inscrição, utilização:
* menu.off('select', handler)
*/
off(eventName, handler) {
Expand All
@@ -150,59 +147,59 @@ let eventMixin = {
},
/**
*Generate an event with the given name and data
*Gera um evento com o nome e dados providenciados
* this.trigger('select', data1, data2);
*/
trigger(eventName, ...args) {
if (!this._eventHandlers?.[eventName]) {
return; //nohandlers for that event name
return; //sem manipuladores (handlers) para esse nome de evento
- `.on(eventName, handler)` --assigns function`handler`to run when the event with that name occurs. Technically, there's an`_eventHandlers`property that stores anarrayof handlers for each event name, and it just adds it to the list.
- `.off(eventName, handler)` --removes the function from the handlers list.
- `.trigger(eventName, ...args)` --generates the event: all handlers from`_eventHandlers[eventName]`are called, with alist of arguments `...args`.
- `.on(eventName, handler)` --atribui a função`handler`para ser executada quando o evento com aquele nome ocorre. Tecnicamente, existe uma propriedade`_eventHandlers`que armazena umarrayde manipuladores de evento para cada nome de evento, e o método apenas adiciona o manipulador à lista.
- `.off(eventName, handler)` --remove a função da lista de manipuladores de evento.
- `.trigger(eventName, ...args)` --gera o evento: todos os manipuladores de eventos de`_eventHandlers[eventName]`são chamados, com alista de argumentos `...args`.
Usage:
Utilização:
```js run
//Make a class
//Cria uma classe
class Menu {
choose(value) {
this.trigger("select", value);
}
}
//Add the mixinwith event-related methods
//Adiciona o mixincom os métodos relacionados aos eventos.
Object.assign(Menu.prototype, eventMixin);
let menu = new Menu();
//add a handler, to be called on selection:
//adiciona um manipulador de eventos, para ser chamado na seleção:
*!*
menu.on("select", value => alert(`Value selected: ${value}`));
menu.on("select", value => alert(`Valor selecionado: ${value}`));
*/!*
//triggers the event =>the handler above runs and shows:
//Value selected: 123
//dispara o evento =>o manipulador de evento acima é executado e mostra:
//Valor selecionado: 123
menu.choose("123");
```
Now, if we'd like any code to react to a menu selection, we can listen for it with `menu.on(...)`.
Agora, se quisermos que qualquer código reaja a uma seleção do menu, podemos ouvir com `menu.on(...)`.
And`eventMixin`mixin makes it easy to add such behavior to as manyclassesas we'd like, without interfering with the inheritance chain.
E o mixin`eventMixin`facilita a adição do tal comportamento para tantasclassesquanto quisermos, sem interferir na cadeia de herança.
##Summary
##Conclusão
*Mixin* --is a generic object-oriented programming term: a class that contains methods for other classes.
*Mixin* --é um termo genérico de programação orientada a objetos: uma classe que contém métodos para outras classes.
Some other languages allow multiple inheritance. JavaScriptdoes not support multiple inheritance, butmixinscan be implemented by copying methods into prototype.
Algumas outras linguagens permitem herança múltipla. JavaScriptnão suporta herança múltipla, porém osmixinspodem ser implementados copiando métodos para prototype.
We can usemixinsas a way to augment a class by adding multiple behaviors, like event-handling as we have seen above.
Podemos usarmixinscomo uma maneira de incrementar uma classe adicionando múltiplos comportamentos, como manipulação de eventos como vimos acima.
Mixinsmay 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.
Mixinspodem se tornar num ponto de conflito se eles acidentalmente sobrescreverem métodos existentes na classe. Então geralmente deve-se pensar bem sobre a nomenclatura dos métodos de um mixin,para minimizar a probabilidade disso acontecer.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.