Skip to content

Class checking: "instanceof" #80

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
Sep 1, 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
50 changes: 25 additions & 25 deletions 1-js/09-classes/05-extend-natives/article.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@

# Extending built-in classes
# Extension des classes intégrées

Built-in classes like Array, Map and others are extendable also.
Les classes intégrées telles que Array, Map et autres sont également extensibles.

For instance, here `PowerArray` inherits from the native `Array`:
Par exemple, ici, `PowerArray` hérite du `Array` natif:

```js run
// add one more method to it (can do more)
// ajoutez-y une méthode supplémentaire
class PowerArray extends Array {
isEmpty() {
return this.length === 0;
Expand All @@ -21,20 +21,20 @@ alert(filteredArr); // 10, 50
alert(filteredArr.isEmpty()); // false
```

Please note a very interesting thing. Built-in methods like `filter`, `map` and others -- return new objects of exactly the inherited type `PowerArray`. Their internal implementation uses object `constructor` property for that.
Noter une chose très intéressante. Les méthodes intégrées telles que `filter`, `map` et autres renvoient des nouveaux objets exactement du type hérité `PowerArray`. Leur implémentation interne utilise la propriété d'objet `constructor` pour cela.

In the example above,
Dans l'exemple ci-dessus,
```js
arr.constructor === PowerArray
```

When `arr.filter()` is called, it internally creates the new array of results using exactly `arr.constructor`, not basic `Array`. That's actually very cool, because we can keep using `PowerArray` methods further on the result.
Lorsque `arr.filter()` est appelé, elle crée en interne le nouveau tableau de résultats en utilisant exactement `arr.constructor`, et non pas `Array`. C'est en fait très intéressant, car nous pouvons continuer à utiliser les méthodes `PowerArray` sur le résultat.

Even more, we can customize that behavior.
Encore plus, nous pouvons personnaliser ce comportement.

We can add a special static getter `Symbol.species` to the class. If exists, it should return the constructor that JavaScript will use internally to create new entities in `map`, `filter` and so on.
Nous pouvons ajouter un accésseur statique spécial `Symbol.species` à la classe. S'il existe, il devrait renvoyer le constructeur que JavaScript utilisera en interne pour créer de nouvelles entités dans `map`, `filter`, etc.

If we'd like built-in methods like `map` or `filter` to return regular arrays, we can return `Array` in `Symbol.species`, like here:
Si nous souhaitons que des méthodes intégrées comme `map` ou `filter` renvoient des tableaux classiques, nous pouvons retourner `Array` dans `Symbol.species`, comme ici:

```js run
class PowerArray extends Array {
Expand All @@ -43,7 +43,7 @@ class PowerArray extends Array {
}

*!*
// built-in methods will use this as the constructor
// les méthodes intégrées l'utiliseront comme constructeur
static get [Symbol.species]() {
return Array;
}
Expand All @@ -53,37 +53,37 @@ class PowerArray extends Array {
let arr = new PowerArray(1, 2, 5, 10, 50);
alert(arr.isEmpty()); // false

// filter creates new array using arr.constructor[Symbol.species] as constructor
// filter crée un nouveau tableau en utilisant arr.constructor [Symbol.species] comme constructeur
let filteredArr = arr.filter(item => item >= 10);

*!*
// filteredArr is not PowerArray, but Array
// filteredArr n'est pas PowerArray, mais Array
*/!*
alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function
```

As you can see, now `.filter` returns `Array`. So the extended functionality is not passed any further.
Comme vous pouvez le constater, maintenant, `.filter` renvoie `Array`. La fonctionnalité étendue n'est donc plus transmise.

```smart header="Other collections work similarly"
Other collections, such as `Map` and `Set`, work alike. They also use `Symbol.species`.
```smart header="D'autres collections fonctionnent de la même manière"
D'autres collections, telles que `Map` et `Set`, fonctionnent de la même manière. Ils utilisent également `Symbol.species`.
```

## No static inheritance in built-ins
## Pas d'héritage statique dans les éléments intégrés

Built-in objects have their own static methods, for instance `Object.keys`, `Array.isArray` etc.
Les objets intégrés ont leurs propres méthodes statiques, par exemple `Object.keys`,` Array.isArray` etc.

As we already know, native classes extend each other. For instance, `Array` extends `Object`.
Comme nous le savons déjà, les classes natives s'étendent les uns des autres. Par exemple, `Array` extends `Object`.

Normally, when one class extends another, both static and non-static methods are inherited. That was thoroughly explained in the chapter [](info:static-properties-methods#statics-and-inheritance).
Normalement, lorsqu'une classe en étend une autre, les méthodes statiques et non statiques sont héritées. Cela a été expliqué en détail dans le chapitre [](info:static-properties-methods#statics-and-inheritance).

But built-in classes are an exception. They don't inherit statics from each other.
Mais les classes intégrées sont une exception. Ils n'héritent pas les méthodes statiques les uns des autres.

For example, both `Array` and `Date` inherit from `Object`, so their instances have methods from `Object.prototype`. But `Array.[[Prototype]]` does not reference `Object`, so there's no `Array.keys()` and `Date.keys()` static methods.
Par exemple, `Array` et `Date` héritent de `Object`, de sorte que leurs instances ont des méthodes issues de `Object.prototype`. Mais `Array.[[Prototype]]` ne fait pas référence à `Object`, il n'y a donc pas de méthodes statiques `Array.keys()` et `Date.keys()`.

Here's the picture structure for `Date` and `Object`:
Voici la structure d'image pour `Date` et `Object`:

![](object-date-inheritance.svg)

As you can see, there's no link between `Date` and `Object`. They are independent, only `Date.prototype` inherits from `Object.prototype`.
Comme vous pouvez le constater, il n'y a pas de lien entre `Date` et `Object`. Ils sont indépendants, seul `Date.prototype` hérite de `Object.prototype`.

That's an important difference of inheritance between built-in objects compared to what we get with `extends`.
C'est une différence d'héritage importante entre les objets intégrés par rapport à ce que nous obtenons avec `extends`.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Yeah, looks strange indeed.
Ouais, ça a l'air étrange.

But `instanceof` does not care about the function, but rather about its `prototype`, that it matches against the prototype chain.
Mais `instanceof` ne se soucie pas de la fonction, mais plutôt de son `prototype`, qui correspond à la chaîne de prototypes.

And here `a.__proto__ == B.prototype`, so `instanceof` returns `true`.
Et ici `a.__ proto__ == B.prototype`, ainsi `instanceof` renvoie `true`.

So, by the logic of `instanceof`, the `prototype` actually defines the type, not the constructor function.
Ainsi, par la logique de `instanceof`, le `prototype` définit en fait le type, pas la fonction constructeur.
4 changes: 2 additions & 2 deletions 1-js/09-classes/06-instanceof/1-strange-instanceof/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ importance: 5

---

# Strange instanceof
# instanceof étrange

Why `instanceof` below returns `true`? We can easily see that `a` is not created by `B()`.
Pourquoi `instanceof` ci-dessous renvoie `true`? Nous pouvons facilement voir que `a` n'est pas créé par `B()`.

```js run
function A() {}
Expand Down
Loading