diff --git a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md index 6d25a462a..6ff2b10d9 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md @@ -1,4 +1,4 @@ -1. `true`, taken from `rabbit`. -2. `null`, taken from `animal`. -3. `undefined`, there's no such property any more. +1. `true`, tomado de `rabbit`. +2. `null`, tomado de `animal`. +3. `undefined`, ya no existe tal propiedad. diff --git a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md index f38fb6f97..03511ed62 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Working with prototype +# Trabajando con prototipo -Here's the code that creates a pair of objects, then modifies them. +Aquí está el código que crea un par de objetos, luego los modifica. -Which values are shown in the process? +¿Qué valores se muestran en el proceso? ```js let animal = { @@ -28,4 +28,4 @@ delete animal.jumps; alert( rabbit.jumps ); // ? (3) ``` -There should be 3 answers. +Debería haber 3 respuestas. diff --git a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md index a16796f9c..6131ba61b 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md @@ -1,5 +1,5 @@ -1. Let's add `__proto__`: +1. Agreguemos `__proto__`: ```js run let head = { @@ -27,6 +27,6 @@ alert( table.money ); // undefined ``` -2. In modern engines, performance-wise, there's no difference whether we take a property from an object or its prototype. They remember where the property was found and reuse it in the next request. +2. En los motores modernos, en términos de rendimiento, no hay diferencia si tomamos una propiedad de un objeto o su prototipo. Recuerdan dónde se encontró la propiedad y la reutilizan en la siguiente solicitud. - For instance, for `pockets.glasses` they remember where they found `glasses` (in `head`), and next time will search right there. They are also smart enough to update internal caches if something changes, so that optimization is safe. + Por ejemplo, para `pockets.glasses` recuerdan dónde encontraron `glasses` (en `head`), y la próxima vez buscarán allí. También son lo suficientemente inteligentes como para actualizar cachés internos si algo cambia, de modo que la optimización sea segura. diff --git a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md index bc2db47fe..4c657b075 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Searching algorithm +# Algoritmo de búsqueda -The task has two parts. +La tarea tiene dos partes. -Given the following objects: +Dados los siguientes objetos: ```js let head = { @@ -27,5 +27,5 @@ let pockets = { }; ``` -1. Use `__proto__` to assign prototypes in a way that any property lookup will follow the path: `pockets` -> `bed` -> `table` -> `head`. For instance, `pockets.pen` should be `3` (found in `table`), and `bed.glasses` should be `1` (found in `head`). -2. Answer the question: is it faster to get `glasses` as `pockets.glasses` or `head.glasses`? Benchmark if needed. +1. Use `__proto__` para asignar prototipos de manera que cualquier búsqueda de propiedades siga la ruta: `pockets` -> `bed` -> `table` -> `head`. Por ejemplo, `pockets.pen` debería ser` 3` (que se encuentra en `table`), y `bed.glasses` debería ser `1` (que se encuentra en `head`). +2. Responda la pregunta: ¿es más rápido obtener `glasses` como `pockets.glasses` o `head.glasses`? Referencie si es necesario. diff --git a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md index 4d6ea2653..2dcdf3091 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md @@ -1,7 +1,8 @@ -**The answer: `rabbit`.** +**La respuesta es: `rabbit`.** -That's because `this` is an object before the dot, so `rabbit.eat()` modifies `rabbit`. +Esto se debe a que `this` es un objeto antes del punto, por lo que `rabbit.eat()` modifica `rabbit`. -Property lookup and execution are two different things. -The method `rabbit.eat` is first found in the prototype, then executed with `this=rabbit`. +La búsqueda y ejecución de propiedades son dos cosas diferentes. + +El método `rabbit.eat` se encuentra primero en el prototipo, luego se ejecuta con `this = rabbit`. \ No newline at end of file diff --git a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md index ed8482c07..6441c60f5 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Where does it write? +# ¿Donde escribe? -We have `rabbit` inheriting from `animal`. +Tenemos `rabbit` heredando de `animal`. -If we call `rabbit.eat()`, which object receives the `full` property: `animal` or `rabbit`? +Si llamamos a `rabbit.eat()`, ¿qué objeto recibe la propiedad `full`: `animal` o `rabbit`? ```js let animal = { diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md index c141b2ecd..923c273ee 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md @@ -1,18 +1,18 @@ -Let's look carefully at what's going on in the call `speedy.eat("apple")`. +Echemos un vistazo a lo que sucede en la llamada `speedy.eat("manzana")`. -1. The method `speedy.eat` is found in the prototype (`=hamster`), then executed with `this=speedy` (the object before the dot). +1. El método `speedy.eat` se encuentra en el prototipo (`=hamster`), luego se ejecuta con `this=speedy` (el objeto antes del punto). -2. Then `this.stomach.push()` needs to find `stomach` property and call `push` on it. It looks for `stomach` in `this` (`=speedy`), but nothing found. +2. Entonces `this.stomach.push()` necesita encontrar la propiedad `stomach` y llamar a `push` sobre ella. Busca `stomach` en `this` (`=speedy`), pero no se encuentra nada. -3. Then it follows the prototype chain and finds `stomach` in `hamster`. +3. Luego sigue la cadena del prototipo y encuentra `stomach` en `hamster`. -4. Then it calls `push` on it, adding the food into *the stomach of the prototype*. +4. Luego se llama 'push' en él, agregando la comida en *el stomach del prototipo*. -So all hamsters share a single stomach! +¡Así que todos los hámsters comparten un solo estómago! -Both for `lazy.stomach.push(...)` and `speedy.stomach.push()`, the property `stomach` is found in the prototype (as it's not in the object itself), then the new data is pushed into it. +Tanto para `lazy.stomach.push(...)` como para `speedy.stomach.push ()`, la propiedad `stomach` se encuentra en el prototipo (ya que no está en el objeto mismo), entonces los nuevos datos son empujado hacia dentro. -Please note that such thing doesn't happen in case of a simple assignment `this.stomach=`: +Tenga en cuenta que tal cosa no sucede en caso de una asignación simple `this.stomach=`: ```js run let hamster = { @@ -20,7 +20,7 @@ let hamster = { eat(food) { *!* - // assign to this.stomach instead of this.stomach.push + // asigna a this.stomach en lugar de this.stomach.push this.stomach = [food]; */!* } @@ -34,17 +34,17 @@ let lazy = { __proto__: hamster }; -// Speedy one found the food -speedy.eat("apple"); -alert( speedy.stomach ); // apple +// Speedy encontró la comida +speedy.eat("manzana"); +alert( speedy.stomach ); // manzana -// Lazy one's stomach is empty -alert( lazy.stomach ); // +// El estomago de Lazy está vacio +alert( lazy.stomach ); // ``` -Now all works fine, because `this.stomach=` does not perform a lookup of `stomach`. The value is written directly into `this` object. +Ahora todo funciona bien, porque `this.stomach =` no realiza una búsqueda de `stomach`. El valor se escribe directamente en el objeto `this`. -Also we can totally avoid the problem by making sure that each hamster has their own stomach: +También podemos evitar totalmente el problema asegurándonos de que cada hámster tenga su propio estómago: ```js run let hamster = { @@ -69,12 +69,11 @@ let lazy = { */!* }; -// Speedy one found the food -speedy.eat("apple"); -alert( speedy.stomach ); // apple +// Speedy encontró la comida +speedy.eat("manzana"); +alert( speedy.stomach ); // manzana -// Lazy one's stomach is empty -alert( lazy.stomach ); // +// El estómago de Lazy está vacio +alert( lazy.stomach ); // ``` - -As a common solution, all properties that describe the state of a particular object, like `stomach` above, should be written into that object. That prevents such problems. +Como solución común, todas las propiedades que describen el estado de un objeto en particular, como el "stomach" anterior, deben escribirse en ese objeto. Eso evita tales problemas. \ No newline at end of file diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md index 50171123d..541636c2c 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Why are both hamsters full? +# ¿Por qué están llenos los dos hámsters? -We have two hamsters: `speedy` and `lazy` inheriting from the general `hamster` object. +Tenemos dos hámsters: `speedy` y `lazy` heredando del objeto `hamster` general. -When we feed one of them, the other one is also full. Why? How can we fix it? +Cuando alimentamos a uno de ellos, el otro también está lleno. ¿Por qué? ¿Cómo podemos arreglarlo? ```js run let hamster = { @@ -25,11 +25,11 @@ let lazy = { __proto__: hamster }; -// This one found the food -speedy.eat("apple"); -alert( speedy.stomach ); // apple +// Este encontró la comida +speedy.eat("manzana"); +alert( speedy.stomach ); // manzana -// This one also has it, why? fix please. -alert( lazy.stomach ); // apple +// Este también lo tiene, ¿por qué? arreglar por favor. +alert( lazy.stomach ); // manzana ``` diff --git a/1-js/08-prototypes/01-prototype-inheritance/article.md b/1-js/08-prototypes/01-prototype-inheritance/article.md index 710390f15..8da13cd92 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/article.md +++ b/1-js/08-prototypes/01-prototype-inheritance/article.md @@ -1,22 +1,22 @@ -# Prototypal inheritance +# Herencia prototípica -In programming, we often want to take something and extend it. +En programación, a menudo queremos tomar algo y extenderlo. -For instance, we have a `user` object with its properties and methods, and want to make `admin` and `guest` as slightly modified variants of it. We'd like to reuse what we have in `user`, not copy/reimplement its methods, just build a new object on top of it. +Por ejemplo, tenemos un objeto `user` con sus propiedades y métodos, y queremos hacer que `admin` y `guest` sean variantes ligeramente modificadas del mismo. Nos gustaría reutilizar lo que tenemos en `user`, no copiar/reimplementar sus métodos, solo construir un nuevo objeto encima de él. -*Prototypal inheritance* is a language feature that helps in that. +*La herencia de prototipos* es una característica del lenguaje que ayuda en eso. ## [[Prototype]] -In JavaScript, objects have a special hidden property `[[Prototype]]` (as named in the specification), that is either `null` or references another object. That object is called "a prototype": +En JavaScript, los objetos tienen una propiedad oculta especial `[[Prototype]]` (como se menciona en la especificación), que es `nulo` o hace referencia a otro objeto. Ese objeto se llama "un prototipo": ![prototype](object-prototype-empty.svg) -The prototype is a little bit "magical". When we want to read a property from `object`, and it's missing, JavaScript automatically takes it from the prototype. In programming, such thing is called "prototypal inheritance". Many cool language features and programming techniques are based on it. +El prototipo es un poco "mágico". Cuando queremos leer una propiedad de `object`, y falta, JavaScript la toma automáticamente del prototipo. En programación, tal cosa se llama "herencia prototípica". Muchas características geniales del lenguaje y técnicas de programación se basan en él. -The property `[[Prototype]]` is internal and hidden, but there are many ways to set it. +La propiedad `[[Prototype]]` es interna y está oculta, pero hay muchas formas de configurarla. -One of them is to use the special name `__proto__`, like this: +Una de ellas es usar el nombre especial `__proto__`, así: ```js run let animal = { @@ -31,17 +31,17 @@ rabbit.__proto__ = animal; */!* ``` -```smart header="`__proto__` is a historical getter/setter for `[[Prototype]]`" -Please note that `__proto__` is *not the same* as `[[Prototype]]`. It's a getter/setter for it. +```smart header="`__proto__` es un getter/setter histórico para `[[Prototype]]`" +Tenga en cuenta que `__proto__` *no es lo mismo* que `[[Prototype]] `. Es un getter/setter para este. -It exists for historical reasons. In modern language it is replaced with functions `Object.getPrototypeOf/Object.setPrototypeOf` that also get/set the prototype. We'll study the reasons for that and these functions later. +Existe por razones históricas. En lenguaje moderno, se reemplaza con las funciones `Object.getPrototypeOf/Object.setPrototypeOf` que también obtienen/establecen el prototipo. Estudiaremos las razones de eso y estas funciones más adelante. -By the specification, `__proto__` must only be supported by browsers, but in fact all environments including server-side support it. For now, as `__proto__` notation is a little bit more intuitively obvious, we'll use it in the examples. +Según la especificación, `__proto__` solo debe ser compatible con los navegadores, pero de hecho todos los entornos lo admiten, incluido el lado del servidor. Por ahora, como la notación `__proto__` es un poco más intuitiva, la usaremos en los ejemplos. ``` -If we look for a property in `rabbit`, and it's missing, JavaScript automatically takes it from `animal`. +Si buscamos una propiedad en `rabbit`, y falta, JavaScript automáticamente la toma de `animal`. -For instance: +Por ejemplo: ```js let animal = { @@ -55,31 +55,31 @@ let rabbit = { rabbit.__proto__ = animal; // (*) */!* -// we can find both properties in rabbit now: +// // podemos encontrar ambas propiedades en conejo ahora: *!* -alert( rabbit.eats ); // true (**) +alert( rabbit.eats ); // verdadero (**) */!* -alert( rabbit.jumps ); // true +alert( rabbit.jumps ); // verdadero ``` -Here the line `(*)` sets `animal` to be a prototype of `rabbit`. +Aquí la línea `(*)` establece que `animal` es un prototipo de `rabbit`. -Then, when `alert` tries to read property `rabbit.eats` `(**)`, it's not in `rabbit`, so JavaScript follows the `[[Prototype]]` reference and finds it in `animal` (look from the bottom up): +Luego, cuando `alert` intenta leer la propiedad `rabbit.eats` `(**)`, no está en `rabbit`, por lo que JavaScript sigue la referencia `[[Prototype]]` y la encuentra en `animal` (mira de abajo hacia arriba): ![](proto-animal-rabbit.svg) -Here we can say that "`animal` is the prototype of `rabbit`" or "`rabbit` prototypically inherits from `animal`". +Aquí podemos decir que "`animal` es el prototipo de `rabbit`" o "`rabbit` hereda prototípicamente de `animal`". -So if `animal` has a lot of useful properties and methods, then they become automatically available in `rabbit`. Such properties are called "inherited". +Entonces, si `animal` tiene muchas propiedades y métodos útiles, entonces estarán automáticamente disponibles en `rabbit`. Dichas propiedades se denominan "heredadas". -If we have a method in `animal`, it can be called on `rabbit`: +Si tenemos un método en `animal`, se puede llamar en `rabbit`: ```js run let animal = { eats: true, *!* walk() { - alert("Animal walk"); + alert("Animal da un paseo"); } */!* }; @@ -89,23 +89,23 @@ let rabbit = { __proto__: animal }; -// walk is taken from the prototype +// walk es tomado del prototipo *!* -rabbit.walk(); // Animal walk +rabbit.walk(); // Animal da un paseo */!* ``` -The method is automatically taken from the prototype, like this: +El método se toma automáticamente del prototipo, así: ![](proto-animal-rabbit-walk.svg) -The prototype chain can be longer: +La cadena prototipo puede ser más larga: ```js run let animal = { eats: true, walk() { - alert("Animal walk"); + alert("Animal da un paseo"); } }; @@ -123,33 +123,33 @@ let longEar = { */!* }; -// walk is taken from the prototype chain -longEar.walk(); // Animal walk -alert(longEar.jumps); // true (from rabbit) +// walk se toma de la cadena prototipo +longEar.walk(); // Animal da un paseo +alert(longEar.jumps); // verdadero (desde rabbit) ``` ![](proto-animal-rabbit-chain.svg) -There are only two limitations: +Solo hay dos limitaciones: -1. The references can't go in circles. JavaScript will throw an error if we try to assign `__proto__` in a circle. -2. The value of `__proto__` can be either an object or `null`. Other types are ignored. +1. Las referencias no pueden ir en círculos. JavaScript arrojará un error si intentamos asignar `__proto__` en un círculo. +2. El valor de `__proto__` puede ser un objeto o `nulo`. Otros tipos son ignorados. -Also it may be obvious, but still: there can be only one `[[Prototype]]`. An object may not inherit from two others. +También puede ser obvio, pero aún así: solo puede haber un `[[Prototype]]`. Un objeto no puede heredar desde dos. -## Writing doesn't use prototype +## La escritura no usa prototipo -The prototype is only used for reading properties. +El prototipo solo se usa para leer propiedades. -Write/delete operations work directly with the object. +Las operaciones de escritura/eliminación funcionan directamente con el objeto. -In the example below, we assign its own `walk` method to `rabbit`: +En el ejemplo a continuación, asignamos su propio método `walk` a `rabbit`: ```js run let animal = { eats: true, walk() { - /* this method won't be used by rabbit */ + /* este método no será utilizado por rabbit */ } }; @@ -159,20 +159,20 @@ let rabbit = { *!* rabbit.walk = function() { - alert("Rabbit! Bounce-bounce!"); + alert("¡Conejo! Rebota-rebota!"); }; */!* -rabbit.walk(); // Rabbit! Bounce-bounce! +rabbit.walk(); // ¡Conejo! Rebota-rebota! ``` -From now on, `rabbit.walk()` call finds the method immediately in the object and executes it, without using the prototype: +De ahora en adelante, la llamada `rabbit.walk()` encuentra el método inmediatamente en el objeto y lo ejecuta, sin usar el prototipo: ![](proto-animal-rabbit-walk-2.svg) -Accessor properties are an exception, as assignment is handled by a setter function. So writing to such a property is actually the same as calling a function. +Las propiedades de acceso son una excepción, ya que la asignación es manejada por una función setter. Por lo tanto, escribir en una propiedad de este tipo es en realidad lo mismo que llamar a una función. -For that reason `admin.fullName` works correctly in the code below: +Por esa razón, `admin.fullName` funciona correctamente en el siguiente código: ```js run let user = { @@ -195,34 +195,34 @@ let admin = { alert(admin.fullName); // John Smith (*) -// setter triggers! +// disparadores setter! admin.fullName = "Alice Cooper"; // (**) ``` -Here in the line `(*)` the property `admin.fullName` has a getter in the prototype `user`, so it is called. And in the line `(**)` the property has a setter in the prototype, so it is called. +Aquí en la línea `(*)` la propiedad `admin.fullName` tiene un getter en el prototipo `user`, por lo que es llamado. Y en la línea `(**)` la propiedad tiene un setter en el prototipo, por lo que es llamado. -## The value of "this" +## El valor de "this" -An interesting question may arise in the example above: what's the value of `this` inside `set fullName(value)`? Where are the properties `this.name` and `this.surname` written: into `user` or `admin`? +Puede surgir una pregunta interesante en el ejemplo anterior: ¿cuál es el valor de `this` dentro de `set fullName(value)`? ¿Dónde están escritas las propiedades `this.name` y ` this.surname`: en `user` o `admin`? -The answer is simple: `this` is not affected by prototypes at all. +La respuesta es simple: "this" no se ve afectado por los prototipos en absoluto. -**No matter where the method is found: in an object or its prototype. In a method call, `this` is always the object before the dot.** +**No importa dónde se encuentre el método: en un objeto o su prototipo. En una llamada al método, `this` es siempre el objeto antes del punto.** -So, the setter call `admin.fullName=` uses `admin` as `this`, not `user`. +Entonces, la llamada al setter `admin.fullName=` usa `admin` como` this`, no a `user`. -That is actually a super-important thing, because we may have a big object with many methods, and have objects that inherit from it. And when the inheriting objects run the inherited methods, they will modify only their own states, not the state of the big object. +Eso es realmente algo muy importante, porque podemos tener un gran objeto con muchos métodos y tener objetos que hereden de él. Y cuando los objetos heredados ejecutan los métodos heredados, modificarán solo sus propios estados, no el estado del gran objeto. -For instance, here `animal` represents a "method storage", and `rabbit` makes use of it. +Por ejemplo, aquí `animal` representa un "método de almacenamiento", y `rabbit` lo utiliza. -The call `rabbit.sleep()` sets `this.isSleeping` on the `rabbit` object: +La llamada `rabbit.sleep()` establece `this.isSleeping` en el objeto `rabbit`: ```js run -// animal has methods +// animal tiene métodos let animal = { walk() { if (!this.isSleeping) { - alert(`I walk`); + alert(`Yo camino`); } }, sleep() { @@ -231,30 +231,30 @@ let animal = { }; let rabbit = { - name: "White Rabbit", + name: "Conejo Blanco", __proto__: animal }; -// modifies rabbit.isSleeping +// modifica rabbit.isSleeping rabbit.sleep(); -alert(rabbit.isSleeping); // true -alert(animal.isSleeping); // undefined (no such property in the prototype) +alert(rabbit.isSleeping); // Verdadero +alert(animal.isSleeping); // undefined (no existe tal propiedad en el prototipo) ``` -The resulting picture: +La imagen resultante: ![](proto-animal-rabbit-walk-3.svg) -If we had other objects, like `bird`, `snake`, etc., inheriting from `animal`, they would also gain access to methods of `animal`. But `this` in each method call would be the corresponding object, evaluated at the call-time (before dot), not `animal`. So when we write data into `this`, it is stored into these objects. +Si tuviéramos otros objetos, como `bird`, `snake`, etc., heredados de `animal`, también tendrían acceso a los métodos de `animal`. Pero `this` en cada llamada al método sería el objeto correspondiente, evaluado en el momento de la llamada (antes del punto), no `animal`. Entonces, cuando escribimos datos en `this`, se almacenan en estos objetos. -As a result, methods are shared, but the object state is not. +Como resultado, los métodos se comparten, pero el estado del objeto no. -## for..in loop +## Bucle for..in -The `for..in` loop iterates over inherited properties too. +El bucle `for..in` también itera sobre las propiedades heredadas. -For instance: +Por ejemplo: ```js run let animal = { @@ -267,19 +267,19 @@ let rabbit = { }; *!* -// Object.keys only returns own keys +// Object.keys solo devuelve claves propias alert(Object.keys(rabbit)); // jumps */!* *!* -// for..in loops over both own and inherited keys -for(let prop in rabbit) alert(prop); // jumps, then eats +// for..in recorre las claves propias y heredadas +for(let prop in rabbit) alert(prop); // jumps, despues eats */!* ``` -If that's not what we want, and we'd like to exclude inherited properties, there's a built-in method [obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty): it returns `true` if `obj` has its own (not inherited) property named `key`. +Si no queremos eso, y quisieramos excluir las propiedades heredadas, hay un método incorporado [obj.hasOwnProperty(key)] (mdn:js/Object/hasOwnProperty): devuelve `true` si `obj` tiene la propiedad interna (no heredada) llamada `key`. -So we can filter out inherited properties (or do something else with them): +Entonces podemos filtrar las propiedades heredadas (o hacer algo más con ellas): ```js run let animal = { @@ -291,39 +291,40 @@ let rabbit = { __proto__: animal }; + for(let prop in rabbit) { let isOwn = rabbit.hasOwnProperty(prop); if (isOwn) { - alert(`Our: ${prop}`); // Our: jumps + alert(`Es nuestro: ${prop}`); // Es nuestro: jumps } else { - alert(`Inherited: ${prop}`); // Inherited: eats + alert(`Es heredado: ${prop}`); // Es heredado: eats } } ``` -Here we have the following inheritance chain: `rabbit` inherits from `animal`, that inherits from `Object.prototype` (because `animal` is a literal object `{...}`, so it's by default), and then `null` above it: +Aquí tenemos la siguiente cadena de herencia: `rabbit` hereda de `animal`, que hereda de `Object.prototype` (porque `animal` es un objetc `{...}` literal, entonces es por defecto), y luego `null` encima de él: ![](rabbit-animal-object.svg) -Note, there's one funny thing. Where is the method `rabbit.hasOwnProperty` coming from? We did not define it. Looking at the chain we can see that the method is provided by `Object.prototype.hasOwnProperty`. In other words, it's inherited. +Nota, hay una cosa divertida. ¿De dónde viene el método `rabbit.hasOwnProperty`? No lo definimos. Mirando la cadena podemos ver que el método es proporcionado por `Object.prototype.hasOwnProperty`. En otras palabras, se hereda. -...But why does `hasOwnProperty` not appear in the `for..in` loop like `eats` and `jumps` do, if `for..in` lists inherited properties? +...Pero, ¿por qué `hasOwnProperty` no aparece en el bucle `for..in` como `eats` y `jumps`, si `for..in` enumera las propiedades heredadas? -The answer is simple: it's not enumerable. Just like all other properties of `Object.prototype`, it has `enumerable:false` flag. And `for..in` only lists enumerable properties. That's why it and the rest of the `Object.prototype` properties are not listed. +La respuesta es simple: no es enumerable. Al igual que todas las demás propiedades de `Object.prototype`, tiene la bandera `enumerable: false`. Y `for..in` solo enumera las propiedades enumerables. Es por eso que este y el resto de las propiedades de `Object.prototype` no están en la lista. -```smart header="Almost all other key/value-getting methods ignore inherited properties" -Almost all other key/value-getting methods, such as `Object.keys`, `Object.values` and so on ignore inherited properties. +```smart header="Casi todos los demás métodos de obtención de valor/clave ignoran las propiedades heredadas" +Casi todos los demás métodos de obtención de valores/claves, como `Object.keys`, `Object.values`, etc., ignoran las propiedades heredadas. -They only operate on the object itself. Properties from the prototype are *not* taken into account. +Solo operan en el objeto mismo. Las propiedades del prototipo *no* se tienen en cuenta. ``` -## Summary +## Resumen -- In JavaScript, all objects have a hidden `[[Prototype]]` property that's either another object or `null`. -- We can use `obj.__proto__` to access it (a historical getter/setter, there are other ways, to be covered soon). -- The object referenced by `[[Prototype]]` is called a "prototype". -- If we want to read a property of `obj` or call a method, and it doesn't exist, then JavaScript tries to find it in the prototype. -- Write/delete operations act directly on the object, they don't use the prototype (assuming it's a data property, not a setter). -- If we call `obj.method()`, and the `method` is taken from the prototype, `this` still references `obj`. So methods always work with the current object even if they are inherited. -- The `for..in` loop iterates over both its own and its inherited properties. All other key/value-getting methods only operate on the object itself. +- En JavaScript, todos los objetos tienen una propiedad oculta `[[Prototype]]` que es otro objeto o `nulo`. +- Podemos usar `obj.__proto__` para acceder a él (un getter/setter histórico, hay otras formas, que se cubrirán pronto). +- El objeto al que hace referencia `[[Prototype]]` se denomina "prototipo". +- Si queremos leer una propiedad de `obj` o llamar a un método, y no existe, entonces JavaScript intenta encontrarla en el prototipo. +- Las operaciones de escritura/eliminación actúan directamente sobre el objeto, no usan el prototipo (suponiendo que sea una propiedad de datos, no un setter). +- Si llamamos a `obj.method()`, y `method` se toma del prototipo, `this` todavía hace referencia a `obj`. Por lo tanto, los métodos siempre funcionan con el objeto actual, incluso si se heredan. +- El bucle `for..in` itera sobre las propiedades propias y heredadas. Todos los demás métodos de obtención de valor/clave solo operan en el objeto mismo. \ No newline at end of file