diff --git a/1-js/09-classes/06-instanceof/1-strange-instanceof/solution.md b/1-js/09-classes/06-instanceof/1-strange-instanceof/solution.md index d41d90edf..80884f7b3 100644 --- a/1-js/09-classes/06-instanceof/1-strange-instanceof/solution.md +++ b/1-js/09-classes/06-instanceof/1-strange-instanceof/solution.md @@ -1,7 +1,7 @@ -Yeah, looks strange indeed. +Sí, se ve extraño de hecho. -But `instanceof` does not care about the function, but rather about its `prototype`, that it matches against the prototype chain. +Pero a `instanceof` no le importa la función, sino más bien su `prototype`, que coincide con la cadena del prototipo. -And here `a.__proto__ == B.prototype`, so `instanceof` returns `true`. +Y aquí `a.__ proto__ == B.prototype`, entonces `instanceof` devuelve `true`. -So, by the logic of `instanceof`, the `prototype` actually defines the type, not the constructor function. +Entonces, según la lógica de `instanceof`, el `prototype` en realidad define el tipo, no la función constructora. diff --git a/1-js/09-classes/06-instanceof/1-strange-instanceof/task.md b/1-js/09-classes/06-instanceof/1-strange-instanceof/task.md index 5b8dc7de3..07bb311a4 100644 --- a/1-js/09-classes/06-instanceof/1-strange-instanceof/task.md +++ b/1-js/09-classes/06-instanceof/1-strange-instanceof/task.md @@ -2,9 +2,9 @@ importance: 5 --- -# Strange instanceof +# Extraño instanceof -In the code below, why does `instanceof` return `true`? We can easily see that `a` is not created by `B()`. +En el siguiente código, ¿por qué `instanceof` devuelve `true`? Podemos ver fácilmente que `a` no es creado por `B()`. ```js run function A() {} @@ -15,6 +15,6 @@ A.prototype = B.prototype = {}; let a = new A(); *!* -alert( a instanceof B ); // true +alert( a instanceof B ); // verdadero */!* ``` diff --git a/1-js/09-classes/06-instanceof/article.md b/1-js/09-classes/06-instanceof/article.md index aa973da06..44b6c4633 100644 --- a/1-js/09-classes/06-instanceof/article.md +++ b/1-js/09-classes/06-instanceof/article.md @@ -1,62 +1,63 @@ -# Class checking: "instanceof" +# Comprobación de clase: "instanceof" -The `instanceof` operator allows to check whether an object belongs to a certain class. It also takes inheritance into account. +El operador `instanceof` permite verificar si un objeto pertenece a una clase determinada. También tiene en cuenta la herencia. -Such a check may be necessary in many cases. Here we'll use it for building a *polymorphic* function, the one that treats arguments differently depending on their type. +Tal verificación puede ser necesaria en muchos casos. Aquí lo usaremos para construir una función *polimórfica*, la que trata los argumentos de manera diferente dependiendo de su tipo. -## The instanceof operator [#ref-instanceof] +## El operador instanceof [#ref-instanceof] -The syntax is: +La sintaxis es: ```js obj instanceof Class ``` -It returns `true` if `obj` belongs to the `Class` or a class inheriting from it. +Devuelve `true` si `obj` pertenece a la `Class` o una clase que hereda de ella. -For instance: +Por ejemplo: ```js run class Rabbit {} let rabbit = new Rabbit(); -// is it an object of Rabbit class? +// ¿Es un objeto de la clase Rabbit? *!* -alert( rabbit instanceof Rabbit ); // true +alert( rabbit instanceof Rabbit ); // verdadero */!* ``` -It also works with constructor functions: +También funciona con funciones de constructor: ```js run *!* -// instead of class +// en lugar de clase function Rabbit() {} */!* -alert( new Rabbit() instanceof Rabbit ); // true +alert( new Rabbit() instanceof Rabbit ); // verdadero ``` -...And with built-in classes like `Array`: +...Y con clases integradas como `Array`: ```js run let arr = [1, 2, 3]; -alert( arr instanceof Array ); // true -alert( arr instanceof Object ); // true +alert( arr instanceof Array ); // verdadero +alert( arr instanceof Object ); // verdadero ``` -Please note that `arr` also belongs to the `Object` class. That's because `Array` prototypically inherits from `Object`. +Tenga en cuenta que `arr` también pertenece a la clase `Object`. Esto se debe a que `Array` hereda prototípicamente de `Object`. -Normally, `instanceof` examines the prototype chain for the check. We can also set a custom logic in the static method `Symbol.hasInstance`. +Normalmente, `instanceof` examina la cadena de prototipos para la verificación. También podemos establecer una lógica personalizada en el método estático `Symbol.hasInstance`. -The algorithm of `obj instanceof Class` works roughly as follows: +El algoritmo de `obj instanceof Class` funciona más o menos de la siguiente manera: -1. If there's a static method `Symbol.hasInstance`, then just call it: `Class[Symbol.hasInstance](obj)`. It should return either `true` or `false`, and we're done. That's how we can customize the behavior of `instanceof`. +1. Si hay un método estático `Symbol.hasInstance`, simplemente llámelo: `Class[Symbol.hasInstance](obj)`. Debería devolver `true` o `false`, y hemos terminado. Así es como podemos personalizar el comportamiento de `instanceof`. - For example: + Por ejemplo: ```js run - // setup instanceOf check that assumes that - // anything with canEat property is an animal + // Instalar instancia de verificación que asume que + // cualquier cosa con propiedad canEat es un animal + class Animal { static [Symbol.hasInstance](obj) { if (obj.canEat) return true; @@ -64,25 +65,25 @@ The algorithm of `obj instanceof Class` works roughly as follows: } let obj = { canEat: true }; - - alert(obj instanceof Animal); // true: Animal[Symbol.hasInstance](obj) is called + alert(obj instanceof Animal); // verdadero: Animal[Symbol.hasInstance](obj) es llamada ``` -2. Most classes do not have `Symbol.hasInstance`. In that case, the standard logic is used: `obj instanceOf Class` checks whether `Class.prototype` is equal to one of the prototypes in the `obj` prototype chain. +2. La mayoría de las clases no tienen `Symbol.hasInstance`. En ese caso, se utiliza la lógica estándar: `obj instanceOf Class` comprueba si `Class.prototype` es igual a uno de los prototipos en la cadena de prototipos `obj`. - In other words, compare one after another: + En otras palabras, compara uno tras otro: + ```js obj.__proto__ === Class.prototype? obj.__proto__.__proto__ === Class.prototype? obj.__proto__.__proto__.__proto__ === Class.prototype? ... - // if any answer is true, return true - // otherwise, if we reached the end of the chain, return false + // si alguna respuesta es verdadera, devuelve true + // de lo contrario, si llegamos al final de la cadena, devuelve false ``` - In the example above `rabbit.__proto__ === Rabbit.prototype`, so that gives the answer immediately. + En el ejemplo anterior `rabbit.__ proto__ === Rabbit.prototype`, por lo que da la respuesta de inmediato. - In the case of an inheritance, the match will be at the second step: + En el caso de una herencia, la coincidencia será en el segundo paso: ```js run class Animal {} @@ -90,79 +91,79 @@ The algorithm of `obj instanceof Class` works roughly as follows: let rabbit = new Rabbit(); *!* - alert(rabbit instanceof Animal); // true + alert(rabbit instanceof Animal); // verdadero */!* // rabbit.__proto__ === Rabbit.prototype *!* - // rabbit.__proto__.__proto__ === Animal.prototype (match!) + // rabbit.__proto__.__proto__ === Animal.prototype (iguala!) */!* ``` -Here's the illustration of what `rabbit instanceof Animal` compares with `Animal.prototype`: +Aquí está la ilustración de lo que `rabbit instanceof Animal` compara con `Animal.prototype`: ![](instanceof.svg) -By the way, there's also a method [objA.isPrototypeOf(objB)](mdn:js/object/isPrototypeOf), that returns `true` if `objA` is somewhere in the chain of prototypes for `objB`. So the test of `obj instanceof Class` can be rephrased as `Class.prototype.isPrototypeOf(obj)`. +Por cierto, también hay un método [objA.isPrototypeOf(objB)] (mdn:js/object/isPrototypeOf), que devuelve `true` si `objA` está en algún lugar de la cadena de prototipos para `objB`. Por lo tanto, la prueba de `obj instanceof Class` se puede reformular como `Class.prototype.isPrototypeOf(obj)`. -It's funny, but the `Class` constructor itself does not participate in the check! Only the chain of prototypes and `Class.prototype` matters. +Es divertido, ¡pero el constructor `Class` en sí mismo no participa en el chequeo! Solo importa la cadena de prototipos y `Class.prototype`. -That can lead to interesting consequences when a `prototype` property is changed after the object is created. +Eso puede llevar a consecuencias interesantes cuando se cambia una propiedad `prototype` después de crear el objeto. -Like here: +Como aquí: ```js run function Rabbit() {} let rabbit = new Rabbit(); -// changed the prototype +// cambió el prototipo Rabbit.prototype = {}; -// ...not a rabbit any more! +// ...ya no es un conejo! *!* -alert( rabbit instanceof Rabbit ); // false +alert( rabbit instanceof Rabbit ); // falso */!* ``` -## Bonus: Object.prototype.toString for the type +## Bonificación: Object.prototype.toString para el tipo -We already know that plain objects are converted to string as `[object Object]`: +Ya sabemos que los objetos simples se convierten en cadenas como `[objetc Objetc]`: ```js run let obj = {}; alert(obj); // [object Object] -alert(obj.toString()); // the same +alert(obj.toString()); // lo mismo ``` -That's their implementation of `toString`. But there's a hidden feature that makes `toString` actually much more powerful than that. We can use it as an extended `typeof` and an alternative for `instanceof`. +Esa es su implementación de `toString`. Pero hay una característica oculta que hace que `toString` sea mucho más poderoso que eso. Podemos usarlo como un `typeof` extendido y una alternativa para `instanceof`. -Sounds strange? Indeed. Let's demystify. +¿Suena extraño? En efecto. Vamos a desmitificar. -By [specification](https://tc39.github.io/ecma262/#sec-object.prototype.tostring), the built-in `toString` can be extracted from the object and executed in the context of any other value. And its result depends on that value. +Por esta [especificación](https://tc39.github.io/ecma262/#sec-object.prototype.tostring), el `toString` incorporado puede extraerse del objeto y ejecutarse en el contexto de cualquier otro valor. Y su resultado depende de ese valor. -- For a number, it will be `[object Number]` -- For a boolean, it will be `[object Boolean]` -- For `null`: `[object Null]` -- For `undefined`: `[object Undefined]` -- For arrays: `[object Array]` -- ...etc (customizable). +- Para un número, será `[object Number]` +- Para un booleano, será `[objetc Boolean]` +- Para `null`: `[objetc Null]` +- Para `undefined`: `[objetc Undefined]` +- Para matrices: `[Object Array]` +- ... etc (personalizable). -Let's demonstrate: +Demostremos: ```js run -// copy toString method into a variable for convenience +// copie el método toString en una variable a conveniencia let objectToString = Object.prototype.toString; -// what type is this? +// ¿que tipo es este? let arr = []; alert( objectToString.call(arr) ); // [object *!*Array*/!*] ``` -Here we used [call](mdn:js/function/call) as described in the chapter [](info:call-apply-decorators) to execute the function `objectToString` in the context `this=arr`. +Aquí usamos [call](mdn:js/function/call) como se describe en el capítulo [](info:call-apply-decorators) para ejecutar la función `objectToString` en el contexto `this=arr`. -Internally, the `toString` algorithm examines `this` and returns the corresponding result. More examples: +Internamente, el algoritmo `toString` examina `this` y devuelve el resultado correspondiente. Más ejemplos: ```js run let s = Object.prototype.toString; @@ -174,9 +175,9 @@ alert( s.call(alert) ); // [object Function] ### Symbol.toStringTag -The behavior of Object `toString` can be customized using a special object property `Symbol.toStringTag`. +El comportamiento del objeto `toString` se puede personalizar utilizando una propiedad de objeto especial `Symbol.toStringTag`. -For instance: +Por ejemplo: ```js run let user = { @@ -186,33 +187,33 @@ let user = { alert( {}.toString.call(user) ); // [object User] ``` -For most environment-specific objects, there is such a property. Here are some browser specific examples: +Para la mayoría de los objetos específicos del entorno, existe dicha propiedad. Aquí hay algunos ejemplos específicos del navegador: ```js run -// toStringTag for the environment-specific object and class: -alert( window[Symbol.toStringTag]); // window +// toStringTag para el objeto y clase específicos del entorno: +alert( window[Symbol.toStringTag]); // ventana alert( XMLHttpRequest.prototype[Symbol.toStringTag] ); // XMLHttpRequest alert( {}.toString.call(window) ); // [object Window] alert( {}.toString.call(new XMLHttpRequest()) ); // [object XMLHttpRequest] ``` -As you can see, the result is exactly `Symbol.toStringTag` (if exists), wrapped into `[object ...]`. +Como puedes ver, el resultado es exactamente `Symbol.toStringTag` (si existe), envuelto en `[object ...]`. -At the end we have "typeof on steroids" that not only works for primitive data types, but also for built-in objects and even can be customized. +Al final tenemos "typeof con esteroides" que no solo funciona para tipos de datos primitivos, sino también para objetos incorporados e incluso puede personalizarse. -We can use `{}.toString.call` instead of `instanceof` for built-in objects when we want to get the type as a string rather than just to check. +Podemos usar `{}.toString.call` en lugar de `instanceof` para los objetos incorporados cuando deseamos obtener el tipo como una cadena en lugar de solo verificar. -## Summary +## Resumen -Let's summarize the type-checking methods that we know: +Resumamos los métodos de verificación de tipos que conocemos: -| | works for | returns | +| | trabaja para | retorna | |---------------|-------------|---------------| -| `typeof` | primitives | string | -| `{}.toString` | primitives, built-in objects, objects with `Symbol.toStringTag` | string | -| `instanceof` | objects | true/false | +| `typeof` | primitivos | cadena | +| `{}.toString` | primitivos, objetos incorporados, objetos con `Symbol.toStringTag` | cadena | +| `instanceof` | objetos | true/false | -As we can see, `{}.toString` is technically a "more advanced" `typeof`. +Como podemos ver, `{}.toString` es técnicamente un `typeof` "más avanzado". -And `instanceof` operator really shines when we are working with a class hierarchy and want to check for the class taking into account inheritance. +Y el operador `instanceof` realmente brilla cuando estamos trabajando con una jerarquía de clases y queremos verificar si la clase tiene en cuenta la herencia. diff --git a/1-js/09-classes/07-mixins/article.md b/1-js/09-classes/07-mixins/article.md index 60f6f7c4a..912385a89 100644 --- a/1-js/09-classes/07-mixins/article.md +++ b/1-js/09-classes/07-mixins/article.md @@ -1,22 +1,22 @@ -# Mixins +# Los Mixins -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. +En JavaScript solo podemos heredar de un solo objeto. Solo puede haber un `[[Prototype]]` para un objeto. Y una clase puede extender solo otra clase. -But sometimes that feels limiting. For instance, we have a class `StreetSweeper` and a class `Bicycle`, and want to make their mix: a `StreetSweepingBicycle`. +Pero a veces eso se siente limitante. Por ejemplo, tenemos una clase `StreetSweeper` y una clase `Bicycle`, y queremos hacer su combinación: un `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. +O tenemos una clase `User` y una clase `EventEmitter` que implementa la generación de eventos, y nos gustaría agregar la funcionalidad de `EventEmitter` a `User`, para que nuestros usuarios puedan emitir eventos. -There's a concept that can help here, called "mixins". +Hay un concepto que puede ayudar aquí, llamado "mixins". -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. +Como se define en Wikipedia, un [mixin]https://en.wikipedia.org/wiki/Mixin) es una clase que contiene métodos que pueden ser utilizados por otras clases sin necesidad de heredar de ella. -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. +En otras palabras, un *mixin* proporciona métodos que implementan cierto comportamiento, pero no lo usamos solo, lo usamos para agregar el comportamiento a otras clases. -## A mixin example +## Un ejemplo de mixin -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. +La forma más sencilla de implementar un mixin en JavaScript es hacer un objeto con métodos útiles, para que podamos combinarlos fácilmente en un prototipo de cualquier clase. -For instance here the mixin `sayHiMixin` is used to add some "speech" for `User`: +Por ejemplo, aquí el mixin `sayHiMixin` se usa para agregar algo de "diálogo" a `User`: ```js run *!* @@ -24,15 +24,15 @@ For instance here the mixin `sayHiMixin` is used to add some "speech" for `User` */!* let sayHiMixin = { sayHi() { - alert(`Hello ${this.name}`); + alert(`Hola ${this.name}`); }, sayBye() { - alert(`Bye ${this.name}`); + alert(`Adios ${this.name}`); } }; *!* -// usage: +// uso: */!* class User { constructor(name) { @@ -40,14 +40,14 @@ class User { } } -// copy the methods +// copia los métodos Object.assign(User.prototype, sayHiMixin); -// now User can say hi -new User("Dude").sayHi(); // Hello Dude! +// Ahora el User puede decir hola +new User("tío").sayHi(); // Hola tío! ``` -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: +No hay herencia, sino un simple método de copia. Entonces, `User` puede heredar de otra clase y también incluir el mixin para "mezclar" los métodos adicionales, como este: ```js class User extends Person { @@ -57,9 +57,9 @@ class User extends Person { Object.assign(User.prototype, sayHiMixin); ``` -Mixins can make use of inheritance inside themselves. +Los mixins pueden hacer uso de la herencia dentro de sí mismos. -For instance, here `sayHiMixin` inherits from `sayMixin`: +Por ejemplo, aquí `sayHiMixin` hereda de `sayMixin`: ```js run let sayMixin = { @@ -69,16 +69,16 @@ let sayMixin = { }; let sayHiMixin = { - __proto__: sayMixin, // (or we could use Object.create to set the prototype here) + __proto__: sayMixin, // (o podríamos usar Object.create para configurar el prototype aquí) sayHi() { *!* - // call parent method + // llama al método padre */!* - super.say(`Hello ${this.name}`); // (*) + super.say(`Hola ${this.name}`); // (*) }, sayBye() { - super.say(`Bye ${this.name}`); // (*) + super.say(`Adios ${this.name}`); // (*) } }; @@ -88,43 +88,43 @@ class User { } } -// copy the methods +// copia los métodos Object.assign(User.prototype, sayHiMixin); -// now User can say hi -new User("Dude").sayHi(); // Hello Dude! +// ahora User puede decir hola +new User("tío").sayHi(); // Hola tío! ``` -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. +Tenga en cuenta que la llamada al método padre `super.say()` de `sayHiMixin` (en las líneas etiquetadas con `(*)`) busca el método en el prototipo de ese mixin, no la clase. -Here's the diagram (see the right part): +Aquí está el diagrama (ver la parte derecha): ![](mixin-inheritance.svg) -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. +Esto se debe a que los métodos `sayHi` y `sayBye` se crearon inicialmente en `sayHiMixin`. Entonces, a pesar de que se copiaron, su propiedad interna `[[[HomeObject]]` hace referencia a `sayHiMixin`, como se muestra en la imagen de arriba. -As `super` looks for parent methods in `[[HomeObject]].[[Prototype]]`, that means it searches `sayHiMixin.[[Prototype]]`, not `User.[[Prototype]]`. +Como `super` busca métodos primarios en `[[HomeObject]].[[Prototype]]`, significa que busca `sayHiMixin.[[Prototype]]`, no `User.[[Prototype]]`. ## EventMixin -Now let's make a mixin for real life. +Ahora hagamos un mixin para la 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 mixin that allows us to easily add event-related functions to any class/object. +Una característica importante de muchos objetos del navegador (por ejemplo) es que pueden generar eventos. Los eventos son una excelente manera de "transmitir información" a cualquiera que lo desee. Así que hagamos un mixin que nos permita agregar fácilmente funciones relacionadas con eventos a cualquier clase/objeto. -- 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. -- 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. +- El mixin proporcionará un método `.trigger(name, [... data])` para "generar un evento" cuando le ocurra algo importante. El argumento `name` es un nombre del evento, opcionalmente seguido de argumentos adicionales con datos del evento. +- También el método `.on(name, handler)` que agrega la función `handler` como oyente a eventos con el nombre dado. Se llamará cuando se desencadene un evento con el nombre `name` dado, y obtenga los argumentos de la llamada `.trigger`. +- ...Y el método `.off(name, handler)` que elimina el oyente `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. +Después de agregar el mixin, un objeto `user` podrá generar un evento `"login"` cuando el visitante inicie sesión. Y otro objeto, por ejemplo, `calendar` puede querer escuchar dichos eventos para cargar el calendario para el persona registrada. -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. +O bien, un `menu` puede generar el evento `"seleccionar"` cuando se selecciona un elemento del menú, y otros objetos pueden asignar controladores para reaccionar ante ese evento. Y así. -Here's the code: +Aquí está el código: ```js run let eventMixin = { /** - * Subscribe to event, usage: + * Suscríbete al evento, uso: * menu.on('select', function(item) { ... } */ on(eventName, handler) { @@ -136,7 +136,7 @@ let eventMixin = { }, /** - * Cancel the subscription, usage: + * Cancelar la suscripción, uso: * menu.off('select', handler) */ off(eventName, handler) { @@ -150,12 +150,12 @@ let eventMixin = { }, /** - * Generate an event with the given name and data + * Generar un evento con el nombre y los datos * this.trigger('select', data1, data2); */ trigger(eventName, ...args) { if (!this._eventHandlers || !this._eventHandlers[eventName]) { - return; // no handlers for that event name + return; // no hay controladores para ese nombre de evento } // call the handlers @@ -165,44 +165,44 @@ let eventMixin = { ``` -- `.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. -- `.off(eventName, handler)` -- removes the function from the handlers list. -- `.trigger(eventName, ...args)` -- generates the event: all handlers from `_eventHandlers[eventName]` are called, with a list of arguments `...args`. +- `.on(eventName, handler)`: asigna la función `handler` para que se ejecute cuando se produce el evento con ese nombre. Técnicamente, hay una propiedad `_eventHandlers` que almacena una matriz de controladores para cada nombre de evento, y simplemente la agrega a la lista. +- `.off(eventName, handler)` - elimina la función de la lista de controladores. +- `.trigger(eventName, ... args)` - genera el evento: se llama a todos los controladores de `_eventHandlers [eventName]`, con una lista de argumentos `... args`. -Usage: +Uso: ```js run -// Make a class +// Hacer una clase class Menu { choose(value) { this.trigger("select", value); } } -// Add the mixin with event-related methods +// Agregue el mixin con métodos relacionados con eventos Object.assign(Menu.prototype, eventMixin); let menu = new Menu(); -// add a handler, to be called on selection: +// agregue un controlador, que se llamará en la selección: *!* -menu.on("select", value => alert(`Value selected: ${value}`)); +menu.on("select", value => alert(`Valor seleccionado: ${value}`)); */!* -// triggers the event => the handler above runs and shows: -// Value selected: 123 +// desencadena el evento => el controlador anterior se ejecuta y muestra: +// Valor seleccionado: 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(...)`. +Ahora, si queremos que algún código reaccione a una selección de menú, podemos escucharlo con `menu.on(...)`. -And `eventMixin` mixin makes it easy to add such behavior to as many classes as we'd like, without interfering with the inheritance chain. +Y el mixin de `eventMixin` hace que sea fácil agregar ese comportamiento a tantas clases como queramos, sin interferir con la cadena de herencia. -## Summary +## Resumen -*Mixin* -- is a generic object-oriented programming term: a class that contains methods for other classes. +*Mixin* -- es un término genérico de programación orientado a objetos: una clase que contiene métodos para otras clases. -Some other languages allow multiple inheritance. JavaScript does not support multiple inheritance, but mixins can be implemented by copying methods into prototype. +Algunos lenguajes permiten la herencia múltiple. JavaScript no admite la herencia múltiple, pero los mixins se pueden implementar copiando métodos en el prototipo. -We can use mixins as a way to augment a class by adding multiple behaviors, like event-handling as we have seen above. +Podemos usar mixins como una forma de aumentar una clase agregando múltiples comportamientos, como el manejo de eventos que hemos visto anteriormente. -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. +Los mixins pueden convertirse en un punto de conflicto si sobrescriben accidentalmente los métodos de clase existentes. Por lo tanto, generalmente uno debe pensar bien sobre la definición de métodos de un mixin, para minimizar la probabilidad de que eso suceda. \ No newline at end of file diff --git a/1-js/09-classes/07-mixins/head.html b/1-js/09-classes/07-mixins/head.html index 20e3a6354..5d13ba451 100644 --- a/1-js/09-classes/07-mixins/head.html +++ b/1-js/09-classes/07-mixins/head.html @@ -2,7 +2,7 @@ let eventMixin = { /** - * Subscribe to event, usage: + * Suscríbete al evento, uso: * menu.on('select', function(item) { ... } */ on(eventName, handler) { @@ -14,7 +14,7 @@ }, /** - * Cancel the subscription, usage: + * Cancelar la suscripción, uso: * menu.off('select', handler) */ off(eventName, handler) { @@ -28,15 +28,15 @@ }, /** - * Generate the event and attach the data to it + * Genere el evento y adjúntele los datos. * this.trigger('select', data1, data2); */ trigger(eventName, ...args) { if (!this._eventHandlers || !this._eventHandlers[eventName]) { - return; // no handlers for that event name + return; // no hay controladores para ese nombre de evento } - // call the handlers + // llama a los manejadores this._eventHandlers[eventName].forEach(handler => handler.apply(this, args)); } };