diff --git a/1-js/09-classes/05-extend-natives/article.md b/1-js/09-classes/05-extend-natives/article.md index 2dc4902b5..5e9536bbf 100644 --- a/1-js/09-classes/05-extend-natives/article.md +++ b/1-js/09-classes/05-extend-natives/article.md @@ -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; @@ -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 { @@ -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; } @@ -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`. diff --git a/1-js/09-classes/06-instanceof/1-strange-instanceof/solution.md b/1-js/09-classes/06-instanceof/1-strange-instanceof/solution.md index d41d90edf..c8991b930 100644 --- a/1-js/09-classes/06-instanceof/1-strange-instanceof/solution.md +++ b/1-js/09-classes/06-instanceof/1-strange-instanceof/solution.md @@ -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. diff --git a/1-js/09-classes/06-instanceof/1-strange-instanceof/task.md b/1-js/09-classes/06-instanceof/1-strange-instanceof/task.md index e9481912a..52c60e16b 100644 --- a/1-js/09-classes/06-instanceof/1-strange-instanceof/task.md +++ b/1-js/09-classes/06-instanceof/1-strange-instanceof/task.md @@ -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() {} diff --git a/1-js/09-classes/06-instanceof/article.md b/1-js/09-classes/06-instanceof/article.md index 0b02c99be..049beb0b6 100644 --- a/1-js/09-classes/06-instanceof/article.md +++ b/1-js/09-classes/06-instanceof/article.md @@ -1,42 +1,42 @@ -# Class checking: "instanceof" +# Vérification de classe: "instanceof" -The `instanceof` operator allows to check whether an object belongs to a certain class. It also takes inheritance into account. +L'opérateur `instanceof` permet de vérifier si un objet appartient à une certaine classe. Il prend également en compte l'héritage. -Such a check may be necessary in many cases, here we'll use it for building a *polymorphic* function, the one that treats arguments differently depending on their type. +Une telle vérification peut être nécessaire dans de nombreux cas. Nous l'utilisons ici pour construire une fonction *polymorphique*, celle qui traite les arguments différemment en fonction de leur type. -## The instanceof operator [#ref-instanceof] +## L'opérateur instanceof [#ref-instanceof] -The syntax is: +La syntaxe est la suivante: ```js obj instanceof Class ``` -It returns `true` if `obj` belongs to the `Class` or a class inheriting from it. +Cela renvoie `true` si `obj` appartient à la `Class` ou à une classe qui en hérite. -For instance: +Par exemple: ```js run class Rabbit {} let rabbit = new Rabbit(); -// is it an object of Rabbit class? +// est-ce un objet de la classe Rabbit? *!* alert( rabbit instanceof Rabbit ); // true */!* ``` -It also works with constructor functions: +Cela fonctionne aussi avec les fonctions constructeur: ```js run *!* -// instead of class +// au lieu de classe function Rabbit() {} */!* alert( new Rabbit() instanceof Rabbit ); // true ``` -...And with built-in classes like `Array`: +...Et avec des classes intégrées comme `Array`: ```js run let arr = [1, 2, 3]; @@ -44,125 +44,125 @@ alert( arr instanceof Array ); // true alert( arr instanceof Object ); // true ``` -Please note that `arr` also belongs to the `Object` class. That's because `Array` prototypally inherits from `Object`. +Veuillez noter que `arr` appartient également à la classe `Object`. C'est parce que `Array` hérite prototypiquement de `Object`. -Normally, `instanceof` operator examines the prototype chain for the check. We can also set a custom logic in the static method `Symbol.hasInstance`. +Normalement, l’opérateur `instanceof` examine la chaîne de prototypes pour le contrôle. Nous pouvons également définir une logique personnalisée dans la méthode statique `Symbol.hasInstance`. -The algorithm of `obj instanceof Class` works roughly as follows: +L'algorithme de `obj instanceof Class` fonctionne à peu près comme suit: -1. If there's a static method `Symbol.hasInstance`, then just call it: `Class[Symbol.hasInstance](obj)`. It should return either `true` or `false`, and we're done. That's how we can customize the behavior of `instanceof`. +1. S'il existe une méthode statique `Symbol.hasInstance`, appelez-la simplement: `Class[Symbol.hasInstance](obj)`. Cela devrait renvoyer `true` ou `false`, et nous avons terminé. C'est ainsi que nous pouvons personnaliser le comportement de `instanceof`. - For example: +     Par exemple: - ```js run - // setup instanceOf check that assumes that - // anything with canEat property is an animal - class Animal { - static [Symbol.hasInstance](obj) { - if (obj.canEat) return true; - } - } +```js run +// configuration du contrôle de instanceOf qui suppose que +// tout ce qui a la propriété canEat est un animal +class Animal { + static [Symbol.hasInstance](obj) { + if (obj.canEat) return true; + } +} - let obj = { canEat: true }; +let obj = { canEat: true }; - alert(obj instanceof Animal); // true: Animal[Symbol.hasInstance](obj) is called - ``` +alert(obj instanceof Animal); // true: Animal[Symbol.hasInstance](obj) est appelée +``` -2. Most classes do not have `Symbol.hasInstance`. In that case, the standard logic is used: `obj instanceOf Class` checks whether `Class.prototype` equals to one of prototypes in the `obj` prototype chain. +2. La plupart des classes n'ont pas `Symbol.hasInstance`. Dans ce cas, la logique standard est utilisée: `obj instanceOf Class` vérifie si `Class.prototype` est égal à l'un des prototypes de la chaîne de prototypes `obj`. - In other words, compare one after another: - ```js - obj.__proto__ === Class.prototype? - obj.__proto__.__proto__ === Class.prototype? - obj.__proto__.__proto__.__proto__ === Class.prototype? - ... - // if any answer is true, return true - // otherwise, if we reached the end of the chain, return false - ``` + En d'autres termes, comparez les uns après les autres: +```js +obj.__proto__ === Class.prototype? +obj.__proto__.__proto__ === Class.prototype? +obj.__proto__.__proto__.__proto__ === Class.prototype? +... +// si une réponse est vraie, renvoie true +// sinon, si nous arrivons au bout de la chaîne, renvoie false +``` - In the example above `rabbit.__proto__ === Rabbit.prototype`, so that gives the answer immediately. + Dans l'exemple ci-dessus, `rabbit.__ proto__ === Rabbit.prototype`, donne donc la réponse immédiatement. - In the case of an inheritance, the match will be at the second step: +     Dans le cas d'un héritage, le match sera à la deuxième étape: - ```js run - class Animal {} - class Rabbit extends Animal {} +```js run +class Animal {} +class Rabbit extends Animal {} - let rabbit = new Rabbit(); - *!* - alert(rabbit instanceof Animal); // true - */!* +let rabbit = new Rabbit(); +*!* +alert(rabbit instanceof Animal); // true +*/!* - // rabbit.__proto__ === Rabbit.prototype - *!* - // rabbit.__proto__.__proto__ === Animal.prototype (match!) - */!* - ``` +// rabbit.__proto__ === Rabbit.prototype +*!* +// rabbit.__proto__.__proto__ === Animal.prototype (match!) +*/!* +``` -Here's the illustration of what `rabbit instanceof Animal` compares with `Animal.prototype`: +Voici l'illustration de ce que `rabbit instanceof Animal` compare avec `Animal.prototype`: ![](instanceof.svg) -By the way, there's also a method [objA.isPrototypeOf(objB)](mdn:js/object/isPrototypeOf), that returns `true` if `objA` is somewhere in the chain of prototypes for `objB`. So the test of `obj instanceof Class` can be rephrased as `Class.prototype.isPrototypeOf(obj)`. +À propos, il y a aussi une méthode [objA.isPrototypeOf(objB)](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/isPrototypeOf), qui renvoie `true` si `objA` se trouve quelque part dans la chaîne de prototypes pour `objB`. Ainsi, le test de `obj instanceof Class` peut être reformulé comme suit: `Class.prototype.isPrototypeOf(obj) `. -That's funny, but the `Class` constructor itself does not participate in the check! Only the chain of prototypes and `Class.prototype` matters. +C'est drôle, mais le constructeur `Class` lui-même ne participe pas au contrôle! Seule la chaîne de prototypes et `Class.prototype` compte. -That can lead to interesting consequences when `prototype` property is changed after the object is created. +Cela peut avoir des conséquences intéressantes lorsque la propriété `prototype` est modifiée après la création de l'objet. -Like here: +Comme ici: ```js run function Rabbit() {} let rabbit = new Rabbit(); -// changed the prototype +// le prototype est changé Rabbit.prototype = {}; -// ...not a rabbit any more! +// ...plus un rabbit! *!* alert( rabbit instanceof Rabbit ); // false */!* ``` -## Bonus: Object.prototype.toString for the type +## Bonus: Object.prototype.toString pour le type -We already know that plain objects are converted to string as `[object Object]`: +Nous savons déjà que les objets simples sont convertis en chaîne sous la forme `[objet Objet]`: ```js run let obj = {}; alert(obj); // [object Object] -alert(obj.toString()); // the same +alert(obj.toString()); // la même chose ``` -That's their implementation of `toString`. But there's a hidden feature that makes `toString` actually much more powerful than that. We can use it as an extended `typeof` and an alternative for `instanceof`. +C'est leur implémentation de `toString`. Mais il existe une fonctionnalité cachée qui rend `toString` beaucoup plus puissant que cela. Nous pouvons l'utiliser comme un `typeof` étendu et une alternative pour `instanceof`. -Sounds strange? Indeed. Let's demystify. +Cela semble étrange? Effectivement. Démystifions. -By [specification](https://tc39.github.io/ecma262/#sec-object.prototype.tostring), the built-in `toString` can be extracted from the object and executed in the context of any other value. And its result depends on that value. +Par [spécification](https://tc39.github.io/ecma262/#sec-object.prototype.tostring), le `toString` intégré peut être extrait de l'objet et exécuté dans le contexte de toute autre valeur. Et son résultat dépend de cette valeur. -- For a number, it will be `[object Number]` -- For a boolean, it will be `[object Boolean]` -- For `null`: `[object Null]` -- For `undefined`: `[object Undefined]` -- For arrays: `[object Array]` -- ...etc (customizable). +- Pour un nombre, ce sera `[object Number]` +- Pour un booléen, ce sera `[object Boolean]` +- Pour `null`: `[objet Null]` +- Pour `undefined`: `[objet Undefined]` +- Pour les tableaux: `[objet Array]` +- ... etc (personnalisable). -Let's demonstrate: +Montrons cela: ```js run -// copy toString method into a variable for convenience +// copier la méthode toString dans une variable pour plus d'utilité let objectToString = Object.prototype.toString; -// what type is this? +// quel type est-ce? let arr = []; alert( objectToString.call(arr) ); // [object *!*Array*/!*] ``` -Here we used [call](mdn:js/function/call) as described in the chapter [](info:call-apply-decorators) to execute the function `objectToString` in the context `this=arr`. +Ici nous avons utilisé [call](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Function/call) comme décrit dans le chapitre [](info:call-apply-decorators) exécuter la fonction `objectToString` dans le contexte `this=arr`. -Internally, the `toString` algorithm examines `this` and returns the corresponding result. More examples: +En interne, l'algorithme `toString` examine `this` et renvoie le résultat correspondant. Plus d'exemples: ```js run let s = Object.prototype.toString; @@ -174,9 +174,9 @@ alert( s.call(alert) ); // [object Function] ### Symbol.toStringTag -The behavior of Object `toString` can be customized using a special object property `Symbol.toStringTag`. +Le comportement de Object `toString` peut être personnalisé à l'aide d'une propriété d'objet spéciale `Symbol.toStringTag`. -For instance: +Par exemple: ```js run let user = { @@ -186,10 +186,10 @@ let user = { alert( {}.toString.call(user) ); // [object User] ``` -For most environment-specific objects, there is such a property. Here are few browser specific examples: +Pour la plupart des objets spécifiques à l'environnement, il existe une telle propriété. Voici quelques exemples spécifiques à votre navigateur: ```js run -// toStringTag for the environment-specific object and class: +// toStringTag pour l'objet et la classe spécifiques à l'environnement: alert( window[Symbol.toStringTag]); // window alert( XMLHttpRequest.prototype[Symbol.toStringTag] ); // XMLHttpRequest @@ -197,22 +197,22 @@ alert( {}.toString.call(window) ); // [object Window] alert( {}.toString.call(new XMLHttpRequest()) ); // [object XMLHttpRequest] ``` -As you can see, the result is exactly `Symbol.toStringTag` (if exists), wrapped into `[object ...]`. +Comme vous pouvez le constater, le résultat est exactement `Symbol.toStringTag` (s'il existe), encapsulé dans `[objet ...]`. -At the end we have "typeof on steroids" that not only works for primitive data types, but also for built-in objects and even can be customized. +À la fin, nous avons "typeof sur stéroïdes" qui fonctionne non seulement pour les types de données primitifs, mais aussi pour les objets intégrés et peut même être personnalisé. -We can use `{}.toString.call` instead of `instanceof` for built-in objects when we want to get the type as a string rather than just to check. +Nous pouvons utiliser `{}.toString.call` au lieu de `instanceof` pour les objets intégrés lorsque nous voulons obtenir le type sous forme de chaîne plutôt que simplement pour vérifier. -## Summary +## Résumé -Let's summarize the type-checking methods that we know: +Résumons les méthodes de vérification de type que nous connaissons: -| | works for | returns | +| | fonctionne pour | renvoie | |---------------|-------------|---------------| | `typeof` | primitives | string | -| `{}.toString` | primitives, built-in objects, objects with `Symbol.toStringTag` | string | +| `{}.toString` | primitives, objets intégrés, objets avec `Symbol.toStringTag` | string | | `instanceof` | objects | true/false | -As we can see, `{}.toString` is technically a "more advanced" `typeof`. +Comme on peut le constater, `{}.toString` est techniquement un `typeof` "plus avancé". -And `instanceof` operator really shines when we are working with a class hierarchy and want to check for the class taking into account inheritance. +Et l'opérateur `instanceof` excelle lorsque nous travaillons avec une hiérarchie de classes et voulons vérifier si la classe prend en compte l'héritage.