Skip to content

F.prototype #192

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@

Answers:
Respuestas:

1. `true`.
1. `verdadero`.

The assignment to `Rabbit.prototype` sets up `[[Prototype]]` for new objects, but it does not affect the existing ones.
La asignación a `Rabbit.prototype` configura `[[Prototype]]` para objetos nuevos, pero no afecta a los existentes.

2. `false`.
2. `falso`.

Objects are assigned by reference. The object from `Rabbit.prototype` is not duplicated, it's still a single object referenced both by `Rabbit.prototype` and by the `[[Prototype]]` of `rabbit`.
Los objetos se asignan por referencia. El objeto de `Rabbit.prototype` no está duplicado, sigue siendo un solo objeto referenciado tanto por `Rabbit.prototype` como por el `[[Prototype]]` de `rabbit`.

So when we change its content through one reference, it is visible through the other one.
Entonces, cuando cambiamos su contenido a través de una referencia, es visible a través de la otra.

3. `true`.
3. `verdadero`.

All `delete` operations are applied directly to the object. Here `delete rabbit.eats` tries to remove `eats` property from `rabbit`, but it doesn't have it. So the operation won't have any effect.
Todas las operaciones `delete` se aplican directamente al objeto. Aquí `delete rabbit.eats` intenta eliminar la propiedad `eats` de `rabbit`, pero no la tiene. Entonces la operación no tendrá ningún efecto.

4. `undefined`.

The property `eats` is deleted from the prototype, it doesn't exist any more.
La propiedad `eats` se elimina del prototipo, ya no existe.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Changing "prototype"
# Cambiando "prototype"

In the code below we create `new Rabbit`, and then try to modify its prototype.
En el siguiente código creamos `new Rabbit`, y luego intentamos modificar su prototipo.

In the start, we have this code:
Al principio, tenemos este código:

```js run
function Rabbit() {}
Expand All @@ -16,11 +16,11 @@ Rabbit.prototype = {

let rabbit = new Rabbit();

alert( rabbit.eats ); // true
alert( rabbit.eats ); // verdadero
```


1. We added one more string (emphasized). What will `alert` show now?
1. Agregamos una cadena más (enfatizada). ¿Qué mostrará `alert` ahora?

```js
function Rabbit() {}
Expand All @@ -37,7 +37,7 @@ alert( rabbit.eats ); // true
alert( rabbit.eats ); // ?
```

2. ...And if the code is like this (replaced one line)?
2. ...¿Y si el código es así (se reemplazó una línea)?

```js
function Rabbit() {}
Expand All @@ -54,7 +54,7 @@ alert( rabbit.eats ); // true
alert( rabbit.eats ); // ?
```

3. And like this (replaced one line)?
3. ¿Y así (se reemplazó una línea)?

```js
function Rabbit() {}
Expand All @@ -71,7 +71,7 @@ alert( rabbit.eats ); // true
alert( rabbit.eats ); // ?
```

4. The last variant:
4. La última variante:

```js
function Rabbit() {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
We can use such approach if we are sure that `"constructor"` property has the correct value.
Podemos usar dicho enfoque si estamos seguros de que la propiedad `"constructor"` tiene el valor correcto.

For instance, if we don't touch the default `"prototype"`, then this code works for sure:

Expand All @@ -10,14 +10,14 @@ function User(name) {
let user = new User('John');
let user2 = new user.constructor('Pete');

alert( user2.name ); // Pete (worked!)
alert( user2.name ); // Pete (funcionó!)
```

It worked, because `User.prototype.constructor == User`.
Funcionó, porque `User.prototype.constructor == User`.

..But if someone, so to speak, overwrites `User.prototype` and forgets to recreate `constructor` to reference `User`, then it would fail.
..Pero si alguien, por así decirlo, sobrescribe `User.prototype` y olvida recrear `constructor` para hacer referencia a `User`, entonces fallaría.

For instance:
Por ejemplo:

```js run
function User(name) {
Expand All @@ -33,12 +33,12 @@ let user2 = new user.constructor('Pete');
alert( user2.name ); // undefined
```

Why `user2.name` is `undefined`?
¿Por qué `user2.name` es `undefined`?

Here's how `new user.constructor('Pete')` works:
Así es como funciona `new user.constructor('Pete')`:

1. First, it looks for `constructor` in `user`. Nothing.
2. Then it follows the prototype chain. The prototype of `user` is `User.prototype`, and it also has nothing.
3. The value of `User.prototype` is a plain object `{}`, its prototype is `Object.prototype`. And there is `Object.prototype.constructor == Object`. So it is used.
1. Primero, busca a `constructor` en `user`. Nada.
2. Luego sigue la cadena de prototipo. El prototipo de `user` es `User.prototype`, y tampoco tiene nada.
3. El valor de `User.prototype` es un objeto simple `{}`, su prototipo es `Object.prototype`. Y hay `Object.prototype.constructor == Object`. Entonces se usa.

At the end, we have `let user2 = new Object('Pete')`. The built-in `Object` constructor ignores arguments, it always creates an empty object, similar to `let user2 = {}`, that's what we have in `user2` after all.
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ importance: 5

---

# Create an object with the same constructor
# Crea un objeto con el mismo constructor

Imagine, we have an arbitrary object `obj`, created by a constructor function -- we don't know which one, but we'd like to create a new object using it.
Imagínese, tenemos un objeto arbitrario `obj`, creado por una función constructora; no sabemos cuál, pero nos gustaría crear un nuevo objeto con él.

Can we do it like that?
¿Podemos hacerlo así?

```js
let obj2 = new obj.constructor();
```

Give an example of a constructor function for `obj` which lets such code work right. And an example that makes it work wrong.
Dé un ejemplo de una función constructora para `obj` que permita que dicho código funcione correctamente. Y un ejemplo que hace que funcione mal.
104 changes: 52 additions & 52 deletions 1-js/08-prototypes/02-function-prototype/article.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# F.prototype

Remember, new objects can be created with a constructor function, like `new F()`.
Recuerde, se pueden crear nuevos objetos con una función constructora, como `new F()`.

If `F.prototype` is an object, then the `new` operator uses it to set `[[Prototype]]` for the new object.
Si `F.prototype` es un objeto, entonces el operador `new` lo usa para establecer `[[Prototype]]` para el nuevo objeto.

```smart
JavaScript had prototypal inheritance from the beginning. It was one of the core features of the language.
JavaScript tenía herencia prototípica desde el principio. Era una de las características principales del lenguaje.

But in the old times, there was no direct access to it. The only thing that worked reliably was a `"prototype"` property of the constructor function, described in this chapter. So there are many scripts that still use it.
Pero en los viejos tiempos, no había acceso directo a él. Lo único que funcionó de manera confiable fue una propiedad `"prototype"` de la función constructora, descrita en este capítulo. Así que hay muchos scripts que todavía lo usan.
```

Please note that `F.prototype` here means a regular property named `"prototype"` on `F`. It sounds something similar to the term "prototype", but here we really mean a regular property with this name.
Tenga en cuenta que `F.prototype` aquí significa una propiedad regular llamada `"prototype"` en `F`. Suena algo similar al término "prototype", pero aquí realmente queremos decir una propiedad regular con este nombre.

Here's the example:
Aquí está el ejemplo:

```js run
let animal = {
Expand All @@ -27,95 +27,95 @@ function Rabbit(name) {
Rabbit.prototype = animal;
*/!*

let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal
let rabbit = new Rabbit("Conejo Blanco"); // rabbit.__proto__ == animal

alert( rabbit.eats ); // true
alert( rabbit.eats ); // verdadero
```

Setting `Rabbit.prototype = animal` literally states the following: "When a `new Rabbit` is created, assign its `[[Prototype]]` to `animal`".
La configuración de `Rabbit.prototype = animal` literalmente establece lo siguiente: "Cuando se crea un `new Rabbit`, asigne su `[[Prototype]]` a `animal`".

That's the resulting picture:
Esta es la imagen resultante:

![](proto-constructor-animal-rabbit.svg)

On the picture, `"prototype"` is a horizontal arrow, meaning a regular property, and `[[Prototype]]` is vertical, meaning the inheritance of `rabbit` from `animal`.
En la imagen, `"prototype"` es una flecha horizontal, que significa una propiedad regular, y `[[Prototype]]` es vertical, que significa la herencia de `rabbit` desde `animal`.

```smart header="`F.prototype` only used at `new F` time"
`F.prototype` property is only used when `new F` is called, it assigns `[[Prototype]]` of the new object.
```smart header="`F.prototype` solo se usa en el momento `new F`"
La propiedad `F.prototype` solo se usa cuando se llama a `new F`, asigna `[[Prototype]]` del nuevo objeto.

If, after the creation, `F.prototype` property changes (`F.prototype = <another object>`), then new objects created by `new F` will have another object as `[[Prototype]]`, but already existing objects keep the old one.
Si, después de la creación, la propiedad `F.prototype` cambia (`F.prototype = <otro objeto>`), los nuevos objetos creados por `new F` tendrán otro objeto como `[[Prototype]]`, pero ya los objetos existentes conservan el antiguo.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Si, después de la creación, la propiedad F.prototype cambia (F.prototype = <otro objeto>), los nuevos objetos creados por new F tendrán otro objeto como [[Prototype]], pero los objetos ya existentes conservan el antiguo.

```

## Default F.prototype, constructor property
## F.prototype predeterminado, propiedad del constructor

Every function has the `"prototype"` property even if we don't supply it.
Cada función tiene la propiedad `"prototype"` incluso si no la suministramos.

The default `"prototype"` is an object with the only property `constructor` that points back to the function itself.
El `"prototype"` predeterminado es un objeto con la única propiedad `constructor` que apunta de nuevo a la función misma.

Like this:
Como esto:

```js
function Rabbit() {}

/* default prototype
/* prototipo predeterminado
Rabbit.prototype = { constructor: Rabbit };
*/
```

![](function-prototype-constructor.svg)

We can check it:
Lo podemos comprobar:

```js run
function Rabbit() {}
// by default:
// por defecto:
// Rabbit.prototype = { constructor: Rabbit }

alert( Rabbit.prototype.constructor == Rabbit ); // true
alert( Rabbit.prototype.constructor == Rabbit ); // verdadero
```

Naturally, if we do nothing, the `constructor` property is available to all rabbits through `[[Prototype]]`:
Naturalmente, si no hacemos nada, la propiedad `constructor` está disponible para todos los rabbits a través de `[[Prototype]]`:

```js run
function Rabbit() {}
// by default:
// por defecto:
// Rabbit.prototype = { constructor: Rabbit }

let rabbit = new Rabbit(); // inherits from {constructor: Rabbit}
let rabbit = new Rabbit(); // hereda de {constructor: Rabbit}

alert(rabbit.constructor == Rabbit); // true (from prototype)
alert(rabbit.constructor == Rabbit); // verdadero (desde prototype)
```

![](rabbit-prototype-constructor.svg)

We can use `constructor` property to create a new object using the same constructor as the existing one.
Podemos usar la propiedad `constructor` para crear un nuevo objeto usando el constructor ya existente.

Like here:
Como aqui:

```js run
function Rabbit(name) {
this.name = name;
alert(name);
}

let rabbit = new Rabbit("White Rabbit");
let rabbit = new Rabbit("Conejo Blanco");

*!*
let rabbit2 = new rabbit.constructor("Black Rabbit");
let rabbit2 = new rabbit.constructor("Conejo Negro");
*/!*
```

That's handy when we have an object, don't know which constructor was used for it (e.g. it comes from a 3rd party library), and we need to create another one of the same kind.
Eso es útil cuando tenemos un objeto, no sabemos qué constructor se usó para él (por ejemplo, proviene de una biblioteca de terceros), y necesitamos crear otro del mismo tipo.

But probably the most important thing about `"constructor"` is that...
Pero probablemente lo más importante sobre `"constructor"` es que ...

**...JavaScript itself does not ensure the right `"constructor"` value.**
**...JavaScript en sí mismo no garantiza el valor correcto de `"constructor"`.**

Yes, it exists in the default `"prototype"` for functions, but that's all. What happens with it later -- is totally on us.
Sí, existe en el `"prototipo"` predeterminado para las funciones, pero eso es todo. Lo que sucede con eso más tarde, depende totalmente de nosotros.

In particular, if we replace the default prototype as a whole, then there will be no `"constructor"` in it.
En particular, si reemplazamos el prototipo predeterminado como un todo, entonces no habrá `"constructor"` en él.

For instance:
Por ejemplo:

```js run
function Rabbit() {}
Expand All @@ -125,22 +125,22 @@ Rabbit.prototype = {

let rabbit = new Rabbit();
*!*
alert(rabbit.constructor === Rabbit); // false
alert(rabbit.constructor === Rabbit); // falso
*/!*
```

So, to keep the right `"constructor"` we can choose to add/remove properties to the default `"prototype"` instead of overwriting it as a whole:
Entonces, para mantener el `"constructor"` correcto, podemos elegir agregar/eliminar propiedades al `"prototipo"` predeterminado en lugar de sobrescribirlo como un todo:

```js
function Rabbit() {}

// Not overwrite Rabbit.prototype totally
// just add to it
// No sobrescribir totalmente Rabbit.prototype
// solo agrégale
Rabbit.prototype.jumps = true
// the default Rabbit.prototype.constructor is preserved
// se conserva el Rabbit.prototype.constructor predeterminado
```

Or, alternatively, recreate the `constructor` property manually:
O, alternativamente, vuelva a crear la propiedad `constructor` manualmente:

```js
Rabbit.prototype = {
Expand All @@ -150,26 +150,26 @@ Rabbit.prototype = {
*/!*
};

// now constructor is also correct, because we added it
// ahora el constructor también es correcto, porque lo agregamos
```


## Summary
## Resumen

In this chapter we briefly described the way of setting a `[[Prototype]]` for objects created via a constructor function. Later we'll see more advanced programming patterns that rely on it.
En este capítulo describimos brevemente la forma de establecer un `[[Prototype]]` para los objetos creados a través de una función de constructor. Más adelante veremos patrones de programación más avanzados que dependen de él.

Everything is quite simple, just a few notes to make things clear:
Todo es bastante simple, solo algunas notas para aclarar las cosas:

- The `F.prototype` property (don't mistake it for `[[Prototype]]`) sets `[[Prototype]]` of new objects when `new F()` is called.
- The value of `F.prototype` should be either an object or `null`: other values won't work.
- The `"prototype"` property only has such a special effect when set on a constructor function, and invoked with `new`.
- La propiedad `F.prototype` (no la confunda con `[[Prototype]]`) establece `[[Prototype]]` de objetos nuevos cuando se llama a `new F()`.
- El valor de `F.prototype` debe ser un objeto o `null`: otros valores no funcionarán.
- La propiedad `"prototype"` solo tiene un efecto tan especial cuando se establece en una función de constructor, y se invoca con `new`.

On regular objects the `prototype` is nothing special:
En los objetos normales, el `prototype` no es nada especial:
```js
let user = {
name: "John",
prototype: "Bla-bla" // no magic at all
prototype: "Bla-bla" // sin magia en absoluto
};
```

By default all functions have `F.prototype = { constructor: F }`, so we can get the constructor of an object by accessing its `"constructor"` property.
Por defecto, todas las funciones tienen `F.prototype = {constructor: F}`, por lo que podemos obtener el constructor de un objeto accediendo a su propiedad `"constructor"`.