Skip to content

F.prototype #67

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 1 commit into from
Aug 22, 2019
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:
Réponses:

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

The assignment to `Rabbit.prototype` sets up `[[Prototype]]` for new objects, but it does not affect the existing ones.
     L'affectation à `Rabbit.prototype` configure `[[Prototype]]` pour les nouveaux objets, mais n'affecte pas les objets existants.

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

Objects are assigned by reference. The object from `Rabbit.prototype` is not duplicated, it's still a single object is referenced both by `Rabbit.prototype` and by the `[[Prototype]]` of `rabbit`.
     Les objets sont assignés par référence. L'objet de `Rabbit.prototype` n'est pas dupliqué, mais un objet unique est référencé à la fois par `Rabbit.prototype` et par le `[[Prototype]]` de `rabbit`.

So when we change its content through one reference, it is visible through the other one.
     Ainsi, lorsque nous modifions son contenu par l’une des références, il est visible par l’autre.

3. `true`.

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.
     Toutes les opérations `delete` sont appliquées directement à l'objet. `Delete rabbit.eats` tente ici de supprimer la propriété `eats` de `rabbit`, mais ne l’a pas. Donc l'opération n'aura aucun effet.

4. `undefined`.

The property `eats` is deleted from the prototype, it doesn't exist any more.
     La propriété `eats` est supprimée du prototype, elle n’existe plus.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Changing "prototype"
# Changement de "prototype"

In the code below we create `new Rabbit`, and then try to modify its prototype.
Dans le code ci-dessous, nous créons `new Rabbit`, puis essayons de modifier son prototype.

In the start, we have this code:
Au début, nous avons ce code:

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


1. We added one more string (emphasized), what `alert` shows now?
1. Nous avons ajouté une chaîne supplémentaire (accentué), que montre `alert` maintenant?

```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. ...Et si le code est comme ça (une ligne remplacé)?

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

3. Like this (replaced one line)?
3. Comme ceci (une ligne remplacé)?

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

4. The last variant:
4. La dernière variante:

```js
function Rabbit() {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
We can use such approach if we are sure that `"constructor"` property has the correct value.
Nous pouvons utiliser cette approche si nous sommes sûrs que la propriété `"constructeur"` a la valeur correcte.

For instance, if we don't touch the default `"prototype"`, then this code works for sure:
Par exemple, si nous ne touchons pas le `"prototype"` par défaut, alors ce code fonctionne à coup sûr:

```js run
function User(name) {
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 (ça marche!)
```

It worked, because `User.prototype.constructor == User`.
Cela a fonctionné, car `User.prototype.constructor == User`.

..But if someone, so to say, overwrites `User.prototype` and forgets to recreate `"constructor"`, then it would fail.
..Mais si quelqu'un, pour ainsi dire, écrase `User.prototype` et oublie de recréer `"constructor"`, alors cela échouera.

For instance:
Par exemple:

```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`?
Pourquoi `user2.name` est `undefined`?

Here's how `new user.constructor('Pete')` works:
Voici comment `new user.constructor('Pete')` fonctionne:

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. Tout d'abord, il cherche `constructor` dans `user`. Rien.
2. Ensuite, il suit la chaîne de prototype. Le prototype de `user` est `User.prototype` et il n'a également rien.
3. La valeur de `User.prototype` est un objet simple `{}`, son prototype est `Object.prototype`. Et il y a `Object.prototype.constructor == Object`. Alors c'est utilisé.

At the end, we have `let user2 = new Object('Pete')`. The built-in `Object` constructor ignores arguments, it always creates an empty object -- that's what we have in `user2` after all.
À la fin, nous avons `let user2 = new Object('Pete')`. Le constructeur `Object` intégré ignore les arguments, il crée toujours un objet vide - c'est ce que nous avons dans `user2` après tout.
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
# Créer un objet avec le même constructeur

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.
Imaginez nous avons un objet arbitraire `obj`, créé par une fonction constructeur - nous ne savons pas lequel, mais nous aimerions créer un nouvel objet à l'aide de celui-ci.

Can we do it like that?
Pouvons-nous le faire comme ça?

```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.
Donne un exemple de fonction constructeur pour `obj` qui laisse ce code fonctionner correctement. Et un exemple qui fait que ça marche mal.
94 changes: 47 additions & 47 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()`.
Rappelez-vous que de nouveaux objets peuvent être créés avec une fonction constructeur, comme `new F()`.

If `F.prototype` is an object, then `new` operator uses it to set `[[Prototype]]` for the new object.
Si `F.prototype` est un objet, l'opérateur `new` l'utilise pour définir `[[Prototype]]` pour le nouvel objet.

```smart
JavaScript had prototypal inheritance from the beginning. It was one of the core features of the language.
```smart header="Veuillez noter"
JavaScript avait l'héritage prototypique depuis le début. C'était l'une des caractéristiques principales de la langue.

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.
Mais dans le passé, il n'y avait pas d'accès direct. La seule chose qui fonctionnait de manière fiable est une propriété `"prototype"` de la fonction constructeur décrite dans ce chapitre. Donc, il y a beaucoup de scripts qui l'utilisent encore.
```

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.
Veuillez noter que `F.prototype` signifie ici une propriété régulière nommée `"prototype"` sur `F`. Cela ressemble quelque peu au terme "prototype", mais nous entendons ici une propriété régulière portant ce nom.

Here's the example:
Voici l'exemple:

```js run
let animal = {
Expand All @@ -32,65 +32,65 @@ let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal
alert( rabbit.eats ); // true
```

Setting `Rabbit.prototype = animal` literally states the following: "When a `new Rabbit` is created, assign its `[[Prototype]]` to `animal`".
Définir `Rabbit.prototype=animal` énonce littéralement ce qui suit: "Lorsqu'un `new Rabbit` est créé, assigner son `[[Prototype]]` à `animal`".

That's the resulting picture:
C'est l'image résultante:

![](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`.
Sur l'image, `"prototype"` est une flèche horizontale, ce qui signifie une propriété normale, et `[[Prototype]]` est vertical, ce qui signifie l'héritage de `rabbit` de `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. After that, there's no connection between `F.prototype` and the new object. Think of it as a "one-time gift".
```smart header="`F.prototype` utilisé uniquement pendant `new F`"
La propriété `F.prototype` est utilisée uniquement lorsque `new F` est appelé, elle attribue `[[Prototype]]` du nouvel objet. Après cela, il n'y a plus de connexion entre `F.prototype` et le nouvel objet. Pensez-y comme à un "don unique".

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, après la création, la propriété `F.prototype` change (`F.prototype = <un autre objet>`), les nouveaux objets créés par `new F` auront un autre objet comme `[[Prototype]]`, mais les objets déjà existants conservent l'ancien.
```

## Default F.prototype, constructor property
## F.prototype par défaut, propriété du constructeur

Every function has the `"prototype"` property even if we don't supply it.
Chaque fonction a la propriété `"prototype "` même si nous ne la fournissons pas.

The default `"prototype"` is an object with the only property `constructor` that points back to the function itself.
Le `"prototype"` par défaut est un objet avec comme seule propriété `constructor` qui renvoie à la fonction elle-même.

Like this:
Comme ça:

```js
function Rabbit() {}

/* default prototype
/* prototype par défaut
Rabbit.prototype = { constructor: Rabbit };
*/
```

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

We can check it:
Nous pouvons le vérifier:

```js run
function Rabbit() {}
// by default:
// par défaut:
// Rabbit.prototype = { constructor: Rabbit }

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

Naturally, if we do nothing, the `constructor` property is available to all rabbits through `[[Prototype]]`:
Naturellement, si nous ne faisons rien, la propriété `constructor` est disponible pour tous les "rabbits" via `[[Prototype]]`:

```js run
function Rabbit() {}
// by default:
// par défaut:
// Rabbit.prototype = { constructor: Rabbit }

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

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

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

We can use `constructor` property to create a new object using the same constructor as the existing one.
Nous pouvons utiliser la propriété `constructor` pour créer un nouvel objet en utilisant le même constructeur que l'existant.

Like here:
Comme ici:

```js run
function Rabbit(name) {
Expand All @@ -105,17 +105,17 @@ let rabbit2 = new rabbit.constructor("Black Rabbit");
*/!*
```

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.
C'est pratique lorsque nous avons un objet, ne sachant pas quel constructeur a été utilisé pour cela (par exemple, il provient d'une bibliothèque externe), et nous devons en créer un autre du même type.

But probably the most important thing about `"constructor"` is that...
Mais probablement la chose la plus importante à propos de `"constructor"` est que...

**...JavaScript itself does not ensure the right `"constructor"` value.**
**...JavaScript lui-même n'assure pas la bonne valeur de `"constructor"`.**

Yes, it exists in the default `"prototype"` for functions, but that's all. What happens with it later -- is totally on us.
Oui, il existe dans le `"prototype"` par défaut pour les fonctions, mais c'est tout. Ce qui se passe avec apres le fait - dépend totalement de nous.

In particular, if we replace the default prototype as a whole, then there will be no `"constructor"` in it.
En particulier, si nous remplaçons le prototype par défaut dans son ensemble, il ne contiendra pas de "constructor".

For instance:
Par exemple:

```js run
function Rabbit() {}
Expand All @@ -129,18 +129,18 @@ alert(rabbit.constructor === Rabbit); // false
*/!*
```

So, to keep the right `"constructor"` we can choose to add/remove properties to the default `"prototype"` instead of overwriting it as a whole:
Donc, pour garder le bon `"constructor"`, nous pouvons choisir d'ajouter/supprimer des propriétés au `"prototype"` par défaut au lieu de l'écraser dans son ensemble:

```js
function Rabbit() {}

// Not overwrite Rabbit.prototype totally
// just add to it
// Ne pas écraser Rabbit.prototype totalement
// juste y ajouter
Rabbit.prototype.jumps = true
// the default Rabbit.prototype.constructor is preserved
// le Rabbit.prototype.constructor par défaut est conservé
```

Or, alternatively, recreate the `constructor` property manually:
Ou bien, recréez manuellement la propriété `constructor`:

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

// now constructor is also correct, because we added it
// maintenant le constructeur est également correct, car nous l'avons ajouté
```


## Summary
## Résumé

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.
Dans ce chapitre, nous avons brièvement décrit la manière de définir un `[[Prototype]]` pour les objets créés via une fonction constructeur. Plus tard, nous verrons des modèles de programmation plus avancés qui en dépendent.

Everything is quite simple, just few notes to make things clear:
Tout est assez simple, juste quelques précisions:

- The `F.prototype` property (don't mess with `[[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 propriété `F.prototype` (ne plaisante pas avec `[[Prototype]]`) définit `[[Prototype]]` de nouveaux objets lorsque `new F()` est appelée.
- La valeur de `F.prototype` devrait être un objet ou `null`: les autres valeurs ne fonctionneront pas.
- La propriété `"prototype"` n'a cet effet spécial que lorsqu'elle est définie sur une fonction constructeur et invoquée avec `new`.

On regular objects the `prototype` is nothing special:
Sur les objets ordinaires, le `prototype` n'a rien de spécial:
```js
let user = {
name: "John",
prototype: "Bla-bla" // no magic at all
prototype: "Bla-bla" // pas de magie
};
```

By default all functions have `F.prototype = { constructor: F }`, so we can get the constructor of an object by accessing its `"constructor"` property.
Par défaut, toutes les fonctions ont `F.prototype={constructor:F}`, nous pouvons donc obtenir le constructeur d'un objet en accédant à sa propriété `"constructor"`.