{"id":13398438,"url":"https://github.com/denysdovhan/wtfjs","last_synced_at":"2025-05-12T18:40:24.035Z","repository":{"id":37247025,"uuid":"97249406","full_name":"denysdovhan/wtfjs","owner":"denysdovhan","description":"🤪 A list of funny and tricky JavaScript examples","archived":false,"fork":false,"pushed_at":"2025-03-18T13:55:28.000Z","size":1501,"stargazers_count":36181,"open_issues_count":43,"forks_count":2603,"subscribers_count":562,"default_branch":"master","last_synced_at":"2025-04-17T14:40:24.644Z","etag":null,"topics":["book","handbook","javascript","js","learning","notes","specification","wtf"],"latest_commit_sha":null,"homepage":"http://bit.ly/wtfjavascript","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"wtfpl","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/denysdovhan.png","metadata":{"files":{"readme":"README-fr-fr.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"denysdovhan","patreon":"denysdovhan","custom":["buymeacoffee.com/denysdovhan"]}},"created_at":"2017-07-14T15:42:12.000Z","updated_at":"2025-04-17T08:10:00.000Z","dependencies_parsed_at":"2024-01-06T02:02:17.563Z","dependency_job_id":"5767c2f0-7221-466d-869a-1b9d52d12c43","html_url":"https://github.com/denysdovhan/wtfjs","commit_stats":{"total_commits":347,"total_committers":90,"mean_commits":"3.8555555555555556","dds":0.7896253602305475,"last_synced_commit":"6f832d987472b30e1e3ede82de22e517af69e40b"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denysdovhan%2Fwtfjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denysdovhan%2Fwtfjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denysdovhan%2Fwtfjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denysdovhan%2Fwtfjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/denysdovhan","download_url":"https://codeload.github.com/denysdovhan/wtfjs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249391013,"owners_count":21263204,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["book","handbook","javascript","js","learning","notes","specification","wtf"],"created_at":"2024-07-30T19:00:26.067Z","updated_at":"2025-04-18T03:47:11.305Z","avatar_url":"https://github.com/denysdovhan.png","language":"JavaScript","readme":"# What the f\\*ck JavaScript?\n\n[![WTFPL 2.0][license-image]][license-url]\n[![NPM version][npm-image]][npm-url]\n\n\u003e Une liste d'exemples JavaScript drôles et délicats\n\nLe JavaScript est un langage formidable! Il possède une syntaxe simple, un grand écosystème et, le plus important de tout, une immense communauté.\n\nEn même temps, nous savons tous que le JavaScript est un langage assez amusant comprenant des aspects plus complexes que d'autres. Certains d'entre eux peuvent rapidement faire de notre travail quotidien un enfer, tout comme d'autres peuvent nous faire rire aux éclats.\n\nL'idée originale de WTFJS appartient à [Brian Leroux](https://twitter.com/brianleroux). Cette liste est fortement inspirée par son discours [**“WTFJS”** at dotJS 2012](https://www.youtube.com/watch?v=et8xNAc2ic8):\n\n[![dotJS 2012 - Brian Leroux - WTFJS](https://img.youtube.com/vi/et8xNAc2ic8/0.jpg)](https://www.youtube.com/watch?v=et8xNAc2ic8)\n\n# Le Manuscript sous forme de paquet Node\n\nVous pouvez installer ce manuel en utilisant `npm`. Pour cela, il suffit d'exécuter :\n\n```\n$ npm install -g wtfjs\n```\n\nVous devriez pouvoir ensuite utiliser `wtfjs` en ligne de commande. Cela ouvrira le manuel dans votre terminal. Sinon, vous pouvez continuer à lire ici tout simplement.\n\nLa source du _package_ est disponible ici: \u003chttps://github.com/denysdovhan/wtfjs\u003e\n\n# Traductions\n\nActuellement, il existe des traductions de ** wtfjs ** pour les langues suivantes :\n\n- [中文版](./README-zh-cn.md)\n- [Français](./README-fr-fr.md)\n\n[**Demander une autre traduction**][tr-request]\n\n[tr-request]: https://github.com/denysdovhan/wtfjs/issues/new?title=Translation%20Request:%20%5BPlease%20enter%20language%20here%5D\u0026body=I%20am%20able%20to%20translate%20this%20language%20%5Byes/no%5D\n\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n# Table of Contents\n\n- [💪🏻 Motivation](#-motivation)\n- [✍🏻 Notation](#-notation)\n- [👀 Exemples](#-exemples)\n  - [`[]` est égal à `![]`](#-est-%C3%A9gal-%C3%A0-)\n  - [`true` n'est pas égal à `![]`, mais pas égal à `[]` aussi](#true-nest-pas-%C3%A9gal-%C3%A0--mais-pas-%C3%A9gal-%C3%A0--aussi)\n  - [true est faux](#true-est-faux)\n  - [baNaNa](#banana)\n  - [`NaN` n'est pas un `NaN`](#nan-nest-pas-un-nan)\n  - [C'est un échec](#cest-un-%C3%A9chec)\n  - [`[]` est truthy, mais pas `true`](#-est-truthy-mais-pas-true)\n  - [`null` est falsy, mais pas `faux`](#null-est-falsy-mais-pas-faux)\n  - [`document.all` est un objet, mais il est `undefined`](#documentall-est-un-objet-mais-il-est-undefined)\n  - [La valeur minimale est supérieure à zéro](#la-valeur-minimale-est-sup%C3%A9rieure-%C3%A0-z%C3%A9ro)\n  - [Fonction n'est pas une fonction](#fonction-nest-pas-une-fonction)\n  - [Ajout de tableaux](#ajout-de-tableaux)\n  - [Les virgules finales dans un tableau](#les-virgules-finales-dans-un-tableau)\n  - [L'égalité des tableaux est un monstre](#l%C3%A9galit%C3%A9-des-tableaux-est-un-monstre)\n  - [`undefined` et `Number`](#undefined-et-number)\n  - [`parseInt` est un méchant](#parseint-est-un-m%C3%A9chant)\n  - [Math avec `true` et `false`](#math-avec-true-et-false)\n  - [Les commentaires HTML sont valides en JavaScript](#les-commentaires-html-sont-valides-en-javascript)\n  - [`NaN` n'est ~~pas~~ un nombre](#nan-nest-pas-un-nombre)\n  - [`[]` et `null` sont des objets](#-et-null-sont-des-objets)\n  - [Nombres magiquement croissant](#nombres-magiquement-croissant)\n  - [Précision de `0.1 + 0.2`](#pr%C3%A9cision-de-01--02)\n  - [Patching de numéros](#patching-de-num%C3%A9ros)\n  - [Comparaison de trois nombres](#comparaison-de-trois-nombres)\n  - [Math drôle](#math-dr%C3%B4le)\n  - [Addition de RegExps](#addition-de-regexps)\n  - [Les chaînes ne sont pas des instances de `String`](#les-cha%C3%AEnes-ne-sont-pas-des-instances-de-string)\n  - [Appeler des fonctions avec des caractères accent grave](#appeler-des-fonctions-avec-des-caract%C3%A8res-accent-grave)\n  - [Call call call](#call-call-call)\n  - [Une propriété `constructor`](#une-propri%C3%A9t%C3%A9-constructor)\n  - [Object en tant que clé de la propriété d'un objet](#object-en-tant-que-cl%C3%A9-de-la-propri%C3%A9t%C3%A9-dun-objet)\n  - [Accéder aux prototypes avec `__proto__`](#acc%C3%A9der-aux-prototypes-avec-__proto__)\n  - [`` `${{Object}}` ``](#-object-)\n  - [Déstructuration avec des valeurs par défaut](#d%C3%A9structuration-avec-des-valeurs-par-d%C3%A9faut)\n  - [Points et propagation](#points-et-propagation)\n  - [Étiquettes](#%C3%A9tiquettes)\n  - [Étiquettes imbriquées](#%C3%A9tiquettes-imbriqu%C3%A9es)\n  - [`Try...catch` insidieux](#trycatch-insidieux)\n  - [Est-ce un héritage multiple ?](#est-ce-un-h%C3%A9ritage-multiple-)\n  - [Un générateur qui se `yield` lui-même](#un-g%C3%A9n%C3%A9rateur-qui-se-yield-lui-m%C3%AAme)\n  - [Une classe de classe](#une-classe-de-classe)\n  - [Objets incoercibles](#objets-incoercibles)\n  - [Fonctions fléchées complexes](#fonctions-fl%C3%A9ch%C3%A9es-complexes)\n  - [Les fonctions fléchées ne peuvent pas être un constructeur](#les-fonctions-fl%C3%A9ch%C3%A9es-ne-peuvent-pas-%C3%AAtre-un-constructeur)\n  - [`arguments` et fonctions fléchées](#arguments-et-fonctions-fl%C3%A9ch%C3%A9es)\n  - [Retour difficile](#retour-difficile)\n  - [Chaînage d'affectations sur un objet](#cha%C3%AEnage-daffectations-sur-un-objet)\n  - [Accéder aux propriétés d'un objet avec des tableaux](#acc%C3%A9der-aux-propri%C3%A9t%C3%A9s-dun-objet-avec-des-tableaux)\n  - [Opérateurs `null` et relationnels](#op%C3%A9rateurs-null-et-relationnels)\n  - [`Number.toFixed()` affiche différents nombres](#numbertofixed-affiche-diff%C3%A9rents-nombres)\n  - [`Math.max()` est moins que `Math.min()`](#mathmax-est-moins-que-mathmin)\n  - [Comparer `null` à `0`](#comparer-null-%C3%A0-0)\n  - [Même redéclaration d'une variable](#m%C3%AAme-red%C3%A9claration-dune-variable)\n  - [Comportement par défaut d'`Array.prototype.sort()`](#comportement-par-d%C3%A9faut-darrayprototypesort)\n- [📚 Autres ressources](#-autres-ressources)\n- [🎓 Licence](#-licence)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n# 💪🏻 Motivation\n\n\u003e Juste pour le fun\n\u003e\n\u003e \u0026mdash; _[**“Just for Fun: The Story of an Accidental Revolutionary”**](https://archive.org/details/justforfun00linu), Linus Torvalds_\n\nL'objectif principal de cette liste est de rassembler quelques exemples loufoques et d'expliquer leur fonctionnement, quand c'est possible. 😉 Tout simplement parce qu'il est amusant d'apprendre quelque chose qu'on ne connaissait pas auparavant.\n\nSi vous êtes débutant, vous pouvez aussi utiliser ces notes pour approfondir vos connaissances en JavaScript. J'espère qu'elles vous inciteront à passer plus de temps à lire la spécification.\n\nSi vous êtes un développeur professionnel, vous pouvez considérer ces exemples comme une excellente référence pour toutes les bizarreries et comportements inattendus de notre langage bien-aimé, le JavaScript.\n\nDans tous les cas, lisez ce qui suit. Vous y trouverez probablement quelque chose de nouveau !\n\n# ✍🏻 Notation\n\n**`// -\u003e`** est utilisé pour afficher le résultat d'une expression. Par exemple :\n\n```js\n1 + 1; // -\u003e 2\n```\n\n**`// \u003e`** définit le résultat de `console.log` ou tout autre sortie. Par exemple :\n\n```js\nconsole.log(\"hello, world!\"); // \u003e hello, world!\n```\n\n**`//`** indique un commentaire utilisé pour donner des explications. Par exemple :\n\n```js\n// Assigner une fonction la constant foo\nconst foo = function() {};\n```\n\n# 👀 Exemples\n\n## `[]` est égal à `![]`\n\nTableau est égal à pas tableau\n\n```js\n[] == ![]; // -\u003e true\n```\n\n### 💡 Explication :\n\nL'opérateur de comparaison d'égalité faible convertit les deux côtés en nombres pour les comparer. Pour différentes raisons, les deux côtés deviennent le nombre `0`.\n\nLes tableaux sont truthy, donc à droite, on trouve l'opposé d'une valeur truthy, soit `false`, qui est ensuite forcé à `0`. A gauche, puisqu'un tableau vide est forcé à `0` automatiquement, sans devoir être précédemment transformé en booléen, on trouve aussi `0`, malgré le fait qu'un tableau soit truthy.\n\nVoici comment cette expression se simplifie:\n\n```js\n+[] == +![];\n0 == +false;\n0 == 0;\ntrue;\n```\n\nVoir aussi [`[]` est truthy, mais pas `true`](#-est-truthy-mais-pas-true).\n\n- [**12.5.9** Logical NOT Operator (`!`)](https://www.ecma-international.org/ecma-262/#sec-logical-not-operator)\n- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)\n\n## `true` n'est pas égal à `![]`, mais pas égal à `[]` aussi\n\nUn tableau n'est pas égal à `true`, tout comme pas tableau. Un tableau est égal à `false`, pas tableau est égal à `false` aussi :\n\n```js\ntrue == []; // -\u003e false\ntrue == ![]; // -\u003e false\n\nfalse == []; // -\u003e true\nfalse == ![]; // -\u003e true\n```\n\n### 💡 Explication :\n\n```js\ntrue == []; // -\u003e false\ntrue == ![]; // -\u003e false\n\n// Selon la spécification\n\ntrue == []; // -\u003e false\n\ntoNumber(true); // -\u003e 1\ntoNumber([]); // -\u003e 0\n\n1 == 0; // -\u003e false\n\ntrue == ![]; // -\u003e false\n\n![]; // -\u003e false\n\ntrue == false; // -\u003e false\n```\n\n```js\nfalse == []; // -\u003e true\nfalse == ![]; // -\u003e true\n\n// Selon la spécification\n\nfalse == []; // -\u003e true\n\ntoNumber(false); // -\u003e 0\ntoNumber([]); // -\u003e 0\n\n0 == 0; // -\u003e true\n\nfalse == ![]; // -\u003e false\n\n![]; // -\u003e false\n\nfalse == false; // -\u003e true\n```\n\n- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)\n\n## true est faux\n\n```js\n!!\"false\" == !!\"true\"; // -\u003e true\n!!\"false\" === !!\"true\"; // -\u003e true\n```\n\n### 💡 Explication :\n\nConsidérez ceci étape par étape :\n\n```js\n// `true` est 'truthy' et est représenté par la valeur 1 (nombre), 'true' sous forme de chaîne est NaN.\ntrue == \"true\"; // -\u003e false\nfalse == \"false\"; // -\u003e false\n\n// 'false' n'est pas une chaîne vide, donc c'est une valeur `truthy`\n!!\"false\"; // -\u003e true\n!!\"true\"; // -\u003e true\n```\n\n- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)\n\n## baNaNa\n\n```js\n\"b\" + \"a\" + +\"a\" + \"a\"; // -\u003e 'baNaNa'\n```\n\nCeci est une blague \"old school\" en JavaScript, mais remasterisée. Voici l'originale :\n\n```js\n\"foo\" + +\"bar\"; // -\u003e 'fooNaN'\n```\n\n### 💡 Explication :\n\nL'expression est évaluée comme `'foo' + (+'bar')`, ce qui convertit `'bar'` à `NaN`.\n\n- [**12.8.3** The Addition Operator (`+`)](https://www.ecma-international.org/ecma-262/#sec-addition-operator-plus)\n- [12.5.6 Unary + Operator](https://www.ecma-international.org/ecma-262/#sec-unary-plus-operator)\n\n## `NaN` n'est pas un `NaN`\n\n```js\nNaN === NaN; // -\u003e false\n```\n\n### 💡 Explication :\n\nLa spécification définit strictement la logique derrière ce comportement :\n\n\u003e 1. Si `Type(x)` est différent de `Type(y)`, retourne **false**.\n\u003e 2. Si `Type(x)` est `Number`, alors\n\u003e    1. Si `x` est **NaN**, retourne **false**.\n\u003e    2. Si `y` est **NaN**, retourne **false**.\n\u003e    3. … … …\n\u003e\n\u003e \u0026mdash; [**7.2.14** Strict Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-strict-equality-comparison)\n\nSur la base de la définition de `NaN` de l'IEEE :\n\n\u003e Quatre relations mutuellement exclusives sont possibles : inférieur à, égal, supérieur à, et non ordonné. Le dernier cas survient quand au moins un opérande est `NaN`. Tous les `NaN` doivent se comparer de manière non ordonnée avec tout, y compris avec lui-même.\n\u003e\n\u003e \u0026mdash; [“What is the rationale for all comparisons returning false for IEEE754 NaN values?”](https://stackoverflow.com/questions/1565164/1573715#1573715) sur StackOverflow.\n\n## C'est un échec\n\nVous ne le croiriez pas, mais …\n\n```js\n(![] + [])[+[]] +\n  (![] + [])[+!+[]] +\n  ([![]] + [][[]])[+!+[] + [+[]]] +\n  (![] + [])[!+[] + !+[]];\n// -\u003e 'fail'\n```\n\n### 💡 Explication :\n\nEn brisant cette masse de symboles en morceaux, nous remarquons que le schéma suivant se produit souvent :\n\n```js\n![] + []; // -\u003e 'false'\n![]; // -\u003e false\n```\n\nDonc, nous essayons d'ajouter `[]` à `false`, mais en raison d'un certain nombre d'appels de fonctions internes (`binary + Operator` -\u003e `ToPrimitive` -\u003e `[[DefaultValue]]`), nous finissons par convertir l'opérande de droite en chaîne :\n\n```js\n![] + [].toString(); // 'false'\n```\n\nEn considérant une chaîne comme un tableau, nous pouvons accéder à son premier caractère via `[0]` :\n\n```js\n\"false\"[0]; // -\u003e 'f'\n```\n\nLe reste est évident, sauf pour le `i`. Le `i` dans `fail` est saisi en générant la chaîne `\"falseundefined\"` et en saisissant l'éléments sur l'index `[10]`.\n\n## `[]` est truthy, mais pas `true`\n\nUn tableau est une valeur `truthy`, mais n'est pas égal à `true`.\n\n```js\n!![]       // -\u003e true\n[] == true // -\u003e false\n```\n\n### 💡 Explication :\n\nVoici des liens vers les sections correspondantes de la spécification ECMA-262 :\n\n- [**12.5.9** Logical NOT Operator (`!`)](https://www.ecma-international.org/ecma-262/#sec-logical-not-operator)\n- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)\n\n## `null` est falsy, mais pas `faux`\n\nMalgré le fait que `null` soit une valeur `falsy`, elle n'est pas égale à `false`.\n\n```js\n0 == false; // -\u003e true\n\"\" == false; // -\u003e true\n```\n\n### 💡 Explication :\n\nL'explication est la même que pour l'exemple précédent. Voici le lien correspondant :\n\n- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)\n\n## `document.all` est un objet, mais il est `undefined`\n\n\u003e ⚠️ Ceci fait partie de la Browser API et ne fonctionnera pas dans un environnement Node.js ⚠️\n\nMalgré le fait que `document.all` soit un objet de type tableau et qu'il donne accès aux nœuds DOM de la page, il répond à la fonction `typeof` comme étant `undefined`.\n\n```js\ndocument.all instanceof Object; // -\u003e true\ntypeof document.all; // -\u003e 'undefined'\n```\n\nEn même temps, `document.all` n'est pas égal à `undefined`.\n\n```js\ndocument.all === undefined; // -\u003e false\ndocument.all === null; // -\u003e false\n```\n\nMais, parallèlement :\n\n```js\ndocument.all == null; // -\u003e true\n```\n\n### 💡 Explication :\n\n\u003e `document.all` était anciennement un moyen d'accéder aux éléments DOM, principalement avec les anciennes versions d'IE. Bien que cela n'ait jamais été une norme, `document.all` était largement utilisé dans \"l'ancien code JS\". Quand la norme a progressé avec la venue de nouvelles API (par exemple, `document.getElementById`), l'API `document.all` est devenue obsolète et le comité de normes a dû décider ce qu'ils allaient en faire. En raison de sa large utilisation, ils ont décidé de la conserver, mais d'introduire une violation volontaire de la spécification JavaScript.\n\u003e La raison pour laquelle `document.all` retourne `false` lors de l'utilisation de l'opérateur d'égalité stricte ([Strict Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-strict-equality-comparison)) avec `undefined` et `true` lors de l'utilisation de l'opérateur d'égalité abstraite ([Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)) est due à la violation volontaire de la spécification qui le permet explicitement.\n\u003e\n\u003e \u0026mdash; [“Obsolete features - document.all”](https://html.spec.whatwg.org/multipage/obsolete.html#dom-document-all) sur WhatWG - HTML spec.\n\u003e \u0026mdash; [“Chapter 4 - ToBoolean - Falsy values”](https://github.com/getify/You-Dont-Know-JS/blob/0d79079b61dad953bbfde817a5893a49f7e889fb/types%20%26%20grammar/ch4.md#falsy-objects) sur YDKJS - Types \u0026 Grammar.\n\n## La valeur minimale est supérieure à zéro\n\n`Number.MIN_VALUE` est le plus petit nombre, qui est supérieur à zéro :\n\n```js\nNumber.MIN_VALUE \u003e 0; // -\u003e true\n```\n\n### 💡 Explication :\n\n\u003e `Number.MIN_VALUE` est `5e-324`, c'est-à-dire le plus petit nombre positif pouvant être représenté dans la précision flottante et donc, c'est aussi le plus près que possible de zéro. Il définit la meilleure résolution que vous pouvez atteindre avec des valeurs flottantes.\n\u003e\n\u003e Maintenant, la plus petite valeur globale est `Number.NEGATIVE_INFINITY`, bien que cette dernière ne soit pas vraiment numérique au sens strict.\n\u003e\n\u003e \u0026mdash; [“Why is `0` less than `Number.MIN_VALUE` in JavaScript?”](https://stackoverflow.com/questions/26614728/why-is-0-less-than-number-min-value-in-javascript) at StackOverflow\n\n- [**20.1.2.9** Number.MIN_VALUE](https://www.ecma-international.org/ecma-262/#sec-number.min_value)\n\n## Fonction n'est pas une fonction\n\n\u003e ⚠️ Une erreur présente dans la v5.5 (V8) ou inférieure de Node.js (Node.js \u003c=7) ⚠️\n\nVous êtes tous au courant de l'irritant _undefined is not a function_, mais qu'en est-il de ceci :\n\n```js\n// Déclare une classe qui _extends_ `null`\nclass Foo extends null {}\n// -\u003e [Function: Foo]\n\nnew Foo() instanceof null;\n// \u003e TypeError: function is not a function\n// \u003e     at … … …\n```\n\n### 💡 Explication :\n\nCeci ne fait pas partie de la spécification. C'est seulement une erreur qui a depuis été corrigé, il ne devrait donc plus y avoir de problème à l'avenir.\n\n## Ajout de tableaux\n\nEt si vous essayiez d'additionner deux tableaux ?\n\n```js\n[1, 2, 3] + [4, 5, 6]; // -\u003e '1,2,34,5,6'\n```\n\n### 💡 Explication :\n\nC'est la concaténation ! Etape par étape, ça ressemble à ceci :\n\n```js\n[1, 2, 3] +\n  [4, 5, 6][\n    // appelle toString()\n    (1, 2, 3)\n  ].toString() +\n  [4, 5, 6].toString();\n// concaténation\n\"1,2,3\" + \"4,5,6\";\n// -\u003e\n(\"1,2,34,5,6\");\n```\n\n## Les virgules finales dans un tableau\n\nVous avez créé un tableau avec 4 éléments vides. Malgré tout, vous obtiendrez un tableau avec seulement trois éléments, à cause des virgules finales.\n\n```js\nlet a = [, , ,];\na.length; // -\u003e 3\na.toString(); // -\u003e ',,'\n```\n\n### 💡 Explication :\n\n\u003e Les **virgules finales** (_trailing commas_ en anglais) peuvent être utiles lors de l'ajout de nouveaux éléments, de paramètres ou de propriétés à du code JavaScript. Si vous voulez ajouter une nouvelle propriété, vous pouvez tout simplement ajouter une nouvelle ligne sans modifier la ligne précédente si cette ligne utilise déjà une virgule finale. Cela rend plus clair les différences dans un système de contrôle de version et l'édition de code pourrait être moins difficile.\n\u003e\n\u003e \u0026mdash; [Virgules finales (trailing commas)](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Virgules_finales) sur MDN.\n\n## L'égalité des tableaux est un monstre\n\nEn JavaScript, l'égalité des tableaux est un monstre, comme vous pouvez le voir ci-dessous :\n\n```js\n[] == ''   // -\u003e true\n[] == 0    // -\u003e true\n[''] == '' // -\u003e true\n[0] == 0   // -\u003e true\n[0] == ''  // -\u003e false\n[''] == 0  // -\u003e true\n\n[null] == ''      // true\n[null] == 0       // true\n[undefined] == '' // true\n[undefined] == 0  // true\n\n[[]] == 0  // true\n[[]] == '' // true\n\n[[[[[[]]]]]] == '' // true\n[[[[[[]]]]]] == 0  // true\n\n[[[[[[ null ]]]]]] == 0  // true\n[[[[[[ null ]]]]]] == '' // true\n\n[[[[[[ undefined ]]]]]] == 0  // true\n[[[[[[ undefined ]]]]]] == '' // true\n```\n\n### 💡 Explication :\n\nVous devriez regarder très attentivement les exemples ci-dessus ! Ce comportement est décrit dans la section [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison) de la spécification.\n\n## `undefined` et `Number`\n\nSi nous ne transmettons aucun argument dans le constructeur `Number`, nous obtiendrons `0`. La valeur `undefined` est attribuée aux arguments formels en l'absence d'arguments, alors vous pouvez vous attendre à ce que `Number` sans argument utilise `undefined` comme valeur de paramètre. Toutefois, quand nous lui passons `undefined` directement, nous obtiendrons `NaN` en retour.\n\n```js\nNumber(); // -\u003e 0\nNumber(undefined); // -\u003e NaN\n```\n\n### 💡 Explication :\n\nSelon la spécification :\n\n1. Si aucun argument n'a été passé lors de l'appel de la fonction, `n` est `+0`.\n2. Sinon, `n` est ? `ToNumber(value)`.\n3. Dans le cas d'`undefined`, `ToNumber(undefined)` doit retourner `NaN`.\n\nVoici les sections correspondantes :\n\n- [**20.1.1** The Number Constructor](https://www.ecma-international.org/ecma-262/#sec-number-constructor)\n- [**7.1.3** ToNumber(`argument`)](https://www.ecma-international.org/ecma-262/#sec-tonumber)\n\n## `parseInt` est un méchant\n\n`parseInt` est célèbre pour ses bizarreries:\n\n```js\nparseInt(\"f*ck\"); // -\u003e NaN\nparseInt(\"f*ck\", 16); // -\u003e 15\n```\n\n**💡 Explication :** Ce résultat est dû au fait que `parseInt` continue d'analyser caractère par caractère la chaîne jusqu'à ce qu'il rencontre un caractère qu'il ne connaît pas. Le `f` dans `'f*ck'` correspond au chiffre hexadécimal `15`.\n\nAnalyser `Infinity` comme entier est quelque chose…\n\n```js\n//\nparseInt(\"Infinity\", 10); // -\u003e NaN\n// ...\nparseInt(\"Infinity\", 18); // -\u003e NaN...\nparseInt(\"Infinity\", 19); // -\u003e 18\n// ...\nparseInt(\"Infinity\", 23); // -\u003e 18...\nparseInt(\"Infinity\", 24); // -\u003e 151176378\n// ...\nparseInt(\"Infinity\", 29); // -\u003e 385849803\nparseInt(\"Infinity\", 30); // -\u003e 13693557269\n// ...\nparseInt(\"Infinity\", 34); // -\u003e 28872273981\nparseInt(\"Infinity\", 35); // -\u003e 1201203301724\nparseInt(\"Infinity\", 36); // -\u003e 1461559270678...\nparseInt(\"Infinity\", 37); // -\u003e NaN\n```\n\nSoyez prudent avec l'analyse de `null` aussi :\n\n```js\nparseInt(null, 24); // -\u003e 23\n```\n\n**💡 Explication :**\n\n\u003e `parsetInt` convertit `null` sous forme de chaîne `\"null\"` et essait de la convertir. Pour les bases comprises entre 0 et 23, `parseInt` ne peut convertir aucun chiffre, donc `parseInt` renvoie `NaN`. Sur 24, `\"n\"`, la 14ème lettre, est ajoutée au système de numération. Sur 31, `\"u\"`, la 21ème lettre, est ajoutée et la chaîne entière peut être décodée. Sur 37, il n'y a plus de jeu de valeur numérique valide pouvant être générée, donc, `NaN` est renvoyé.\n\u003e\n\u003e \u0026mdash; [“parseInt(null, 24) === 23… wait, what?”](https://stackoverflow.com/questions/6459758/parseintnull-24-23-wait-what) sur StackOverflow.\n\nN'oubliez pas les octaux:\n\n```js\nparseInt(\"06\"); // 6\nparseInt(\"08\"); // 8 si support ECMAScript 5\nparseInt(\"08\"); // 0 si pas support ECMAScript 5\n```\n\n**💡 Explication :** Si la chaîne d'entrée commence par 0, la base est égale à 8 (octal) ou à 10 (décimal). La base choisie dépend de l'implémentation. ECMAScript 5 indique que la valeur 10 (décimal) est utilisée, mais tous les navigateurs ne le prennent pas encore en charge. Pour cette raison, spécifiez toujours une base lorsque vous utilisez `parseInt`.\n\n`parseInt` convertit toujours une entrée en chaîne :\n\n```js\nparseInt({ toString: () =\u003e 2, valueOf: () =\u003e 1 }); // -\u003e 2\nNumber({ toString: () =\u003e 2, valueOf: () =\u003e 1 }); // -\u003e 1\n```\n\nSoyez prudent lors d'analyse de valeurs en virgule flottante :\n\n```js\nparseInt(0.000001); // -\u003e 0\nparseInt(0.0000001); // -\u003e 1\nparseInt(1 / 1999999); // -\u003e 5\n```\n\n**💡 Explication :** `parseInt` prend une chaîne de caractère comme argument et retourne un entier sur la base spécifiée. `parseInt` supprime aussi tout ce que suit, incluant le premier non-chiffre de la chaîne transmise en paramètre. `0.000001` est converti en chaîne `\"0.000001\"`, et `parseInt` retourne `0`. Quand `0.0000001` est converti en chaîne, il est traité comme `\"1e-7\"` et retourne donc `1`. `1/1999999` est interprété comme étant `5.00000250000125e-7` et retourne `5`.\n\n## Math avec `true` et `false`\n\nFaisons des maths :\n\n```js\ntrue +\n  true(\n    // -\u003e 2\n    true + true\n  ) *\n    (true + true) -\n  true; // -\u003e 3\n```\n\nHmmm… 🤔\n\n### 💡 Explication :\n\nAvec le constructeur `Number`, nous pouvons forcer les valeurs aux nombres. Il est assez évident que `true` sera forcé à `1`.\n\n```js\nNumber(true); // -\u003e 1\n```\n\nL'opérateur unaire `+` tente de convertir sa valeur en nombre. Il peut convertir des représentations d'entiers et de nombres flottants sous forme de chaîne, de même que les valeurs `true`, `false` et `null`. S'il ne peut pas analyser une valeur particulière, il sera évalué à `NaN`. Cela signifie que nous pouvons contraindre `true` à `1` plus facilement :\n\n```js\n+true; // -\u003e 1\n```\n\nLorsque vous effectuez une addition ou une multiplication, la méthode `ToNumber` est appelée. Selon la spécification, cette méthode retourne :\n\n\u003e Si `argument` est **true**, retourne **1**. Si `argument` est **false**, retourne **+0**.\n\nC'est pourquoi nous pouvons ajouter des valeurs booléennes en tant que nombres réguliers et obtenir des résultats corrects.\n\nLes sections correspondantes :\n\n- [**12.5.6** Unary `+` Operator](https://www.ecma-international.org/ecma-262/#sec-unary-plus-operator)\n- [**12.8.3** The Addition Operator (`+`)](https://www.ecma-international.org/ecma-262/#sec-addition-operator-plus)\n- [**7.1.3** ToNumber(`argument`)](https://www.ecma-international.org/ecma-262/#sec-tonumber)\n\n## Les commentaires HTML sont valides en JavaScript\n\nVous serez impressionné, mais `\u003c!--` (connu sous le nom de commentaire HTML) est aussi valide comme commentaire en JavaScript.\n\n```js\n// commentaire valide\n\u003c!-- commentaire valide aussi\n```\n\n### 💡 Explication :\n\nImpressionné ? Les commentaires de type HTML étaient à la base destinés à permettre aux navigateurs ne comprenant pas la balise `\u003cscript\u003e` de se dégrader avec élégance. Ces navigateurs, par exemple Netscape 1.x, ne sont plus populaires aujourd'hui. Il est donc inutile de mettre des commenaitres HTML dans vos balises `\u003cscript\u003e`.\n\n- [**B.1.3** HTML-like Comments](https://www.ecma-international.org/ecma-262/#sec-html-like-comments)\n\n## `NaN` n'est ~~pas~~ un nombre\n\n`typeof` `NaN` est un `'number'` :\n\n```js\ntypeof NaN; // -\u003e 'number'\n```\n\n### 💡 Explication :\n\nExplications sur le fonctionnement des opérateurs `typeof` et `instanceof` :\n\n- [**12.5.5** The `typeof` Operator](https://www.ecma-international.org/ecma-262/#sec-typeof-operator)\n- [**12.10.4** Runtime Semantics: InstanceofOperator(`O`,`C`)](https://www.ecma-international.org/ecma-262/#sec-instanceofoperator)\n\n## `[]` et `null` sont des objets\n\n```js\ntypeof []; // -\u003e \"object\"\ntypeof null; // -\u003e \"object\"\n\n// however\nnull instanceof Object; // false\n```\n\n### 💡 Explication :\n\nLe comportement de l'opérateur `typeof` est défini dans la section suivante de la spécification :\n\n- [**12.5.5** The `typeof` Operator](https://www.ecma-international.org/ecma-262/#sec-typeof-operator)\n\nSelon la spécification, l'opérateur `typeof` renvoie une chaîne : [Table 35: `typeof` Operator Results](https://www.ecma-international.org/ecma-262/#table-35). Pour les objets `null`, ordinaires, _standard exotic_ et _non-standard exotic_, qui n'implémentent pas `[[Call]]`, il retourne la chaîne `\"object\"`.\n\nEn revanche, vous pouvez vérifier le type d'un objet en utilisant la méthode `toString`.\n\n```js\nObject.prototype.toString.call([]);\n// -\u003e '[object Array]'\n\nObject.prototype.toString.call(new Date());\n// -\u003e '[object Date]'\n\nObject.prototype.toString.call(null);\n// -\u003e '[object Null]'\n```\n\n## Nombres magiquement croissant\n\n```js\n999999999999999; // -\u003e 999999999999999\n9999999999999999; // -\u003e 10000000000000000\n\n10000000000000000; // -\u003e 10000000000000000\n10000000000000000 + 1; // -\u003e 10000000000000000\n10000000000000000 + 1.1; // -\u003e 10000000000000002\n```\n\n### 💡 Explication :\n\nCeci est dû à la norme IEEE 754-2008 concernant l'arithmétique binaire en virgule flottante. À cette échelle, un nombre s'arrondit au nombre pair le plus près. Plus d'infos :\n\n- [**6.1.6** The Number Type](https://www.ecma-international.org/ecma-262/#sec-ecmascript-language-types-number-type)\n- [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) sur Wikipedia\n\n## Précision de `0.1 + 0.2`\n\nUne blague bien connue. L'ajout de `0.1` et de `0.2` est mortellement précis :\n\n```js\n0.1 +\n  0.2(\n    // -\u003e 0.30000000000000004\n    0.1 + 0.2\n  ) ===\n  0.3; // -\u003e false\n```\n\n### 💡 Explication :\n\nLa réponse à la question [”Is floating point math broken?”](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) sur StackOverflow:\n\n\u003e Les constantes `0.2` et `0.3` seront également des approximations à leurs vraies valeurs. Il arrive que le `double` le plus proche de `0.2` soit supérieur au nombre rationnel `0.2`, mais que le `double` le plus proche de `0.3` soit inférieur au nombre rationnel `0.3`. La somme de `0.1` et `0.2` finit donc par être supérieure au nombre rationnel `0.3` et donc, en désaccord avec la constante de votre code.\n\nLe problème est tellement connu qu'il y a même un site web appelé [0.30000000000000004.com](http://0.30000000000000004.com/). Il est récurrent pour tous les langages utilisant des mathématiques avec des virgules flottantes, pas seulement JavaScript.\n\n## Patching de numéros\n\nVous pouvez ajouter vos propres méthodes pour encapsuler des objets comme `Number` ou `String`.\n\n```js\nNumber.prototype.isOne = function() {\n  return Number(this) === 1;\n};\n\n(1.0).isOne(); // -\u003e true\n(1).isOne(); // -\u003e true\n(2.0)\n  .isOne()(\n    // -\u003e false\n    7\n  )\n  .isOne(); // -\u003e false\n```\n\n### 💡 Explication :\n\nDe toute évidence, vous pouvez _extend_ l'objet `Number` comme n'importe quel autre objet en JavaScript, mais ce n'est toutefois pas recommandé si le comportement de la méthode définie ne fait partie de la spécification. Voici donc la liste des propriétés de `Number` :\n\n- [**20.1** Number Objects](https://www.ecma-international.org/ecma-262/#sec-number-objects)\n\n## Comparaison de trois nombres\n\n```js\n1 \u003c 2 \u003c 3; // -\u003e true\n3 \u003e 2 \u003e 1; // -\u003e false\n```\n\n### 💡 Explication :\n\nPourquoi est-ce que cela fonctionne ainsi ? Et bien le problème se trouve dans la première partie de l'expression. Voici comment cela fonctionne :\n\n```js\n1 \u003c 2 \u003c 3; // 1 \u003c 2 -\u003e true\ntrue \u003c 3; // true -\u003e 1\n1 \u003c 3; // -\u003e true\n\n3 \u003e 2 \u003e 1; // 3 \u003e 2 -\u003e true\ntrue \u003e 1; // true -\u003e 1\n1 \u003e 1; // -\u003e false\n```\n\nNous pouvons résoudre ce problème avec _l'opérateur Supérieur ou égal à (`\u003e=`)_ :\n\n```js\n3 \u003e 2 \u003e= 1; // true\n```\n\nEn savoir plus sur les opérateurs relationnels dans la spécification :\n\n- [**12.10** Relational Operators](https://www.ecma-international.org/ecma-262/#sec-relational-operators)\n\n## Math drôle\n\nSouvent, les résultats d'opérations arithmétiques en JavaScript peuvent être assez inattendus. Considérez ces exemples :\n\n```js\n 3  - 1  // -\u003e 2\n 3  + 1  // -\u003e 4\n'3' - 1  // -\u003e 2\n'3' + 1  // -\u003e '31'\n\n'' + '' // -\u003e ''\n[] + [] // -\u003e ''\n{} + [] // -\u003e 0\n[] + {} // -\u003e '[object Object]'\n{} + {} // -\u003e '[object Object][object Object]'\n\n'222' - -'111' // -\u003e 333\n\n[4] * [4]       // -\u003e 16\n[] * []         // -\u003e 0\n[4, 4] * [4, 4] // NaN\n```\n\n### 💡 Explication :\n\nQue se passe-t-il dans les quatre premiers exemples ? Voici un petit tableau pour comprendre les additions en JavaScript :\n\n```\nNombre  + Nombre  -\u003e addition\nBooléen + Nombre  -\u003e addition\nBooléen + Booléen -\u003e addition\nNombre  + Chaîne -\u003e concaténation\nChaîne  + Booléen -\u003e concaténation\nChaîne  + Chaîne  -\u003e concaténation\n```\n\nQu'en est-il des autres exemples ? Les méthodes `ToPrimitive` et `ToString` sont implicitement appelées pour `[]` et `{}` avant une addition. En lire plus sur le processus d'évalution dans la spécification :\n\n- [**12.8.3** The Addition Operator (`+`)](https://www.ecma-international.org/ecma-262/#sec-addition-operator-plus)\n- [**7.1.1** ToPrimitive(`input` [,`PreferredType`])](https://www.ecma-international.org/ecma-262/#sec-toprimitive)\n- [**7.1.12** ToString(`argument`)](https://www.ecma-international.org/ecma-262/#sec-tostring)\n\n## Addition de RegExps\n\nSaviez-vous que vous pouviez ajouter des nombres comme dans l'exemple ci-dessous ?\n\n```js\n// Remplacement de la méthode toString\nRegExp.prototype.toString =\n  function() {\n    return this.source;\n  } /\n  7 /\n  -/5/; // -\u003e 2\n```\n\n### 💡 Explication :\n\n- [**21.2.5.10** get RegExp.prototype.source](https://www.ecma-international.org/ecma-262/#sec-get-regexp.prototype.source)\n\n## Les chaînes ne sont pas des instances de `String`\n\n```js\n\"str\"; // -\u003e 'str'\ntypeof \"str\"; // -\u003e 'string'\n\"str\" instanceof String; // -\u003e false\n```\n\n### 💡 Explication :\n\nLe constructeur `String` retourne une chaîne :\n\n```js\ntypeof String(\"str\"); // -\u003e 'string'\nString(\"str\"); // -\u003e 'str'\nString(\"str\") == \"str\"; // -\u003e true\n```\n\nEssayons avec un `new` :\n\n```js\nnew String(\"str\") == \"str\"; // -\u003e true\ntypeof new String(\"str\"); // -\u003e \"object\"\n```\n\nUn objet ? Qu'est-ce que c'est ?\n\n```js\nnew String(\"str\"); // -\u003e [String: 'str']\n```\n\nPlus d'infos sur le constructeur `String` dans la spécification :\n\n- [**21.1.1** The String Constructor](https://www.ecma-international.org/ecma-262/#sec-string-constructor)\n\n## Appeler des fonctions avec des caractères accent grave\n\nDéclarons une fonction qui enregistre tous les paramètres dans la console :\n\n```js\nfunction f(...args) {\n  return args;\n}\n```\n\nAucun doute, vous savez qu'il est possible d'appeler cette fonction comme ceci :\n\n```js\nf(1, 2, 3); // -\u003e [ 1, 2, 3 ]\n```\n\nMais saviez-vous que vous pouvez appeler n'importe quelle fonction avec des caractères accent grave (_backticks_ en anglais) ?\n\n```js\nf`true is ${true}, false is ${false}, array is ${[1, 2, 3]}`;\n// -\u003e [ [ 'true is ', ', false is ', ', array is ', '' ],\n// -\u003e   true,\n// -\u003e   false,\n// -\u003e   [ 1, 2, 3 ] ]\n```\n\n### 💡 Explication :\n\nBon, ce n'est pas du tout magique si vous êtes familier des _littéraux de gabarits étiquetés_. Dans l'exemple ci-dessus, la fonction `f` est une étiquette pour littéral de gabarit. Les étiquettes avant un littéral de gabarit vous permettent d'analyser les littéraux de gabarits avec une fonction. Le premier argument d'une fonction étiquetée contient un tableau avec comme valeurs des chaînes. Les arguments restants sont liés aux expressions. Exemple :\n\n```js\nfunction template(strings, ...keys) {\n  // fait quelque chose avec `strings` et `keys`…\n}\n```\n\nVoici la [magic behind](http://mxstbr.blog/2016/11/styled-components-magic-explained/) la célébre bibliothèque appelée [💅 styled-components](https://www.styled-components.com/), qui est populaire dans la communauté React.\n\nLien vers la spécification :\n\n- [**12.3.7** Tagged Templates](https://www.ecma-international.org/ecma-262/#sec-tagged-templates)\n\n## Call call call\n\n\u003e Trouvé par [@cramforce](http://twitter.com/cramforce)\n\n```js\nconsole.log.call.call.call.call.call.apply(a =\u003e a, [1, 2]);\n```\n\n### 💡 Explication :\n\nAttention, ceci pourrait vous casser la tête ! Essayez de reproduire ce code dans votre tête : nous appliquons la méthode `call` en utilisant la méthode `apply`. Plus d'infos :\n\n- [**19.2.3.3** Function.prototype.call(`thisArg`, ...`args`)](https://www.ecma-international.org/ecma-262/#sec-function.prototype.call)\n- [**19.2.3.1 ** Function.prototype.apply(`thisArg`, `argArray`)](https://www.ecma-international.org/ecma-262/#sec-function.prototype.apply)\n\n## Une propriété `constructor`\n\n```js\nconst c = \"constructor\";\nc[c][c]('console.log(\"WTF?\")')(); // \u003e WTF?\n```\n\n### 💡 Explication :\n\nConsidérez cet exemple étape par étape :\n\n```js\n// Déclare une nouvelle constante qui est une chaîne : \"constructor\"\nconst c = \"constructor\";\n\n// `c` est une chaîne\nc; // -\u003e 'constructor'\n\n// Pour obtenir le constructeur de la chaîne\nc[c]; // -\u003e [Function: String]\n\n// Pour obtenir le constructeur du constructeur\nc[c][c]; // -\u003e [Function: Function]\n\n// Appelle la Fonction constructeur et passe\n// le corps d'une nouvelle fonction comme argument\nc[c][c]('console.log(\"WTF?\")'); // -\u003e [Function: anonymous]\n\n// Et ensuite appelle cette fonction anonyme\n// Le résultat est un retour de console avec la chaîne \"WTF?\"\nc[c][c]('console.log(\"WTF?\")')(); // \u003e \"WTF?\"\n```\n\nUn `Object.prototype.constructor` renvoie une référence à la fonction constructeur `Object` qui a créé l'instance de l'objet. Dans le cas des chaînes, il s'agit de `String`, dans le cas des nombres, il s'agit de `Number`, et ainsi de suite.\n\n- [`Object.prototype.constructor`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor) at MDN\n- [**19.1.3.1** Object.prototype.constructor](https://www.ecma-international.org/ecma-262/#sec-object.prototype.constructor)\n\n## Object en tant que clé de la propriété d'un objet\n\n```js\n{ [{}]: {} } // -\u003e { '[object Object]': {} }\n```\n\n### 💡 Explication :\n\nPourquoi est-ce que ça marche ? Ici, nous utilisons un _Computed property name_. Quand vous passez un objet entre ces crochets, l'objet est forcé de devenir une chaîne, alors nous obtenons la clé `[objet Object]` et la valeur `{}`.\n\nNous pouvons créer des enfers de crochets et de parenthèses comme dans l'exemple ci-dessous :\n\n```js\n({ [{}]: { [{}]: {} } }[{}][{}]); // -\u003e {}\n\n// structure:\n// {\n//   '[object Object]': {\n//     '[object Object]': {}\n//   }\n// }\n```\n\nEn savoir plus sur les objets littéraux ici:\n\n- [Object initializer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer) at MDN\n- [**12.2.6** Object Initializer](http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer)\n\n## Accéder aux prototypes avec `__proto__`\n\nComme nous le savons, les primitives n’ont pas de prototypes. Cependant, si nous essayons d'obtenir une valeur de `__proto__` pour les primitives, nous obtiendrions ceci :\n\n```js\n(1).__proto__.__proto__.__proto__; // -\u003e null\n```\n\n### 💡 Explication :\n\nCela se produit car lorsque quelque chose n'a pas de prototype, il sera encapsulé dans un objet à l'aide de la méthode `ToObject`. Donc, étape par étape :\n\n```js\n(1)\n  .__proto__(\n    // -\u003e [Number: 0]\n    1\n  )\n  .__proto__.__proto__(\n    // -\u003e {}\n    1\n  ).__proto__.__proto__.__proto__; // -\u003e null\n```\n\nVoici plus d'infos sur `__proto__` :\n\n- [**B.2.2.1** Object.prototype.**proto**](https://www.ecma-international.org/ecma-262/#sec-object.prototype.__proto__)\n- [**7.1.13** ToObject(`argument`)](https://www.ecma-international.org/ecma-262/#sec-toobject)\n\n## `` `${{Object}}` ``\n\nQuel est le résultat de l'expression ci-dessous ?\n\n```js\n`${{ Object }}`;\n```\n\nLa réponse est :\n\n```js\n// -\u003e '[object Object]'\n```\n\n### 💡 Explication :\n\nNous avons défini un objet avec une propriété `Object` en utilisant une _propriété de notation raccourcie_ :\n\n```js\n{\n  Object: Object;\n}\n```\n\nEnsuite, nous avons passé cet objet au litéral de gabarit, ce qui fait que la méthode `toString` appelle donc cet objet. Voilà pourquoi nous obtenons la chaîne `'[object Object]'`.\n\n- [**12.2.9** Template Literals](https://www.ecma-international.org/ecma-262/#sec-template-literals)\n- [Initialisateur d'objet](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Initialisateur_objet) sur MDN.\n\n## Déstructuration avec des valeurs par défaut\n\nConsidérez cet exemple :\n\n```js\nlet x,\n  { x: y = 1 } = { x };\ny;\n```\n\nL'exemple ci-dessus est une bonne question pour un entretien. Quelle est la valeur de `y` ? La réponse est :\n\n```js\n// -\u003e 1\n```\n\n### 💡 Explication :\n\n```js\nlet x,\n  { x: y = 1 } = { x };\ny;\n//  ↑       ↑           ↑    ↑\n//  1       3           2    4\n```\n\nAvec l'exemple ci-dessus :\n\n1. On déclare `x` sans valeur, donc sa valeur est `undefined`.\n2. Ensuite, nous intégrons la valeur de `x` dans la propriété de l'objet `x`.\n3. Ensuite, nous extrayons la valeur de `x` en utilisant la déstructuration pour l'assigner à `y`. Si la valeur n'est pas déinie, nous utiliserons `1` comme valeur par défaut.\n4. Retourne la valeur de `y`.\n\n- [Initialisateur d'objet](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Initialisateur_objet) sur MDN.\n\n## Points et propagation\n\nDes exemples intéressants pourraient être composés avec la propagation de tableaux. Considérez cela :\n\n```js\n[...[...\"...\"]].length; // -\u003e 3\n```\n\n### 💡 Explication :\n\nPourquoi `3` ? Lorsque nous utilisons le _[spread operator](http://www.ecma-international.org/ecma-262/6.0/#sec-array-initializer)_, la méthode `@@iterator` est appelée et l'itérateur renvoyé est utilisé pour obtenir les valeurs à itérer. L'itérateur par défaut pour une chaîne étend une chaîne en caractères. Après sa propagation, ces caractères sont empaquetés dans un tableau. Ensuite, ce tableau est à nouveau propagé et empaqueté encore une fois dans un tableau.\n\nUne chaîne `'...'` est composée de trois caractères `.`, donc, la longueur du tableau résultant est de `3`.\n\nMaintenant, étape par étape :\n\n```js\n[...'...']             // -\u003e [ '.', '.', '.' ]\n[...[...'...']]        // -\u003e [ '.', '.', '.' ]\n[...[...'...']].length // -\u003e 3\n```\n\nÉvidemment, nous pouvons étendre et encapsuler les éléments d’un tableau autant de fois que nous le souhaitons :\n\n```js\n[...'...']                 // -\u003e [ '.', '.', '.' ]\n[...[...'...']]            // -\u003e [ '.', '.', '.' ]\n[...[...[...'...']]]       // -\u003e [ '.', '.', '.' ]\n[...[...[...[...'...']]]]  // -\u003e [ '.', '.', '.' ]\n// etc.\n```\n\n## Étiquettes\n\nPeu de programmeurs connaissent les étiquettes en JavaScript. Elles sont plutôt intéressantes :\n\n```js\nfoo: {\n  console.log(\"first\");\n  break foo;\n  console.log(\"second\");\n}\n\n// -\u003e first\n// -\u003e undefined\n```\n\n### 💡 Explication :\n\nLa déclaration étiquetée est utilisée avec les déclarations `break` ou `continue`. Vous pouvez utiliser une étiquette pour identifier une boucle, puis ensuite, utiliser la déclaration `break` ou `continue` pour indiquer si un programme doit interrompre la boucle ou poursuivre son exécution.\n\nDans l'exemple ci-dessus, nous identifions une étiquette `foo`. Ensuite, `console.log('first');` est exécuté et l'exécution est interrompue.\n\nEn savoir plus sur les étiquettes en JavaScript :\n\n- [**13.13** Labelled Statements](https://tc39.github.io/ecma262/#sec-labelled-statements)\n- [Label](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Instructions/label) sur MDN.\n\n## Étiquettes imbriquées\n\n```js\na: b: c: d: e: f: g: 1, 2, 3, 4, 5; // -\u003e 5\n```\n\n### 💡 Explication :\n\nSimilaire aux exemples précédents, suivez ces liens pour plus d'infos :\n\n- [**12.16** Comma Operator (`,`)](https://www.ecma-international.org/ecma-262/#sec-comma-operator)\n- [**13.13** Labeled Statements](https://tc39.github.io/ecma262/#sec-labelled-statements)\n- [Label](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Instructions/label) sur MDN.\n\n## `Try...catch` insidieux\n\nQue retournera cette expression ? `2` ou `3` ?\n\n```js\n(() =\u003e {\n  try {\n    return 2;\n  } finally {\n    return 3;\n  }\n})();\n```\n\nLa réponse est `3`. Surprenant ?\n\n### 💡 Explication :\n\n- [**13.15** The `try` Statement](https://www.ecma-international.org/ecma-262/#sec-try-statement)\n\n## Est-ce un héritage multiple ?\n\nRegardez l'exemple ci-dessous :\n\n```js\nnew class F extends (String, Array) {}(); // -\u003e F []\n```\n\nEst-ce un héritage multiple ? Non.\n\n### 💡 Explication :\n\nL'élément intéressant est la valeur de la clause `extends` (`(String, Array)`). L'opérateur de groupement retourne toujours son dernier argument, donc `(String, Array)` est en réalité simplement `Array`. Cela signifie que nous venons de créer une classe qui _extends_ `Array`.\n\n- [**14.5** Class Definitions](https://www.ecma-international.org/ecma-262/#sec-class-definitions)\n- [**12.16** Comma Operator (`,`)](https://www.ecma-international.org/ecma-262/#sec-comma-operator)\n\n## Un générateur qui se `yield` lui-même\n\nConsidérez cet exemple de générateur qui se `yield` lui-même :\n\n```js\n(function* f() {\n  yield f;\n})().next();\n// -\u003e { value: [GeneratorFunction: f], done: false }\n```\n\nComme vous pouvez le constater, la valeur renvoyée est un objet dont la `valeur` est égale à `f`. Dans ce cas, nous pouvons faire quelque chose semblable à ça :\n\n```js\n(function* f() {\n  yield f;\n})()\n  .next()\n  .value()\n  .next()(\n    // -\u003e { value: [GeneratorFunction: f], done: false }\n\n    // and again\n    function* f() {\n      yield f;\n    }\n  )()\n  .next()\n  .value()\n  .next()\n  .value()\n  .next()(\n    // -\u003e { value: [GeneratorFunction: f], done: false }\n\n    // and again\n    function* f() {\n      yield f;\n    }\n  )()\n  .next()\n  .value()\n  .next()\n  .value()\n  .next()\n  .value()\n  .next();\n// -\u003e { value: [GeneratorFunction: f], done: false }\n\n// and so on\n// …\n```\n\n### 💡 Explication :\n\nPour comprendre pourquoi cela fonctionne ainsi, lisez ces sections de la spécification :\n\n- [**25** Control Abstraction Objects](https://www.ecma-international.org/ecma-262/#sec-control-abstraction-objects)\n- [**25.3** Generator Objects](https://www.ecma-international.org/ecma-262/#sec-generator-objects)\n\n## Une classe de classe\n\nConsidérez cette syntaxe obfusquée :\n\n```js\ntypeof new class {\n  class() {}\n}(); // -\u003e \"object\"\n```\n\nIl semblerait que nous déclarions une classe à l'intérieur d'une classe. Cela devrait être une erreur, cependant, nous obtenons la chaîne `\"object\"`.\n\n### 💡 Explication :\n\nDepuis ECMAScript 5, les _mots clés_ sont autorisés en tant que _noms de propriétés_. Réfléchissez comment vous le feriez pour cet exemple d'objet simple :\n\n```js\nconst foo = {\n  class: function() {}\n};\n```\n\nEt les définitions de méthode abrégée standard d'ES6. Aussi, les classes peuvent être anonymes. Donc, si nous supprimons la partie `: function`, nous obtiendrons :\n\n```js\nclass {\n  class() {}\n}\n```\n\nLe résultat d'une classe par défaut est toujours un objet simple. Et son `typeof` devrait retourner `\"object\"`.\n\nPlus d'infos ici :\n\n- [**14.3** Method Definitions](https://www.ecma-international.org/ecma-262/#sec-method-definitions)\n- [**14.5** Class Definitions](https://www.ecma-international.org/ecma-262/#sec-class-definitions)\n\n## Objets incoercibles\n\nAvec des symboles bien connus, il existe un moyen de se débarrasser de la coercition de type. Examinez l'exemple ci-dessous :\n\n```js\nfunction nonCoercible(val) {\n  if (val == null) {\n    throw TypeError(\n      \"inCoercible ne doit pas être appelé avec null ou undefined\"\n    );\n  }\n\n  const res = Object(val);\n\n  res[Symbol.toPrimitive] = () =\u003e {\n    throw TypeError(\"Tente de transformer un objet incoercible\");\n  };\n\n  return res;\n}\n```\n\nMaintenant, nous pouvons l'utiliser de cette manière :\n\n```js\n// objets\nconst foo = nonCoercible({ foo: \"foo\" });\n\nfoo * 10; // -\u003e TypeError: Tente de transformer un objet incoercible\nfoo + \"evil\"; // -\u003e TypeError: Tente de transformer un objet incoercible\n\n// chaînes\nconst bar = nonCoercible(\"bar\");\n\nbar + \"1\"; // -\u003e TypeError: Tente de transformer un objet incoercible\nbar.toString() + 1; // -\u003e bar1\nbar === \"bar\"; // -\u003e false\nbar.toString() === \"bar\"; // -\u003e true\nbar == \"bar\"; // -\u003e TypeError: Tente de transformer un objet incoercible\n\n// nombres\nconst baz = nonCoercible(1);\n\nbaz == 1; // -\u003e Tente de transformer un objet incoercible\nbaz === 1; // -\u003e false\nbaz.valueOf() === 1; // -\u003e true\n```\n\n### 💡 Explication :\n\n- [A gist by Sergey Rubanov](https://gist.github.com/chicoxyzzy/5dd24608e886adf5444499896dff1197)\n- [**6.1.5.1** Well-Known Symbols](https://www.ecma-international.org/ecma-262/#sec-well-known-symbols)\n\n## Fonctions fléchées complexes\n\nConsidérez l'exemple ci-dessous :\n\n```js\nlet f = () =\u003e 10;\nf(); // -\u003e 10\n```\n\nD'accord, d'accord, mais qu'en est-il de celui-ci :\n\n```js\nlet f = () =\u003e {};\nf(); // -\u003e undefined\n```\n\n### 💡 Explication :\n\nVous pourriez vous attendre à obtenir `{}` au lieu d'`undefined`. C'est dû au fait que les accolades font partie de la syntaxe des fonctions fléchées; `f` renverra donc `undefined`. Il est cependant possible de renvoyer l'objet `{}` directement à partir d'une fonction fléchée en mettant la valeur de retour entre parenthèses :\n\n```js\nlet f = () =\u003e ({});\nf(); // -\u003e {}\n```\n\n## Les fonctions fléchées ne peuvent pas être un constructeur\n\nConsidérez l'exemple ci-dessous :\n\n```js\nlet f = function() {\n  this.a = 1;\n};\nnew f(); // -\u003e { 'a': 1 }\n```\n\nMaintenant, essayez de faire la même chose avec une fonction fléchée :\n\n```js\nlet f = () =\u003e {\n  this.a = 1;\n};\nnew f(); // -\u003e TypeError: f is not a constructor\n```\n\n### 💡 Explication :\n\nLes fonctions fléchées ne peuvent pas être utilisées en tant que constructeurs et produiront une erreur si elles sont utilisées avec `new` parce qu'elles ont un _lexical `this`_ et pas de propriété `prototype`, cela n'aurait donc pas beaucoup de sens.\n\n## `arguments` et fonctions fléchées\n\nConsidérez l'exemple ci-dessous :\n\n```js\nlet f = function() {\n  return arguments;\n};\nf(\"a\"); // -\u003e { '0': 'a' }\n```\n\nMaintenant, essayez de faire la même chose avec une fonction fléchée :\n\n```js\nlet f = () =\u003e arguments;\nf(\"a\"); // -\u003e Uncaught ReferenceError: arguments is not defined\n```\n\n### 💡 Explication :\n\nLes fonctions fléchées sont une version allégée des fonctions standards dans laquelle l'accent est mis sur la taille et le _lexical `this`_. En même temps, les fonctions fléchées ne fournissent pas de liaison pour l'objet `arguments`. Comme alternative valable, utilisez les paramètres `rest` pour obtenir le même résultat :\n\n```js\nlet f = (...args) =\u003e args;\nf(\"a\");\n```\n\n- [Fonctions fléchées](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Fonctions/Fonctions_fl%C3%A9ch%C3%A9es) sur MDN.\n\n## Retour difficile\n\nLa déclaration `return` est compliquée aussi. Considérez ceci :\n\n```js\n(function() {\n  return;\n  {\n    b: 10;\n  }\n})(); // -\u003e undefined\n```\n\n### 💡 Explication :\n\n`return` et l'expression renvoyée doivent être sur la même ligne :\n\n```js\n(function() {\n  return {\n    b: 10\n  };\n})(); // -\u003e { b: 10 }\n```\n\nCela est dû au concept appelé \"Insertion Automatique du Point-Virgule\", qui insère automatiquement des points-virgules à la fin de la plupart des nouvelles lignes. Dans le premier exemple, un point-virgule est inséré entre `return` et l'objet littéral. La fonction renvoie donc `undefined` et l'objet littéral n'est jamais évalué.\n\n- [**11.9.1** Rules of Automatic Semicolon Insertion](https://www.ecma-international.org/ecma-262/#sec-rules-of-automatic-semicolon-insertion)\n- [**13.10** The `return` Statement](https://www.ecma-international.org/ecma-262/#sec-return-statement)\n\n## Chaînage d'affectations sur un objet\n\n```js\nvar foo = { n: 1 };\nvar bar = foo;\n\nfoo.x = foo = { n: 2 };\n\nfoo.x; // -\u003e undefined\nfoo; // -\u003e {n: 2}\nbar; // -\u003e {n: 1, x: {n: 2}}\n```\n\nDe droite à gauche, `{n: 2}` est affecté à `foo`, et le résultat de cette affectation `{n: 2}` est affecté à `foo.x`. C'est pourquoi `bar` retourne `{n: 1, x: {n: 2}}`, puisque `bar` est une référence à `foo`. Mais pourquoi `foo.x` retourne `undefined`, alors que ce n'est pas le cas pour `bar.x` ?\n\n### 💡 Explication :\n\n`foo` et `bar` font référence au même objet `{n: 1}`, et les _lvalues_ sont résolues avant les assignations. `foo = {n: 2}` crée un nouvel objet, et donc `foo` est mis à jour pour référencer ce nouvel objet. L'astuce ici est `foo` dans `foo.x = …`, car une _lvalue_ a été résolue au préalable et fait toujours référence à l'objet précédent `foo = {n: 1}` et donc le met à jour en ajoutant la valeur `x`.\n\nAprès cette chaîne d'assignation, `bar`, quant à lui, fait toujours référence à l'ancien objet `foo`, alors que `foo` fait référence au nouvel objet `{n: 2}`, où `x` n'existe pas.\n\nC'est équivalent à :\n\n```js\nvar foo = { n: 1 };\nvar bar = foo;\n\nfoo = { n: 2 }; // -\u003e {n: 2}\nbar.x = foo; // -\u003e {n: 1, x: {n: 2}}\n// `bar.x` pointe sur l'adresse du nouvel objet `foo`\n// ce n'est pas équivalent à : `bar.x = {n: 2}`\n```\n\n## Accéder aux propriétés d'un objet avec des tableaux\n\n```js\nvar obj = { property: 1 };\nvar array = [\"property\"];\n\nobj[array]; // -\u003e 1\n```\n\nQu'en est-il des tableaux pseudo-multidimensionnels ?\n\n```js\nvar map = {};\nvar x = 1;\nvar y = 2;\nvar z = 3;\n\nmap[[x, y, z]] = true;\nmap[[x + 10, y, z]] = true;\n\nmap[\"1,2,3\"]; // -\u003e true\nmap[\"11,2,3\"]; // -\u003e true\n```\n\n### 💡 Explication :\n\nL'opérateur `[]` convertit l'expression passée en utilisant `toString`. Transformer un tableau composé d'un seul élément vers une chaîne est similaire à transformer l'élément du tableau en chaîne :\n\n```js\n[\"property\"].toString(); // -\u003e 'property'\n```\n\n## Opérateurs `null` et relationnels\n\n```js\nnull \u003e 0; // false\nnull == 0; // false\n\nnull \u003e= 0; // true\n```\n\n### 💡 Explication :\n\nEn bref, si `null \u003c 0` est `false`, alors `null \u003e= 0` est `true`. Lisez une explication détaillée [ici](https://blog.campvanilla.com/javascript-the-curious-case-of-null-0-7b131644e274).\n\n## `Number.toFixed()` affiche différents nombres\n\n`Number.toFixed()` peut se comporter étrangement selon le navigateur utilisé. Voir cet exemple :\n\n```js\n(0.7875).toFixed(3);\n// Firefox: -\u003e 0.787\n// Chrome: -\u003e 0.787\n// IE11: -\u003e 0.788\n(0.7876).toFixed(3);\n// Firefox: -\u003e 0.788\n// Chrome: -\u003e 0.788\n// IE11: -\u003e 0.788\n```\n\n### 💡 Explication :\n\nAlors que votre premier instinct peut être que IE11 a correct et que Firefox et Chrome ont faux, la réalité est que Firefox et Chrome obéissent plus directement aux normes relatives aux nombres (IEEE-754 Floating Point), alors qu'IE11 les désobéit minutieusement dans (ce qui est probablement) un effort de donner des résultats plus clairs.\n\nVous pouvez voir pourquoi cela se produit avec quelques tests rapides :\n\n```js\n// Confirme le résultat curieux d'arrondir `5` vers le bas\n(0.7875).toFixed(3); // -\u003e 0.787\n// Il semble que ce soit juste `5` lorsque vous développez\n//  les limites de la précision de flottement de 64 bits (double précision)\n(0.7875).toFixed(14); // -\u003e 0.78750000000000\n// Mais que se passe-t-il si vous allez au-delà de la limite ?\n(0.7875).toFixed(20); // -\u003e 0.78749999999999997780\n```\n\nLes nombres à virgule flottante ne sont pas stockés sous forme de liste de chiffres décimaux en interne, mais par le biais d'une méthodologie plus complexe qui produit de minuscules inexactitudes qui sont généralement arrondies par des appels à `toString` ou des appels similaires, mais qui sont réellement présentes en interne.\n\nDans ce cas, le `5` sur la fin était en réalité une fraction extrêmement petite, en dessous d'un vrai `5`. Si vous arrondissez à une longueur raisonnable, vous obtenez un `5`… mais ce n'est en réalité pas un `5` en interne.\n\nCeci étant dit, IE11 rapportera la valeur entrée uniquement avec des zéros ajoutés à la fin, même dans le cas de `toFixed(20)`, car cela semble forcer la valeur arrondie pour réduire les problèmes liées aux limites matérielles.\n\nVoir pour référence `NOTE 2` sur la définition de ECMA-262 pour `toFixed`.\n\n- [**20.1.3.3** Number.prototype.toFixed (`fractionDigits`)](https://www.ecma-international.org/ecma-262//#sec-number.prototype.tofixed)\n\n## `Math.max()` est moins que `Math.min()`\n\n```js\nMath.min(1, 4, 7, 2); // -\u003e 1\nMath.max(1, 4, 7, 2); // -\u003e 7\nMath.min(); // -\u003e Infinity\nMath.max(); // -\u003e -Infinity\nMath.min() \u003e Math.max(); // -\u003e true\n```\n\n### 💡 Explication :\n\n- [Why is Math.max() less than Math.min()?](https://charlieharvey.org.uk/page/why_math_max_is_less_than_math_min) par Charlie Harvey.\n\n## Comparer `null` à `0`\n\nLes expressions suivantes semblent introduire une contradiction :\n\n```js\nnull == 0; // -\u003e false\nnull \u003e 0; // -\u003e false\nnull \u003e= 0; // -\u003e true\n```\n\nComment `null` peut-il être ni égal ni supérieur à `0`, si `null \u003e= 0` est en fait `true` ? (Ceci fonctionne de la même manière avec inférieur ou égal à (`\u003c=`).)\n\n### 💡 Explication :\n\nLes méthodes d'évaluation de ces trois expressions sont toutes différentes et sont responsables de la production de ce comportement inattendu.\n\nPremièrement, la comparaison d'égalité abstraite `null == 0`. Normalement, si cet opérateur ne peut pas comparer correctement les valeurs d'un côté comme de l'autre, il convertit les deux en nombres et compare ensuite les nombres. Alors, vous pouvez vous attendre au comportement suivant :\n\n```js\n// Ce n'est pas ce qui se passe\n(null == 0 + null) == +0;\n0 == 0;\ntrue;\n```\n\nCependant, suite à une lecture attentive de la spécification, la transformation du nombre n'a pas lieu sur un côté qui est `null` ou `undefined`. Par conséquent, si vous avez `null` sur un des deux côté du signe égal, l'autre côté doit être `null` ou `undefined` pour que l'expression retourne `true`. Comme ce n'est pas le cas, `false` est renvoyé.\n\nEnsuite, la comparaison relationnelle `null \u003e 0`. L'algorithme ici, contrairement à celui de l'opérateur d'égalité abstraite, _va_ convertir `null` à un nombre. Donc, nous obtenons ce comportement :\n\n```js\nnull \u003e 0\n+null = +0\n0 \u003e 0\nfalse\n```\n\nFinalement, la comparaison relationnelle `null \u003e= 0`. Vous pourriez soutenir que cette expression devrait être le résultat de `null \u003e 0 || null == 0`; si tel était le cas, les résultats ci-dessus signifieraient que ceci serait aussi `false`. Toutefois, l'opérateur `\u003e=` fonctionne d'une manière très différente, qui est simplement d'utiliser le contraire de l'opérateur `\u003c`. Parce que notre exemple ci-dessus, utilisant l'opérateur supérieur à, s'applique également à l'opérateur inférieur à, cela signifie que cette expression est réellement évaluée de la manière suivante :\n\n```js\nnull \u003e= 0;\n!(null \u003c 0);\n!(+null \u003c +0);\n!(0 \u003c 0);\n!false;\ntrue;\n```\n\n- [**7.2.12** Abstract Relational Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-relational-comparison)\n- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)\n\n## Même redéclaration d'une variable\n\nJavaScript autorise la redéclaration de variables :\n\n```js\na;\na;\n// Ceci est aussi valide\na, a;\n```\n\nEt ça fonctionne aussi en mode `strict` :\n\n```js\nvar a, a, a;\nvar a;\nvar a;\n```\n\n### 💡 Explication :\n\nToutes les définitions fusionnent en une seule définition.\n\n- [**13.3.2** Variable Statement](https://www.ecma-international.org/ecma-262/#sec-variable-statement)\n\n## Comportement par défaut d'`Array.prototype.sort()`\n\nImaginez que vous ayez besoin de trier un tableau composé de nombres.\n\n```\n[ 10, 1, 3 ].sort() // -\u003e [ 1, 10, 3 ]\n```\n\n### 💡 Explication :\n\nL'ordre de tri par défaut est construit lors de la transformation des éléments en chaînes, puis en comparant leurs séquences de valeurs unitaires sur le jeu de caractères UTF-16.\n\n- [**22.1.3.25** Array.prototype.sort ( comparefn )](https://www.ecma-international.org/ecma-262/#sec-array.prototype.sort)\n\n### Indice\n\nPassez `comparefn` si vous essayez de trier n'importe quoi d'autre qu'une chaîne.\n\n```\n[ 10, 1, 3 ].sort((a, b) =\u003e a - b) // -\u003e [ 1, 3, 10 ]\n```\n\n# 📚 Autres ressources\n\n- [wtfjs.com](http://wtfjs.com/) — une collection d'irrégularités spéciales très particulières, d'incohérences et de moments terriblement non intuitifs pour le langage du Web.\n- [Wat](https://www.destroyallsoftware.com/talks/wat) — Un discours éclair de Gary Bernhardt de CodeMash 2012.\n- [What the... JavaScript?](https://www.youtube.com/watch?v=2pL28CcEijU) — Kyle Simpsons parle des tentatives de Forward 2 pour \"sortir de l'absurdité\" du JavaScript. Il veut vous aider à produire un code plus propre, plus élégant et plus lisible, puis inspirer les gens à contribuer à la communauté open-source.\n\n# 🎓 Licence\n\n[![CC 4.0][license-image]][license-url]\n\n\u0026copy; [Denys Dovhan](http://denysdovhan.com)\n\n[license-url]: http://www.wtfpl.net\n[license-image]: https://img.shields.io/badge/License-WTFPL%202.0-lightgrey.svg?style=flat-square\n[npm-url]: https://npmjs.org/package/wtfjs\n[npm-image]: https://img.shields.io/npm/v/wtfjs.svg?style=flat-square\n","funding_links":["https://github.com/sponsors/denysdovhan","https://patreon.com/denysdovhan","buymeacoffee.com/denysdovhan"],"categories":["JavaScript","Awesome Github Repositorys","Javascript","Uncategorized","Web Development","[Book](#book)","Front end","前端开发框架及项目","学习相关","ES6","Talks","learning","JavaScript (485)","JS","Programming languages","\u003e 10K ⭐️"],"sub_categories":["Uncategorized","JavaScript","其他_文本生成、文本对话","React Components","GRID CSS e FLEXBOX"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenysdovhan%2Fwtfjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdenysdovhan%2Fwtfjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenysdovhan%2Fwtfjs/lists"}