diff --git a/1-js/08-prototypes/04-prototype-methods/2-dictionary-tostring/solution.md b/1-js/08-prototypes/04-prototype-methods/2-dictionary-tostring/solution.md index a92e17900..d2738b9e9 100644 --- a/1-js/08-prototypes/04-prototype-methods/2-dictionary-tostring/solution.md +++ b/1-js/08-prototypes/04-prototype-methods/2-dictionary-tostring/solution.md @@ -1,31 +1,31 @@ -The method can take all enumerable keys using `Object.keys` and output their list. +El método puede tomar todas las claves enumerables usando `Object.keys` y generar su lista. -To make `toString` non-enumerable, let's define it using a property descriptor. The syntax of `Object.create` allows us to provide an object with property descriptors as the second argument. +Para hacer que `toString` no sea enumerable, definámoslo usando un descriptor de propiedad. La sintaxis de `Object.create` nos permite proporcionar un objeto con descriptores de propiedad como segundo argumento. ```js run *!* let dictionary = Object.create(null, { - toString: { // define toString property - value() { // the value is a function + toString: { // define la propiedad toString + value() { // el valor es una funcion return Object.keys(this).join(); } } }); */!* -dictionary.apple = "Apple"; -dictionary.__proto__ = "test"; +dictionary.apple = "Manzana"; +dictionary.__proto__ = "prueba"; -// apple and __proto__ is in the loop +// manzana y __proto__ están en el ciclo for(let key in dictionary) { - alert(key); // "apple", then "__proto__" + alert(key); // "manzana", despues "__proto__" } -// comma-separated list of properties by toString -alert(dictionary); // "apple,__proto__" +// lista de propiedades separadas por comas por toString +alert(dictionary); // "manzana,__proto__" ``` -When we create a property using a descriptor, its flags are `false` by default. So in the code above, `dictionary.toString` is non-enumerable. +Cuando creamos una propiedad usando un descriptor, sus banderas son `false` por defecto. Entonces, en el código anterior, `dictionary.toString` no es enumerable. -See the the chapter [](info:property-descriptors) for review. +Consulte el capítulo [](info:property-descriptors) para su revisión. diff --git a/1-js/08-prototypes/04-prototype-methods/2-dictionary-tostring/task.md b/1-js/08-prototypes/04-prototype-methods/2-dictionary-tostring/task.md index 0d831f2cc..cdd70ce82 100644 --- a/1-js/08-prototypes/04-prototype-methods/2-dictionary-tostring/task.md +++ b/1-js/08-prototypes/04-prototype-methods/2-dictionary-tostring/task.md @@ -2,30 +2,30 @@ importance: 5 --- -# Add toString to the dictionary +# Añadir toString al diccionario -There's an object `dictionary`, created as `Object.create(null)`, to store any `key/value` pairs. +Hay un objeto `dictionary`, creado como `Object.create(null)`, para almacenar cualquier par `clave/valor`. -Add method `dictionary.toString()` into it, that should return a comma-delimited list of keys. Your `toString` should not show up in `for..in` over the object. +Agrega el método `dictionary.toString()`, que debería devolver una lista de claves delimitadas por comas. Tu `toString` no debe aparecer al iterar un `for..in` sobre el objeto. -Here's how it should work: +Así es como debería funcionar: ```js let dictionary = Object.create(null); *!* -// your code to add dictionary.toString method +// tu código para agregar el método dictionary.toString */!* -// add some data -dictionary.apple = "Apple"; -dictionary.__proto__ = "test"; // __proto__ is a regular property key here +// agregar algunos datos +dictionary.apple = "Manzana"; +dictionary.__proto__ = "prueba"; // // aquí proto es una propiedad clave común -// only apple and __proto__ are in the loop +// solo manzana y __proto__ están en el ciclo for(let key in dictionary) { - alert(key); // "apple", then "__proto__" + alert(key); // "manzana", despues "__proto__" } -// your toString in action -alert(dictionary); // "apple,__proto__" +// tu toString en accion +alert(dictionary); // "manzana,__proto__" ``` diff --git a/1-js/08-prototypes/04-prototype-methods/3-compare-calls/solution.md b/1-js/08-prototypes/04-prototype-methods/3-compare-calls/solution.md index 90d3118bf..83658fbd6 100644 --- a/1-js/08-prototypes/04-prototype-methods/3-compare-calls/solution.md +++ b/1-js/08-prototypes/04-prototype-methods/3-compare-calls/solution.md @@ -1,7 +1,7 @@ -The first call has `this == rabbit`, the other ones have `this` equal to `Rabbit.prototype`, because it's actually the object before the dot. +La primera llamada tiene `this == rabbit`, las otras tienen `this` igual a `Rabbit.prototype`, porque en realidad es el objeto antes del punto. -So only the first call shows `Rabbit`, other ones show `undefined`: +Entonces, solo la primera llamada muestra `Rabbit`, las otras muestran `undefined`: ```js run function Rabbit(name) { @@ -11,9 +11,9 @@ Rabbit.prototype.sayHi = function() { alert( this.name ); } -let rabbit = new Rabbit("Rabbit"); +let rabbit = new Rabbit("Conejo"); -rabbit.sayHi(); // Rabbit +rabbit.sayHi(); // Conejo Rabbit.prototype.sayHi(); // undefined Object.getPrototypeOf(rabbit).sayHi(); // undefined rabbit.__proto__.sayHi(); // undefined diff --git a/1-js/08-prototypes/04-prototype-methods/3-compare-calls/task.md b/1-js/08-prototypes/04-prototype-methods/3-compare-calls/task.md index 09bb7f1ed..4fd666fb9 100644 --- a/1-js/08-prototypes/04-prototype-methods/3-compare-calls/task.md +++ b/1-js/08-prototypes/04-prototype-methods/3-compare-calls/task.md @@ -2,9 +2,9 @@ importance: 5 --- -# The difference between calls +# La diferencia entre llamadas -Let's create a new `rabbit` object: +Creemos un nuevo objeto `rabbit`: ```js function Rabbit(name) { @@ -14,10 +14,10 @@ Rabbit.prototype.sayHi = function() { alert(this.name); }; -let rabbit = new Rabbit("Rabbit"); +let rabbit = new Rabbit("Conejo"); ``` -These calls do the same thing or not? +Estas llamadas hacen lo mismo o no? ```js rabbit.sayHi(); diff --git a/1-js/08-prototypes/04-prototype-methods/article.md b/1-js/08-prototypes/04-prototype-methods/article.md index f86f2604e..ba110375b 100644 --- a/1-js/08-prototypes/04-prototype-methods/article.md +++ b/1-js/08-prototypes/04-prototype-methods/article.md @@ -1,26 +1,28 @@ -# Prototype methods, objects without __proto__ +# Métodos prototipo, objetos sin __proto__ -In the first chapter of this section, we mentioned that there are modern methods to setup a prototype. +En el primer capítulo de esta sección, mencionamos que existen métodos modernos para configurar un prototipo. -The `__proto__` is considered outdated and somewhat deprecated (in browser-only part of the JavaScript standard). -The modern methods are: +`__proto__` se considera desactualizado y algo obsoleto (en la parte propia del navegador dentro del estándar JavaScript). -- [Object.create(proto[, descriptors])](mdn:js/Object/create) -- creates an empty object with given `proto` as `[[Prototype]]` and optional property descriptors. -- [Object.getPrototypeOf(obj)](mdn:js/Object/getPrototypeOf) -- returns the `[[Prototype]]` of `obj`. -- [Object.setPrototypeOf(obj, proto)](mdn:js/Object/setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto`. -These should be used instead of `__proto__`. +Los métodos modernos son: -For instance: +- [Object.create(proto[, descriptors])] (mdn:js/Object/create): crea un objeto vacío con el "proto" dado como `[[Prototype]]` y descriptores de propiedad opcionales. +- [Object.getPrototypeOf(obj)](mdn:js/Object/getPrototypeOf) - devuelve el `[[Prototype]]` de `obj`. +- [Object.setPrototypeOf(obj, proto)](mdn:js/Object/setPrototypeOf) - establece el `[[Prototype]]` de `obj` en `proto`. + +Estos deben usarse en lugar de `__proto__`. + +Por ejemplo: ```js run let animal = { eats: true }; -// create a new object with animal as a prototype +// crear un nuevo objeto con animal como prototipo *!* let rabbit = Object.create(animal); */!* @@ -32,11 +34,11 @@ alert(Object.getPrototypeOf(rabbit) === animal); // true */!* *!* -Object.setPrototypeOf(rabbit, {}); // change the prototype of rabbit to {} +Object.setPrototypeOf(rabbit, {}); // cambia el prototipo de rabbit a {} */!* ``` -`Object.create` has an optional second argument: property descriptors. We can provide additional properties to the new object there, like this: +`Object.create` tiene un segundo argumento opcional: descriptores de propiedad. Podemos proporcionar propiedades adicionales al nuevo objeto allí, así: ```js run let animal = { @@ -52,116 +54,130 @@ let rabbit = Object.create(animal, { alert(rabbit.jumps); // true ``` -The descriptors are in the same format as described in the chapter . +Los descriptores están en el mismo formato que se describe en el capítulo . -We can use `Object.create` to perform an object cloning more powerful than copying properties in `for..in`: +Podemos usar `Object.create` para realizar una clonación de objetos más poderosa que copiar propiedades en el ciclo `for..in`: ```js -// fully identical shallow clone of obj +// // clon superficial de obj totalmente idéntico let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj)); ``` -This call makes a truly exact copy of `obj`, including all properties: enumerable and non-enumerable, data properties and setters/getters -- everything, and with the right `[[Prototype]]`. +Esta llamada hace una copia verdaderamente exacta de `obj`, que incluye todas las propiedades: enumerables y no enumerables, propiedades de datos y setters/getters, todo, y con el `[[Prototype]]` correcto. + +## Breve historia + +Si contamos todas las formas de administrar `[[Prototype]]`, ¡hay muchas! ¡Muchas maneras de hacer lo mismo! + +¿Por qué? -## Brief history -If we count all the ways to manage `[[Prototype]]`, there are a lot! Many ways to do the same thing! +Eso es por razones históricas. -Why? -That's for historical reasons. +- La propiedad "prototipo" de una función de constructor ha funcionado desde tiempos muy antiguos. +- Más tarde, en el año 2012, apareció `Object.create` en el estándar. Le dio la capacidad de crear objetos con un prototipo dado, pero no proporcionó la capacidad de obtenerlo/configurarlo. Entonces, los navegadores implementaron el acceso no estándar `__proto__` que permitió al usuario obtener/configurar un prototipo en cualquier momento. +- Más tarde, en el año 2015, `Object.setPrototypeOf` y `Object.getPrototypeOf` se agregaron al estándar, para realizar la misma funcionalidad que `__proto__`. Como `__proto__` se implementó de facto en todas partes, fue desaprobado y llegó al Anexo B de la norma, es decir: opcional para entornos que no son del navegador. -- The `"prototype"` property of a constructor function has worked since very ancient times. -- Later, in the year 2012, `Object.create` appeared in the standard. It gave the ability to create objects with a given prototype, but did not provide the ability to get/set it. So browsers implemented the non-standard `__proto__` accessor that allowed the user to get/set a prototype at any time. -- Later, in the year 2015, `Object.setPrototypeOf` and `Object.getPrototypeOf` were added to the standard, to perform the same functionality as `__proto__`. As `__proto__` was de-facto implemented everywhere, it was kind-of deprecated and made its way to the Annex B of the standard, that is: optional for non-browser environments. -As of now we have all these ways at our disposal. +A partir de ahora tenemos todas estas formas a nuestra disposición. -Why was `__proto__` replaced by the functions `getPrototypeOf/setPrototypeOf`? That's an interesting question, requiring us to understand why `__proto__` is bad. Read on to get the answer. -```warn header="Don't change `[[Prototype]]` on existing objects if speed matters" -Technically, we can get/set `[[Prototype]]` at any time. But usually we only set it once at the object creation time and don't modify it anymore: `rabbit` inherits from `animal`, and that is not going to change. +¿Por qué se reemplazó `__proto__` por las funciones `getPrototypeOf/setPrototypeOf`? Esa es una pregunta interesante, que requiere que comprendamos por qué `__proto__` es malo. Sigue leyendo para obtener la respuesta. -And JavaScript engines are highly optimized for this. Changing a prototype "on-the-fly" with `Object.setPrototypeOf` or `obj.__proto__=` is a very slow operation as it breaks internal optimizations for object property access operations. So avoid it unless you know what you're doing, or JavaScript speed totally doesn't matter for you. +```warn header="No cambie `[[Prototype]]` en objetos existentes si la velocidad es importante" +Técnicamente, podemos obtener/configurar `[[Prototype]]` en cualquier momento. Pero generalmente solo lo configuramos una vez en el momento de creación del objeto y ya no lo modificamos: `rabbit` hereda de `animal`, y eso no va a cambiar. + +Y los motores de JavaScript están altamente optimizados para esto. Cambiar un prototipo "sobre la marcha" con `Object.setPrototypeOf` u `obj.__ proto __=` es una operación muy lenta ya que rompe las optimizaciones internas para las operaciones de acceso a la propiedad del objeto. Por lo tanto, evítelo a menos que sepa lo que está haciendo, o no le importe la velocidad de JavaScript . ``` -## "Very plain" objects [#very-plain] +## Objetos "muy simples" [#very-plain] + -As we know, objects can be used as associative arrays to store key/value pairs. +Como sabemos, los objetos se pueden usar como arreglos asociativas para almacenar pares clave/valor. -...But if we try to store *user-provided* keys in it (for instance, a user-entered dictionary), we can see an interesting glitch: all keys work fine except `"__proto__"`. +...Pero si tratamos de almacenar claves *proporcionadas por el usuario* en él (por ejemplo, un diccionario ingresado por el usuario), podemos ver una falla interesante: todas las claves funcionan bien excepto `"__proto __ "`. -Check out the example: +Mira el ejemplo: ```js run let obj = {}; -let key = prompt("What's the key?", "__proto__"); -obj[key] = "some value"; +let key = prompt("Cual es la clave?", "__proto__"); +obj[key] = "algún valor"; -alert(obj[key]); // [object Object], not "some value"! +alert(obj[key]); // [object Object], no es "algún valor"! ``` -Here, if the user types in `__proto__`, the assignment is ignored! -That shouldn't surprise us. The `__proto__` property is special: it must be either an object or `null`. A string can not become a prototype. +Aquí, si el usuario escribe en `__proto__`, ¡la asignación se ignora! + +Eso no debería sorprendernos. La propiedad `__proto__` es especial: debe ser un objeto o `null`. Una cadena no puede convertirse en un prototipo. + + +Pero no *intentamos* implementar tal comportamiento, ¿verdad? Queremos almacenar pares clave/valor, y la clave llamada `"__proto__"` no se guardó correctamente. ¡Entonces eso es un error! -But we didn't *intend* to implement such behavior, right? We want to store key/value pairs, and the key named `"__proto__"` was not properly saved. So that's a bug! -Here the consequences are not terrible. But in other cases we may be assigning object values, and then the prototype may indeed be changed. As a result, the execution will go wrong in totally unexpected ways. +Aquí las consecuencias no son terribles. Pero en otros casos podemos estar asignando valores de objeto, y luego el prototipo puede ser cambiado. Como resultado, la ejecución irá mal de maneras totalmente inesperadas. -What's worse -- usually developers do not think about such possibility at all. That makes such bugs hard to notice and even turn them into vulnerabilities, especially when JavaScript is used on server-side. +Lo que es peor: generalmente los desarrolladores no piensan en tal posibilidad en absoluto. Eso hace que tales errores sean difíciles de notar e incluso los convierta en vulnerabilidades, especialmente cuando se usa JavaScript en el lado del servidor. -Unexpected things also may happen when assigning to `toString`, which is a function by default, and to other built-in methods. +También pueden ocurrir cosas inesperadas al asignar a `toString`, que es una función por defecto, y a otros métodos integrados. -How can we avoid this problem? +¿Cómo podemos evitar este problema? -First, we can just switch to using `Map` for storage instead of plain objects, then everything's fine. +Primero, podemos elegir usar `Map` para almacenamiento en lugar de objetos simples, luego todo queda bien. -But `Object` can also serve us well here, because language creators gave thought to that problem long ago. +Pero 'Objeto' también puede servirnos bien aquí, porque los creadores del lenguaje pensaron en ese problema hace mucho tiempo. + +`__proto__` no es una propiedad de un objeto, sino una propiedad de acceso de `Object.prototype`: -`__proto__` is not a property of an object, but an accessor property of `Object.prototype`: ![](object-prototype-2.svg) -So, if `obj.__proto__` is read or set, the corresponding getter/setter is called from its prototype, and it gets/sets `[[Prototype]]`. +Entonces, si se lee o establece `obj.__ proto__`, el getter/setter correspondiente se llama desde su prototipo y obtiene/establece `[[Prototype]]`. + +Como se dijo al comienzo de esta sección del tutorial: `__proto__` es una forma de acceder a `[[Prototype]]`, no es `[[Prototype]]` en sí. -As it was said in the beginning of this tutorial section: `__proto__` is a way to access `[[Prototype]]`, it is not `[[Prototype]]` itself. -Now, if we intend to use an object as an associative array and be free of such problems, we can do it with a little trick: +Ahora, si pretendemos usar un objeto como una arreglo asociativa y no tener tales problemas, podemos hacerlo con un pequeño truco: ```js run *!* let obj = Object.create(null); */!* -let key = prompt("What's the key?", "__proto__"); -obj[key] = "some value"; +let key = prompt("Cual es la clave", "__proto__"); +obj[key] = "algún valor"; -alert(obj[key]); // "some value" +alert(obj[key]); // "algún valor" ``` -`Object.create(null)` creates an empty object without a prototype (`[[Prototype]]` is `null`): +`Object.create(null)` crea un objeto vacío sin un prototipo (`[[Prototype]]` es `null`): ![](object-prototype-null.svg) -So, there is no inherited getter/setter for `__proto__`. Now it is processed as a regular data property, so the example above works right. +Entonces, no hay getter/setter heredado para `__proto__`. Ahora se procesa como una propiedad de datos normal, por lo que el ejemplo anterior funciona correctamente. + -We can call such objects "very plain" or "pure dictionary" objects, because they are even simpler than the regular plain object `{...}`. +Podemos llamar a estos objetos: objetos "muy simples" o "de diccionario puro", porque son aún más simples que el objeto simple normal `{...}`. -A downside is that such objects lack any built-in object methods, e.g. `toString`: + +Una desventaja es que dichos objetos carecen de métodos de objetos integrados, p.ej. `toString`: ```js run *!* let obj = Object.create(null); */!* -alert(obj); // Error (no toString) +alert(obj); // Error (no hay toString) ``` -...But that's usually fine for associative arrays. +...Pero eso generalmente está bien para arreglos asociativas. + + +Tenga en cuenta que la mayoría de los métodos relacionados con objetos son `Object.algo(...)`, como `Object.keys(obj)` y no están en el prototipo, por lo que seguirán trabajando en dichos objetos: -Note that most object-related methods are `Object.something(...)`, like `Object.keys(obj)` -- they are not in the prototype, so they will keep working on such objects: ```js run @@ -169,37 +185,41 @@ let chineseDictionary = Object.create(null); chineseDictionary.hello = "你好"; chineseDictionary.bye = "再见"; -alert(Object.keys(chineseDictionary)); // hello,bye +alert(Object.keys(chineseDictionary)); // hola,adios ``` -## Summary +## Resumen + + +Los métodos modernos para configurar y acceder directamente al prototipo son: -Modern methods to set up and directly access the prototype are: +- [Object.create(proto[, descriptores])](mdn:js/Object/create) - crea un objeto vacío con un `proto` dado como `[[Prototype]]` (puede ser `nulo`) y descriptores de propiedad opcionales. +- [Object.getPrototypeOf(obj)](mdn:js/Object.getPrototypeOf) - devuelve el `[[Prototype]]` de `obj` (igual que el getter de `__proto__`). +- [Object.setPrototypeOf(obj, proto)](mdn:js/Object.setPrototypeOf) - establece el `[[Prototype]]` de `obj` en `proto` (igual que el setter de `__proto__`). -- [Object.create(proto[, descriptors])](mdn:js/Object/create) -- creates an empty object with a given `proto` as `[[Prototype]]` (can be `null`) and optional property descriptors. -- [Object.getPrototypeOf(obj)](mdn:js/Object.getPrototypeOf) -- returns the `[[Prototype]]` of `obj` (same as `__proto__` getter). -- [Object.setPrototypeOf(obj, proto)](mdn:js/Object.setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto` (same as `__proto__` setter). +El getter/setter incorporado de `__proto__` no es seguro si queremos poner claves generadas por el usuario en un objeto. Aunque un usuario puede ingresar `"__proto __"` como clave, y habrá un error, con consecuencias levemente dañinas, pero generalmente impredecibles. -The built-in `__proto__` getter/setter is unsafe if we'd want to put user-generated keys into an object. Just because a user may enter `"__proto__"` as the key, and there'll be an error, with hopefully light, but generally unpredictable consequences. -So we can either use `Object.create(null)` to create a "very plain" object without `__proto__`, or stick to `Map` objects for that. +Entonces podemos usar `Object.create(null)` para crear un objeto "muy simple" sin `__proto__`, o apegarnos a los objetos `Map` para eso. -Also, `Object.create` provides an easy way to shallow-copy an object with all descriptors: +Además, `Object.create` proporciona una manera fácil de copiar llanamente un objeto con todos los descriptores: ```js let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj)); ``` -We also made it clear that `__proto__` is a getter/setter for `[[Prototype]]` and resides in `Object.prototype`, just like other methods. -We can create an object without a prototype by `Object.create(null)`. Such objects are used as "pure dictionaries", they have no issues with `"__proto__"` as the key. +También dejamos en claro que `__proto__` es un getter/setter para `[[Prototype]]` y reside en `Object.prototype`, al igual que otros métodos. + +Podemos crear un objeto sin prototipo mediante `Object.create(null)`. Dichos objetos se utilizan como "diccionarios puros", no tienen problemas con `"__proto __"` como clave. + +Otros métodos: -Other methods: +- [Object.keys(obj)](mdn:js/Object/keys) / [Object.values(obj)](mdn:js/Object/values) / [Object.entries(obj)](mdn:js/Object/entries): devuelve una arreglo de pares clave-valor: nombres/valores, de propiedades de cadena propios enumerables. +- [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols): devuelve un arreglo de todas las claves simbólicas propias. +- [Object.getOwnPropertyNames(obj)](mdn:js/Object/getOwnPropertyNames): devuelve un arreglo de todas las claves de cadena propias. +- [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys): devuelve un arreglo de todas las claves propias. +- [obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty): devuelve `true` si `obj` tiene su propia clave (no heredada) llamada `key`. -- [Object.keys(obj)](mdn:js/Object/keys) / [Object.values(obj)](mdn:js/Object/values) / [Object.entries(obj)](mdn:js/Object/entries) -- returns an array of enumerable own string property names/values/key-value pairs. -- [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) -- returns an array of all own symbolic keys. -- [Object.getOwnPropertyNames(obj)](mdn:js/Object/getOwnPropertyNames) -- returns an array of all own string keys. -- [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) -- returns an array of all own keys. -- [obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty): returns `true` if `obj` has its own (not inherited) key named `key`. +Todos los métodos que devuelven propiedades de objeto (como `Object.keys` y otros) - devuelven propiedades "propias". Si queremos heredados, podemos usar `for..in`. -All methods that return object properties (like `Object.keys` and others) -- return "own" properties. If we want inherited ones, we can use `for..in`. diff --git a/1-js/08-prototypes/index.md b/1-js/08-prototypes/index.md index 8554a0e30..443804008 100644 --- a/1-js/08-prototypes/index.md +++ b/1-js/08-prototypes/index.md @@ -1 +1 @@ -# Prototypes, inheritance +# Prototipos, herencia