From 9c0c4eee2aa9e0975f130c75f8b5bd3ca2a37745 Mon Sep 17 00:00:00 2001 From: Carlos Ortiz Gutierrez Date: Thu, 14 May 2020 18:18:04 -0600 Subject: [PATCH] 1-08-01-ph traducido 1-08-01-ph Traducido 12 1-08-01-ph Corregido 9 --- .../1-property-after-delete/solution.md | 6 +- .../1-property-after-delete/task.md | 8 +- .../2-search-algorithm/solution.md | 6 +- .../2-search-algorithm/task.md | 10 +- .../3-proto-and-this/solution.md | 9 +- .../3-proto-and-this/task.md | 6 +- .../4-hamster-proto/solution.md | 44 ++-- .../4-hamster-proto/task.md | 16 +- .../01-prototype-inheritance/article.md | 213 ++++++++++++------ .../object-prototype-empty.svg | 23 +- .../proto-animal-rabbit-chain.svg | 41 +--- .../proto-animal-rabbit-walk-2.svg | 30 +-- .../proto-animal-rabbit-walk-3.svg | 31 +-- .../proto-animal-rabbit-walk.svg | 30 +-- .../proto-animal-rabbit.svg | 29 +-- .../proto-user-admin.svg | 33 +-- .../rabbit-animal-object.svg | 1 + 1-js/08-prototypes/index.md | 2 +- 18 files changed, 203 insertions(+), 335 deletions(-) create mode 100644 1-js/08-prototypes/01-prototype-inheritance/rabbit-animal-object.svg 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 002b24b8a..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. -We have an object: +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 c7d147b9c..3cf1d7120 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,6 +1,7 @@ -**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`. 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 b37499bad..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 it writes? +# ¿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 fad4b8860..dd412c5e3 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! -Every time the `stomach` is taken from the prototype, then `stomach.push` modifies it "at place". +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 evade 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,12 @@ 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, are usually 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. 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 6f9fb279e..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 two hamsters are 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 to 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 7c106b1f7..928030fff 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) -That `[[Prototype]]` has a "magical" meaning. 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 `__proto__`, like this: +Una de ellas es usar el nombre especial `__proto__`, así: ```js run let animal = { @@ -31,19 +31,19 @@ rabbit.__proto__ = animal; */!* ``` -```smart header="`__proto__` is a historical getter/setter for `[[Prototype]]`" -Please note that `__proto__` is *not the same* as `[[Prototype]]`. That'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 run +```js let animal = { eats: true }; @@ -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,24 +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"); } }; @@ -124,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 actually 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 (like primitives) 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 */ } }; @@ -160,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) -That's for data properties only, not for accessors. If a property is a getter/setter, then it behaves like a function: getters/setters are looked up in the prototype. +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 = { @@ -196,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 the properties `this.name` and `this.surname` are 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 inherit from it. Then inherited objects can run its methods, and they will modify the state of these objects, not the big one. +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() { @@ -232,29 +231,99 @@ 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 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. + +Como resultado, los métodos se comparten, pero el estado del objeto no. + +## Bucle for..in + +El bucle `for..in` también itera sobre las propiedades heredadas. + +Por ejemplo: + +```js run +let animal = { + eats: true +}; + +let rabbit = { + jumps: true, + __proto__: animal +}; + +*!* +// Object.keys solo devuelve claves propias +alert(Object.keys(rabbit)); // jumps +*/!* + +*!* +// for..in recorre las claves propias y heredadas +for(let prop in rabbit) alert(prop); // jumps, despues eats +*/!* +``` + +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`. + +Entonces podemos filtrar las propiedades heredadas (o hacer algo más con ellas): + +```js run +let animal = { + eats: true +}; + +let rabbit = { + jumps: true, + __proto__: animal +}; -As a result, methods are shared, but the object state is not. +for(let prop in rabbit) { + let isOwn = rabbit.hasOwnProperty(prop); + + if (isOwn) { + alert(`Es nuestro: ${prop}`); // Es nuestro: jumps + } else { + alert(`Es heredado: ${prop}`); // Es heredado: eats + } +} +``` + +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) + +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. + +...Pero, ¿por qué `hasOwnProperty` no aparece en el bucle `for..in` como `eats` y `jumps`, si `for..in` enumera las propiedades heredadas? + +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="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. + +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 work directly on the object, they don't use the prototype (unless the property is actually 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. +- 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. diff --git a/1-js/08-prototypes/01-prototype-inheritance/object-prototype-empty.svg b/1-js/08-prototypes/01-prototype-inheritance/object-prototype-empty.svg index e1efc1cea..da48a7ccd 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/object-prototype-empty.svg +++ b/1-js/08-prototypes/01-prototype-inheritance/object-prototype-empty.svg @@ -1,22 +1 @@ - - - - object-prototype-empty.svg - Created with sketchtool. - - - - - prototype object - - - - object - - - - [[Prototype]] - - - - \ No newline at end of file +prototype objectobject[[Prototype]] \ No newline at end of file diff --git a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-chain.svg b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-chain.svg index 5eda2d9e2..520bf87ed 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-chain.svg +++ b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-chain.svg @@ -1,40 +1 @@ - - - - proto-animal-rabbit-chain.svg - Created with sketchtool. - - - - - eats: true - walk: function - - - animal - - - - jumps: true - - - rabbit - - - - [[Prototype]] - - - - earLength: 10 - - - longEar - - - - [[Prototype]] - - - - \ No newline at end of file +eats: true walk: functionanimaljumps: truerabbit[[Prototype]]earLength: 10longEar[[Prototype]] \ No newline at end of file diff --git a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-2.svg b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-2.svg index a0a495cb3..8b6573574 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-2.svg +++ b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-2.svg @@ -1,29 +1 @@ - - - - proto-animal-rabbit-walk-2.svg - Created with sketchtool. - - - - - eats: true - walk: function - - - animal - - - - walk: function - - - rabbit - - - - [[Prototype]] - - - - \ No newline at end of file +eats: true walk: functionanimalwalk: functionrabbit[[Prototype]] \ No newline at end of file diff --git a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-3.svg b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-3.svg index 541b92d83..6e3b6f555 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-3.svg +++ b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-3.svg @@ -1,30 +1 @@ - - - - proto-animal-rabbit-walk-3.svg - Created with sketchtool. - - - - - walk: function - sleep: function - - - animal - - - rabbit - - - - [[Prototype]] - - - - name: "White Rabbit" - isSleeping: true - - - - \ No newline at end of file +walk: function sleep: functionanimalrabbit[[Prototype]]name: "White Rabbit" isSleeping: true \ No newline at end of file diff --git a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk.svg b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk.svg index db1208eac..b83933a87 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk.svg +++ b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk.svg @@ -1,29 +1 @@ - - - - proto-animal-rabbit-walk.svg - Created with sketchtool. - - - - - eats: true - walk: function - - - animal - - - - jumps: true - - - rabbit - - - - [[Prototype]] - - - - \ No newline at end of file +eats: true walk: functionanimaljumps: truerabbit[[Prototype]] \ No newline at end of file diff --git a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit.svg b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit.svg index 2672739e5..538f5afb3 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit.svg +++ b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit.svg @@ -1,28 +1 @@ - - - - proto-animal-rabbit.svg - Created with sketchtool. - - - - - eats: true - - - animal - - - - jumps: true - - - rabbit - - - - [[Prototype]] - - - - \ No newline at end of file +eats: trueanimaljumps: truerabbit[[Prototype]] \ No newline at end of file diff --git a/1-js/08-prototypes/01-prototype-inheritance/proto-user-admin.svg b/1-js/08-prototypes/01-prototype-inheritance/proto-user-admin.svg index 37b318f2b..ed9fea4a0 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/proto-user-admin.svg +++ b/1-js/08-prototypes/01-prototype-inheritance/proto-user-admin.svg @@ -1,32 +1 @@ - - - - proto-user-admin.svg - Created with sketchtool. - - - - - name: "John" - surname: "Smith" - set fullName: function - - - - isAdmin: true - name: "Alice" - surname: "Cooper" - - - user - - - admin - - - - [[Prototype]] - - - - \ No newline at end of file +name: "John" surname: "Smith" set fullName: functionisAdmin: true name: "Alice" surname: "Cooper"useradmin[[Prototype]] \ No newline at end of file diff --git a/1-js/08-prototypes/01-prototype-inheritance/rabbit-animal-object.svg b/1-js/08-prototypes/01-prototype-inheritance/rabbit-animal-object.svg new file mode 100644 index 000000000..782a858bd --- /dev/null +++ b/1-js/08-prototypes/01-prototype-inheritance/rabbit-animal-object.svg @@ -0,0 +1 @@ +toString: function hasOwnProperty: function ...Object.prototypeanimal[[Prototype]][[Prototype]][[Prototype]]nulleats: truerabbitjumps: true \ No newline at end of file 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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy