Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/denysdovhan/wtfjs

🤪 A list of funny and tricky JavaScript examples
https://github.com/denysdovhan/wtfjs

book handbook javascript js learning notes specification wtf

Last synced: 6 days ago
JSON representation

🤪 A list of funny and tricky JavaScript examples

Awesome Lists containing this project

README

        

# What the f\*ck JavaScript?

[![WTFPL 2.0][license-image]][license-url]
[![NPM version][npm-image]][npm-url]

> Une liste d'exemples JavaScript drôles et délicats

Le JavaScript est un langage formidable! Il possède une syntaxe simple, un grand écosystème et, le plus important de tout, une immense communauté.

En 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.

L'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):

[![dotJS 2012 - Brian Leroux - WTFJS](https://img.youtube.com/vi/et8xNAc2ic8/0.jpg)](https://www.youtube.com/watch?v=et8xNAc2ic8)

# Le Manuscript sous forme de paquet Node

Vous pouvez installer ce manuel en utilisant `npm`. Pour cela, il suffit d'exécuter :

```
$ npm install -g wtfjs
```

Vous devriez pouvoir ensuite utiliser `wtfjs` en ligne de commande. Cela ouvrira le manuel dans votre terminal. Sinon, vous pouvez continuer à lire ici tout simplement.

La source du _package_ est disponible ici:

# Traductions

Actuellement, il existe des traductions de ** wtfjs ** pour les langues suivantes :

- [中文版](./README-zh-cn.md)
- [Français](./README-fr-fr.md)

[**Demander une autre traduction**][tr-request]

[tr-request]: https://github.com/denysdovhan/wtfjs/issues/new?title=Translation%20Request:%20%5BPlease%20enter%20language%20here%5D&body=I%20am%20able%20to%20translate%20this%20language%20%5Byes/no%5D

# Table of Contents

- [💪🏻 Motivation](#-motivation)
- [✍🏻 Notation](#-notation)
- [👀 Exemples](#-exemples)
- [`[]` est égal à `![]`](#-est-%C3%A9gal-%C3%A0-)
- [`true` n'est pas égal à `![]`, mais pas égal à `[]` aussi](#true-nest-pas-%C3%A9gal-%C3%A0--mais-pas-%C3%A9gal-%C3%A0--aussi)
- [true est faux](#true-est-faux)
- [baNaNa](#banana)
- [`NaN` n'est pas un `NaN`](#nan-nest-pas-un-nan)
- [C'est un échec](#cest-un-%C3%A9chec)
- [`[]` est truthy, mais pas `true`](#-est-truthy-mais-pas-true)
- [`null` est falsy, mais pas `faux`](#null-est-falsy-mais-pas-faux)
- [`document.all` est un objet, mais il est `undefined`](#documentall-est-un-objet-mais-il-est-undefined)
- [La valeur minimale est supérieure à zéro](#la-valeur-minimale-est-sup%C3%A9rieure-%C3%A0-z%C3%A9ro)
- [Fonction n'est pas une fonction](#fonction-nest-pas-une-fonction)
- [Ajout de tableaux](#ajout-de-tableaux)
- [Les virgules finales dans un tableau](#les-virgules-finales-dans-un-tableau)
- [L'égalité des tableaux est un monstre](#l%C3%A9galit%C3%A9-des-tableaux-est-un-monstre)
- [`undefined` et `Number`](#undefined-et-number)
- [`parseInt` est un méchant](#parseint-est-un-m%C3%A9chant)
- [Math avec `true` et `false`](#math-avec-true-et-false)
- [Les commentaires HTML sont valides en JavaScript](#les-commentaires-html-sont-valides-en-javascript)
- [`NaN` n'est ~~pas~~ un nombre](#nan-nest-pas-un-nombre)
- [`[]` et `null` sont des objets](#-et-null-sont-des-objets)
- [Nombres magiquement croissant](#nombres-magiquement-croissant)
- [Précision de `0.1 + 0.2`](#pr%C3%A9cision-de-01--02)
- [Patching de numéros](#patching-de-num%C3%A9ros)
- [Comparaison de trois nombres](#comparaison-de-trois-nombres)
- [Math drôle](#math-dr%C3%B4le)
- [Addition de RegExps](#addition-de-regexps)
- [Les chaînes ne sont pas des instances de `String`](#les-cha%C3%AEnes-ne-sont-pas-des-instances-de-string)
- [Appeler des fonctions avec des caractères accent grave](#appeler-des-fonctions-avec-des-caract%C3%A8res-accent-grave)
- [Call call call](#call-call-call)
- [Une propriété `constructor`](#une-propri%C3%A9t%C3%A9-constructor)
- [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)
- [Accéder aux prototypes avec `__proto__`](#acc%C3%A9der-aux-prototypes-avec-__proto__)
- [`` `${{Object}}` ``](#-object-)
- [Déstructuration avec des valeurs par défaut](#d%C3%A9structuration-avec-des-valeurs-par-d%C3%A9faut)
- [Points et propagation](#points-et-propagation)
- [Étiquettes](#%C3%A9tiquettes)
- [Étiquettes imbriquées](#%C3%A9tiquettes-imbriqu%C3%A9es)
- [`Try...catch` insidieux](#trycatch-insidieux)
- [Est-ce un héritage multiple ?](#est-ce-un-h%C3%A9ritage-multiple-)
- [Un générateur qui se `yield` lui-même](#un-g%C3%A9n%C3%A9rateur-qui-se-yield-lui-m%C3%AAme)
- [Une classe de classe](#une-classe-de-classe)
- [Objets incoercibles](#objets-incoercibles)
- [Fonctions fléchées complexes](#fonctions-fl%C3%A9ch%C3%A9es-complexes)
- [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)
- [`arguments` et fonctions fléchées](#arguments-et-fonctions-fl%C3%A9ch%C3%A9es)
- [Retour difficile](#retour-difficile)
- [Chaînage d'affectations sur un objet](#cha%C3%AEnage-daffectations-sur-un-objet)
- [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)
- [Opérateurs `null` et relationnels](#op%C3%A9rateurs-null-et-relationnels)
- [`Number.toFixed()` affiche différents nombres](#numbertofixed-affiche-diff%C3%A9rents-nombres)
- [`Math.max()` est moins que `Math.min()`](#mathmax-est-moins-que-mathmin)
- [Comparer `null` à `0`](#comparer-null-%C3%A0-0)
- [Même redéclaration d'une variable](#m%C3%AAme-red%C3%A9claration-dune-variable)
- [Comportement par défaut d'`Array.prototype.sort()`](#comportement-par-d%C3%A9faut-darrayprototypesort)
- [📚 Autres ressources](#-autres-ressources)
- [🎓 Licence](#-licence)

# 💪🏻 Motivation

> Juste pour le fun
>
> — _[**“Just for Fun: The Story of an Accidental Revolutionary”**](https://archive.org/details/justforfun00linu), Linus Torvalds_

L'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.

Si 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.

Si 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.

Dans tous les cas, lisez ce qui suit. Vous y trouverez probablement quelque chose de nouveau !

# ✍🏻 Notation

**`// ->`** est utilisé pour afficher le résultat d'une expression. Par exemple :

```js
1 + 1; // -> 2
```

**`// >`** définit le résultat de `console.log` ou tout autre sortie. Par exemple :

```js
console.log("hello, world!"); // > hello, world!
```

**`//`** indique un commentaire utilisé pour donner des explications. Par exemple :

```js
// Assigner une fonction la constant foo
const foo = function() {};
```

# 👀 Exemples

## `[]` est égal à `![]`

Tableau est égal à pas tableau

```js
[] == ![]; // -> true
```

### 💡 Explication :

L'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`.

Les 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.

Voici comment cette expression se simplifie:

```js
+[] == +![];
0 == +false;
0 == 0;
true;
```

Voir aussi [`[]` est truthy, mais pas `true`](#-est-truthy-mais-pas-true).

- [**12.5.9** Logical NOT Operator (`!`)](https://www.ecma-international.org/ecma-262/#sec-logical-not-operator)
- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)

## `true` n'est pas égal à `![]`, mais pas égal à `[]` aussi

Un tableau n'est pas égal à `true`, tout comme pas tableau. Un tableau est égal à `false`, pas tableau est égal à `false` aussi :

```js
true == []; // -> false
true == ![]; // -> false

false == []; // -> true
false == ![]; // -> true
```

### 💡 Explication :

```js
true == []; // -> false
true == ![]; // -> false

// Selon la spécification

true == []; // -> false

toNumber(true); // -> 1
toNumber([]); // -> 0

1 == 0; // -> false

true == ![]; // -> false

![]; // -> false

true == false; // -> false
```

```js
false == []; // -> true
false == ![]; // -> true

// Selon la spécification

false == []; // -> true

toNumber(false); // -> 0
toNumber([]); // -> 0

0 == 0; // -> true

false == ![]; // -> false

![]; // -> false

false == false; // -> true
```

- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)

## true est faux

```js
!!"false" == !!"true"; // -> true
!!"false" === !!"true"; // -> true
```

### 💡 Explication :

Considérez ceci étape par étape :

```js
// `true` est 'truthy' et est représenté par la valeur 1 (nombre), 'true' sous forme de chaîne est NaN.
true == "true"; // -> false
false == "false"; // -> false

// 'false' n'est pas une chaîne vide, donc c'est une valeur `truthy`
!!"false"; // -> true
!!"true"; // -> true
```

- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)

## baNaNa

```js
"b" + "a" + +"a" + "a"; // -> 'baNaNa'
```

Ceci est une blague "old school" en JavaScript, mais remasterisée. Voici l'originale :

```js
"foo" + +"bar"; // -> 'fooNaN'
```

### 💡 Explication :

L'expression est évaluée comme `'foo' + (+'bar')`, ce qui convertit `'bar'` à `NaN`.

- [**12.8.3** The Addition Operator (`+`)](https://www.ecma-international.org/ecma-262/#sec-addition-operator-plus)
- [12.5.6 Unary + Operator](https://www.ecma-international.org/ecma-262/#sec-unary-plus-operator)

## `NaN` n'est pas un `NaN`

```js
NaN === NaN; // -> false
```

### 💡 Explication :

La spécification définit strictement la logique derrière ce comportement :

> 1. Si `Type(x)` est différent de `Type(y)`, retourne **false**.
> 2. Si `Type(x)` est `Number`, alors
> 1. Si `x` est **NaN**, retourne **false**.
> 2. Si `y` est **NaN**, retourne **false**.
> 3. … … …
>
> — [**7.2.14** Strict Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-strict-equality-comparison)

Sur la base de la définition de `NaN` de l'IEEE :

> 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.
>
> — [“What is the rationale for all comparisons returning false for IEEE754 NaN values?”](https://stackoverflow.com/questions/1565164/1573715#1573715) sur StackOverflow.

## C'est un échec

Vous ne le croiriez pas, mais …

```js
(![] + [])[+[]] +
(![] + [])[+!+[]] +
([![]] + [][[]])[+!+[] + [+[]]] +
(![] + [])[!+[] + !+[]];
// -> 'fail'
```

### 💡 Explication :

En brisant cette masse de symboles en morceaux, nous remarquons que le schéma suivant se produit souvent :

```js
![] + []; // -> 'false'
![]; // -> false
```

Donc, nous essayons d'ajouter `[]` à `false`, mais en raison d'un certain nombre d'appels de fonctions internes (`binary + Operator` -> `ToPrimitive` -> `[[DefaultValue]]`), nous finissons par convertir l'opérande de droite en chaîne :

```js
![] + [].toString(); // 'false'
```

En considérant une chaîne comme un tableau, nous pouvons accéder à son premier caractère via `[0]` :

```js
"false"[0]; // -> 'f'
```

Le 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]`.

## `[]` est truthy, mais pas `true`

Un tableau est une valeur `truthy`, mais n'est pas égal à `true`.

```js
!![] // -> true
[] == true // -> false
```

### 💡 Explication :

Voici des liens vers les sections correspondantes de la spécification ECMA-262 :

- [**12.5.9** Logical NOT Operator (`!`)](https://www.ecma-international.org/ecma-262/#sec-logical-not-operator)
- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)

## `null` est falsy, mais pas `faux`

Malgré le fait que `null` soit une valeur `falsy`, elle n'est pas égale à `false`.

```js
0 == false; // -> true
"" == false; // -> true
```

### 💡 Explication :

L'explication est la même que pour l'exemple précédent. Voici le lien correspondant :

- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)

## `document.all` est un objet, mais il est `undefined`

> ⚠️ Ceci fait partie de la Browser API et ne fonctionnera pas dans un environnement Node.js ⚠️

Malgré 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`.

```js
document.all instanceof Object; // -> true
typeof document.all; // -> 'undefined'
```

En même temps, `document.all` n'est pas égal à `undefined`.

```js
document.all === undefined; // -> false
document.all === null; // -> false
```

Mais, parallèlement :

```js
document.all == null; // -> true
```

### 💡 Explication :

> `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.
> 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.
>
> — [“Obsolete features - document.all”](https://html.spec.whatwg.org/multipage/obsolete.html#dom-document-all) sur WhatWG - HTML spec.
> — [“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 & Grammar.

## La valeur minimale est supérieure à zéro

`Number.MIN_VALUE` est le plus petit nombre, qui est supérieur à zéro :

```js
Number.MIN_VALUE > 0; // -> true
```

### 💡 Explication :

> `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.
>
> Maintenant, la plus petite valeur globale est `Number.NEGATIVE_INFINITY`, bien que cette dernière ne soit pas vraiment numérique au sens strict.
>
> — [“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

- [**20.1.2.9** Number.MIN_VALUE](https://www.ecma-international.org/ecma-262/#sec-number.min_value)

## Fonction n'est pas une fonction

> ⚠️ Une erreur présente dans la v5.5 (V8) ou inférieure de Node.js (Node.js <=7) ⚠️

Vous êtes tous au courant de l'irritant _undefined is not a function_, mais qu'en est-il de ceci :

```js
// Déclare une classe qui _extends_ `null`
class Foo extends null {}
// -> [Function: Foo]

new Foo() instanceof null;
// > TypeError: function is not a function
// > at … … …
```

### 💡 Explication :

Ceci 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.

## Ajout de tableaux

Et si vous essayiez d'additionner deux tableaux ?

```js
[1, 2, 3] + [4, 5, 6]; // -> '1,2,34,5,6'
```

### 💡 Explication :

C'est la concaténation ! Etape par étape, ça ressemble à ceci :

```js
[1, 2, 3] +
[4, 5, 6][
// appelle toString()
(1, 2, 3)
].toString() +
[4, 5, 6].toString();
// concaténation
"1,2,3" + "4,5,6";
// ->
("1,2,34,5,6");
```

## Les virgules finales dans un tableau

Vous avez créé un tableau avec 4 éléments vides. Malgré tout, vous obtiendrez un tableau avec seulement trois éléments, à cause des virgules finales.

```js
let a = [, , ,];
a.length; // -> 3
a.toString(); // -> ',,'
```

### 💡 Explication :

> 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.
>
> — [Virgules finales (trailing commas)](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Virgules_finales) sur MDN.

## L'égalité des tableaux est un monstre

En JavaScript, l'égalité des tableaux est un monstre, comme vous pouvez le voir ci-dessous :

```js
[] == '' // -> true
[] == 0 // -> true
[''] == '' // -> true
[0] == 0 // -> true
[0] == '' // -> false
[''] == 0 // -> true

[null] == '' // true
[null] == 0 // true
[undefined] == '' // true
[undefined] == 0 // true

[[]] == 0 // true
[[]] == '' // true

[[[[[[]]]]]] == '' // true
[[[[[[]]]]]] == 0 // true

[[[[[[ null ]]]]]] == 0 // true
[[[[[[ null ]]]]]] == '' // true

[[[[[[ undefined ]]]]]] == 0 // true
[[[[[[ undefined ]]]]]] == '' // true
```

### 💡 Explication :

Vous 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.

## `undefined` et `Number`

Si 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.

```js
Number(); // -> 0
Number(undefined); // -> NaN
```

### 💡 Explication :

Selon la spécification :

1. Si aucun argument n'a été passé lors de l'appel de la fonction, `n` est `+0`.
2. Sinon, `n` est ? `ToNumber(value)`.
3. Dans le cas d'`undefined`, `ToNumber(undefined)` doit retourner `NaN`.

Voici les sections correspondantes :

- [**20.1.1** The Number Constructor](https://www.ecma-international.org/ecma-262/#sec-number-constructor)
- [**7.1.3** ToNumber(`argument`)](https://www.ecma-international.org/ecma-262/#sec-tonumber)

## `parseInt` est un méchant

`parseInt` est célèbre pour ses bizarreries:

```js
parseInt("f*ck"); // -> NaN
parseInt("f*ck", 16); // -> 15
```

**💡 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`.

Analyser `Infinity` comme entier est quelque chose…

```js
//
parseInt("Infinity", 10); // -> NaN
// ...
parseInt("Infinity", 18); // -> NaN...
parseInt("Infinity", 19); // -> 18
// ...
parseInt("Infinity", 23); // -> 18...
parseInt("Infinity", 24); // -> 151176378
// ...
parseInt("Infinity", 29); // -> 385849803
parseInt("Infinity", 30); // -> 13693557269
// ...
parseInt("Infinity", 34); // -> 28872273981
parseInt("Infinity", 35); // -> 1201203301724
parseInt("Infinity", 36); // -> 1461559270678...
parseInt("Infinity", 37); // -> NaN
```

Soyez prudent avec l'analyse de `null` aussi :

```js
parseInt(null, 24); // -> 23
```

**💡 Explication :**

> `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é.
>
> — [“parseInt(null, 24) === 23… wait, what?”](https://stackoverflow.com/questions/6459758/parseintnull-24-23-wait-what) sur StackOverflow.

N'oubliez pas les octaux:

```js
parseInt("06"); // 6
parseInt("08"); // 8 si support ECMAScript 5
parseInt("08"); // 0 si pas support ECMAScript 5
```

**💡 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`.

`parseInt` convertit toujours une entrée en chaîne :

```js
parseInt({ toString: () => 2, valueOf: () => 1 }); // -> 2
Number({ toString: () => 2, valueOf: () => 1 }); // -> 1
```

Soyez prudent lors d'analyse de valeurs en virgule flottante :

```js
parseInt(0.000001); // -> 0
parseInt(0.0000001); // -> 1
parseInt(1 / 1999999); // -> 5
```

**💡 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`.

## Math avec `true` et `false`

Faisons des maths :

```js
true +
true(
// -> 2
true + true
) *
(true + true) -
true; // -> 3
```

Hmmm… 🤔

### 💡 Explication :

Avec le constructeur `Number`, nous pouvons forcer les valeurs aux nombres. Il est assez évident que `true` sera forcé à `1`.

```js
Number(true); // -> 1
```

L'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 :

```js
+true; // -> 1
```

Lorsque vous effectuez une addition ou une multiplication, la méthode `ToNumber` est appelée. Selon la spécification, cette méthode retourne :

> Si `argument` est **true**, retourne **1**. Si `argument` est **false**, retourne **+0**.

C'est pourquoi nous pouvons ajouter des valeurs booléennes en tant que nombres réguliers et obtenir des résultats corrects.

Les sections correspondantes :

- [**12.5.6** Unary `+` Operator](https://www.ecma-international.org/ecma-262/#sec-unary-plus-operator)
- [**12.8.3** The Addition Operator (`+`)](https://www.ecma-international.org/ecma-262/#sec-addition-operator-plus)
- [**7.1.3** ToNumber(`argument`)](https://www.ecma-international.org/ecma-262/#sec-tonumber)

## Les commentaires HTML sont valides en JavaScript

Vous serez impressionné, mais `