Showing preview only (593K chars total). Download the full file or copy to clipboard to get everything.
Repository: denysdovhan/wtfjs
Branch: master
Commit: e92b871953d0
Files: 23
Total size: 575.4 KB
Directory structure:
gitextract_53_zsuvp/
├── .editorconfig
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ └── new-example.md
│ ├── PULL_REQUEST_TEMPLATE/
│ │ ├── new_example.md
│ │ └── translation.md
│ ├── dependabot.yml
│ └── workflows/
│ ├── release.yml
│ └── validate.yml
├── .gitignore
├── .husky/
│ └── pre-commit
├── CONTRIBUTING.md
├── LICENSE
├── README-fr-fr.md
├── README-hi.md
├── README-it-it.md
├── README-kr.md
├── README-pl-pl.md
├── README-pt-br.md
├── README-si.md
├── README-zh-cn.md
├── README.md
├── package.json
└── wtfjs.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[package.json]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
================================================
FILE: .github/FUNDING.yml
================================================
github: denysdovhan
patreon: denysdovhan
custom: [buymeacoffee.com/denysdovhan]
================================================
FILE: .github/ISSUE_TEMPLATE/new-example.md
================================================
---
name: New Example
about: A new example for wtfjs collection
title: ''
labels: new-example
assignees: ''
---
<!--
**New examples will be accepted only if they have an explanation.** Preferably, the explanation should contain links to the specification, blog posts, forum publications.
If you don't know why an example works the way it works, ask for help on [the discussion forum](https://github.com/denysdovhan/wtfjs/discussions).
Issues without explanations will be closed.
-->
================================================
FILE: .github/PULL_REQUEST_TEMPLATE/new_example.md
================================================
<!--
**New examples will be accepted only if they have an explanation.** Preferably, the explanation should contain links to the specification, blog posts, forum publications.
If you don't know why an example works the way it works, ask for help on [the discussion forum](https://github.com/denysdovhan/wtfjs/discussions).
Issues without explanations will be closed.
-->
================================================
FILE: .github/PULL_REQUEST_TEMPLATE/translation.md
================================================
<!--
**If you want a translation, please, make one.** Issues with translation requests will be closed in favor of PRs.
Before sending a PR with translation, please check if there are any existing PRs with translation to your language.
**You have to find someone who speaks your language natively to read, check and verify your translation.** That's how we are trying to prevent typos and mistakes.
-->
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
# Maintain dependencies for npm
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 10
================================================
FILE: .github/workflows/release.yml
================================================
name: Release
on:
push:
branches:
- master
jobs:
release:
name: Prepare release
runs-on: ubuntu-latest
steps:
- name: 🛑 Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.9.1
- name: ⬇️ Checkout Repo
uses: actions/checkout@v3
- name: ⬢ Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "*"
cache: npm
- name: 📦 Install Packages
run: npm ci
- name: 📝 Generate TOC
run: npm run toc
- name: 💅 Format files
run: npm run format
- name: 🚀 Release
run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
================================================
FILE: .github/workflows/validate.yml
================================================
name: Validate
on:
push:
pull_request:
jobs:
validate:
name: Validate
runs-on: ubuntu-latest
steps:
- name: 🛑 Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.9.1
- name: ⬇️ Checkout Repo
uses: actions/checkout@v3
- name: ⬢ Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "*"
cache: npm
- name: 📦 Install Packages
run: npm ci
- name: 💅 Check formatting
run: npm test
================================================
FILE: .gitignore
================================================
.DS_Store
node_modules
npm-debug.log
================================================
FILE: .husky/pre-commit
================================================
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing Guidelines
This guide will help you to contribute to this project smoothly. Please, read carefully to make your contribution process easier.
Usually, this project has two types of contributions: _new examples_ and _translations_.
## New Examples
**New examples will be accepted only if they have an explanation.** Preferably, the explanation should contain links to the specification, blog posts, forum publications.
If you don't know why an example works the way it works, ask for help on [the discussion forum](https://github.com/denysdovhan/wtfjs/discussions).
Issues without explanations will be closed.
## Translations
**If you want a translation, please, make one.** Issues with translation requests will be closed in favor of PRs.
Before sending a PR with translation, please check if there are any existing PRs with translation to your language.
**You have to find someone who speaks your language natively to read, check and verify your translation.** That's how we are trying to prevent typos and mistakes.
---
Thanks for understanding, have fun!
================================================
FILE: LICENSE
================================================
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2017 Denys Dovhan
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
================================================
FILE: README-fr-fr.md
================================================
# 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):
[](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: <https://github.com/denysdovhan/wtfjs>
# 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
<!-- prettier-ignore-start -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
# 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)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- prettier-ignore-end -->
# 💪🏻 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 `<!--` (connu sous le nom de commentaire HTML) est aussi valide comme commentaire en JavaScript.
```js
// commentaire valide
<!-- commentaire valide aussi
```
### 💡 Explication :
Impressionné ? Les commentaires de type HTML étaient à la base destinés à permettre aux navigateurs ne comprenant pas la balise `<script>` 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 `<script>`.
- [**B.1.3** HTML-like Comments](https://www.ecma-international.org/ecma-262/#sec-html-like-comments)
## `NaN` n'est ~~pas~~ un nombre
`typeof` `NaN` est un `'number'` :
```js
typeof NaN; // -> 'number'
```
### 💡 Explication :
Explications sur le fonctionnement des opérateurs `typeof` et `instanceof` :
- [**12.5.5** The `typeof` Operator](https://www.ecma-international.org/ecma-262/#sec-typeof-operator)
- [**12.10.4** Runtime Semantics: InstanceofOperator(`O`,`C`)](https://www.ecma-international.org/ecma-262/#sec-instanceofoperator)
## `[]` et `null` sont des objets
```js
typeof []; // -> "object"
typeof null; // -> "object"
// however
null instanceof Object; // false
```
### 💡 Explication :
Le comportement de l'opérateur `typeof` est défini dans la section suivante de la spécification :
- [**12.5.5** The `typeof` Operator](https://www.ecma-international.org/ecma-262/#sec-typeof-operator)
Selon 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"`.
En revanche, vous pouvez vérifier le type d'un objet en utilisant la méthode `toString`.
```js
Object.prototype.toString.call([]);
// -> '[object Array]'
Object.prototype.toString.call(new Date());
// -> '[object Date]'
Object.prototype.toString.call(null);
// -> '[object Null]'
```
## Nombres magiquement croissant
```js
999999999999999; // -> 999999999999999
9999999999999999; // -> 10000000000000000
10000000000000000; // -> 10000000000000000
10000000000000000 + 1; // -> 10000000000000000
10000000000000000 + 1.1; // -> 10000000000000002
```
### 💡 Explication :
Ceci 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 :
- [**6.1.6** The Number Type](https://www.ecma-international.org/ecma-262/#sec-ecmascript-language-types-number-type)
- [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) sur Wikipedia
## Précision de `0.1 + 0.2`
Une blague bien connue. L'ajout de `0.1` et de `0.2` est mortellement précis :
```js
0.1 +
0.2(
// -> 0.30000000000000004
0.1 + 0.2
) ===
0.3; // -> false
```
### 💡 Explication :
La réponse à la question [”Is floating point math broken?”](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) sur StackOverflow:
> 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.
Le 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.
## Patching de numéros
Vous pouvez ajouter vos propres méthodes pour encapsuler des objets comme `Number` ou `String`.
```js
Number.prototype.isOne = function() {
return Number(this) === 1;
};
(1.0).isOne(); // -> true
(1).isOne(); // -> true
(2.0)
.isOne()(
// -> false
7
)
.isOne(); // -> false
```
### 💡 Explication :
De 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` :
- [**20.1** Number Objects](https://www.ecma-international.org/ecma-262/#sec-number-objects)
## Comparaison de trois nombres
```js
1 < 2 < 3; // -> true
3 > 2 > 1; // -> false
```
### 💡 Explication :
Pourquoi 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 :
```js
1 < 2 < 3; // 1 < 2 -> true
true < 3; // true -> 1
1 < 3; // -> true
3 > 2 > 1; // 3 > 2 -> true
true > 1; // true -> 1
1 > 1; // -> false
```
Nous pouvons résoudre ce problème avec _l'opérateur Supérieur ou égal à (`>=`)_ :
```js
3 > 2 >= 1; // true
```
En savoir plus sur les opérateurs relationnels dans la spécification :
- [**12.10** Relational Operators](https://www.ecma-international.org/ecma-262/#sec-relational-operators)
## Math drôle
Souvent, les résultats d'opérations arithmétiques en JavaScript peuvent être assez inattendus. Considérez ces exemples :
```js
3 - 1 // -> 2
3 + 1 // -> 4
'3' - 1 // -> 2
'3' + 1 // -> '31'
'' + '' // -> ''
[] + [] // -> ''
{} + [] // -> 0
[] + {} // -> '[object Object]'
{} + {} // -> '[object Object][object Object]'
'222' - -'111' // -> 333
[4] * [4] // -> 16
[] * [] // -> 0
[4, 4] * [4, 4] // NaN
```
### 💡 Explication :
Que se passe-t-il dans les quatre premiers exemples ? Voici un petit tableau pour comprendre les additions en JavaScript :
```
Nombre + Nombre -> addition
Booléen + Nombre -> addition
Booléen + Booléen -> addition
Nombre + Chaîne -> concaténation
Chaîne + Booléen -> concaténation
Chaîne + Chaîne -> concaténation
```
Qu'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 :
- [**12.8.3** The Addition Operator (`+`)](https://www.ecma-international.org/ecma-262/#sec-addition-operator-plus)
- [**7.1.1** ToPrimitive(`input` [,`PreferredType`])](https://www.ecma-international.org/ecma-262/#sec-toprimitive)
- [**7.1.12** ToString(`argument`)](https://www.ecma-international.org/ecma-262/#sec-tostring)
## Addition de RegExps
Saviez-vous que vous pouviez ajouter des nombres comme dans l'exemple ci-dessous ?
```js
// Remplacement de la méthode toString
RegExp.prototype.toString =
function() {
return this.source;
} /
7 /
-/5/; // -> 2
```
### 💡 Explication :
- [**21.2.5.10** get RegExp.prototype.source](https://www.ecma-international.org/ecma-262/#sec-get-regexp.prototype.source)
## Les chaînes ne sont pas des instances de `String`
```js
"str"; // -> 'str'
typeof "str"; // -> 'string'
"str" instanceof String; // -> false
```
### 💡 Explication :
Le constructeur `String` retourne une chaîne :
```js
typeof String("str"); // -> 'string'
String("str"); // -> 'str'
String("str") == "str"; // -> true
```
Essayons avec un `new` :
```js
new String("str") == "str"; // -> true
typeof new String("str"); // -> "object"
```
Un objet ? Qu'est-ce que c'est ?
```js
new String("str"); // -> [String: 'str']
```
Plus d'infos sur le constructeur `String` dans la spécification :
- [**21.1.1** The String Constructor](https://www.ecma-international.org/ecma-262/#sec-string-constructor)
## Appeler des fonctions avec des caractères accent grave
Déclarons une fonction qui enregistre tous les paramètres dans la console :
```js
function f(...args) {
return args;
}
```
Aucun doute, vous savez qu'il est possible d'appeler cette fonction comme ceci :
```js
f(1, 2, 3); // -> [ 1, 2, 3 ]
```
Mais saviez-vous que vous pouvez appeler n'importe quelle fonction avec des caractères accent grave (_backticks_ en anglais) ?
```js
f`true is ${true}, false is ${false}, array is ${[1, 2, 3]}`;
// -> [ [ 'true is ', ', false is ', ', array is ', '' ],
// -> true,
// -> false,
// -> [ 1, 2, 3 ] ]
```
### 💡 Explication :
Bon, 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 :
```js
function template(strings, ...keys) {
// fait quelque chose avec `strings` et `keys`…
}
```
Voici 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.
Lien vers la spécification :
- [**12.3.7** Tagged Templates](https://www.ecma-international.org/ecma-262/#sec-tagged-templates)
## Call call call
> Trouvé par [@cramforce](http://twitter.com/cramforce)
```js
console.log.call.call.call.call.call.apply(a => a, [1, 2]);
```
### 💡 Explication :
Attention, 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 :
- [**19.2.3.3** Function.prototype.call(`thisArg`, ...`args`)](https://www.ecma-international.org/ecma-262/#sec-function.prototype.call)
- [**19.2.3.1 ** Function.prototype.apply(`thisArg`, `argArray`)](https://www.ecma-international.org/ecma-262/#sec-function.prototype.apply)
## Une propriété `constructor`
```js
const c = "constructor";
c[c][c]('console.log("WTF?")')(); // > WTF?
```
### 💡 Explication :
Considérez cet exemple étape par étape :
```js
// Déclare une nouvelle constante qui est une chaîne : "constructor"
const c = "constructor";
// `c` est une chaîne
c; // -> 'constructor'
// Pour obtenir le constructeur de la chaîne
c[c]; // -> [Function: String]
// Pour obtenir le constructeur du constructeur
c[c][c]; // -> [Function: Function]
// Appelle la Fonction constructeur et passe
// le corps d'une nouvelle fonction comme argument
c[c][c]('console.log("WTF?")'); // -> [Function: anonymous]
// Et ensuite appelle cette fonction anonyme
// Le résultat est un retour de console avec la chaîne "WTF?"
c[c][c]('console.log("WTF?")')(); // > "WTF?"
```
Un `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.
- [`Object.prototype.constructor`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor) at MDN
- [**19.1.3.1** Object.prototype.constructor](https://www.ecma-international.org/ecma-262/#sec-object.prototype.constructor)
## Object en tant que clé de la propriété d'un objet
```js
{ [{}]: {} } // -> { '[object Object]': {} }
```
### 💡 Explication :
Pourquoi 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 `{}`.
Nous pouvons créer des enfers de crochets et de parenthèses comme dans l'exemple ci-dessous :
```js
({ [{}]: { [{}]: {} } }[{}][{}]); // -> {}
// structure:
// {
// '[object Object]': {
// '[object Object]': {}
// }
// }
```
En savoir plus sur les objets littéraux ici:
- [Object initializer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer) at MDN
- [**12.2.6** Object Initializer](http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer)
## Accéder aux prototypes avec `__proto__`
Comme 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 :
```js
(1).__proto__.__proto__.__proto__; // -> null
```
### 💡 Explication :
Cela 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 :
```js
(1)
.__proto__(
// -> [Number: 0]
1
)
.__proto__.__proto__(
// -> {}
1
).__proto__.__proto__.__proto__; // -> null
```
Voici plus d'infos sur `__proto__` :
- [**B.2.2.1** Object.prototype.**proto**](https://www.ecma-international.org/ecma-262/#sec-object.prototype.__proto__)
- [**7.1.13** ToObject(`argument`)](https://www.ecma-international.org/ecma-262/#sec-toobject)
## `` `${{Object}}` ``
Quel est le résultat de l'expression ci-dessous ?
```js
`${{ Object }}`;
```
La réponse est :
```js
// -> '[object Object]'
```
### 💡 Explication :
Nous avons défini un objet avec une propriété `Object` en utilisant une _propriété de notation raccourcie_ :
```js
{
Object: Object;
}
```
Ensuite, 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]'`.
- [**12.2.9** Template Literals](https://www.ecma-international.org/ecma-262/#sec-template-literals)
- [Initialisateur d'objet](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Initialisateur_objet) sur MDN.
## Déstructuration avec des valeurs par défaut
Considérez cet exemple :
```js
let x,
{ x: y = 1 } = { x };
y;
```
L'exemple ci-dessus est une bonne question pour un entretien. Quelle est la valeur de `y` ? La réponse est :
```js
// -> 1
```
### 💡 Explication :
```js
let x,
{ x: y = 1 } = { x };
y;
// ↑ ↑ ↑ ↑
// 1 3 2 4
```
Avec l'exemple ci-dessus :
1. On déclare `x` sans valeur, donc sa valeur est `undefined`.
2. Ensuite, nous intégrons la valeur de `x` dans la propriété de l'objet `x`.
3. 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.
4. Retourne la valeur de `y`.
- [Initialisateur d'objet](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Initialisateur_objet) sur MDN.
## Points et propagation
Des exemples intéressants pourraient être composés avec la propagation de tableaux. Considérez cela :
```js
[...[..."..."]].length; // -> 3
```
### 💡 Explication :
Pourquoi `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.
Une chaîne `'...'` est composée de trois caractères `.`, donc, la longueur du tableau résultant est de `3`.
Maintenant, étape par étape :
```js
[...'...'] // -> [ '.', '.', '.' ]
[...[...'...']] // -> [ '.', '.', '.' ]
[...[...'...']].length // -> 3
```
Évidemment, nous pouvons étendre et encapsuler les éléments d’un tableau autant de fois que nous le souhaitons :
```js
[...'...'] // -> [ '.', '.', '.' ]
[...[...'...']] // -> [ '.', '.', '.' ]
[...[...[...'...']]] // -> [ '.', '.', '.' ]
[...[...[...[...'...']]]] // -> [ '.', '.', '.' ]
// etc.
```
## Étiquettes
Peu de programmeurs connaissent les étiquettes en JavaScript. Elles sont plutôt intéressantes :
```js
foo: {
console.log("first");
break foo;
console.log("second");
}
// -> first
// -> undefined
```
### 💡 Explication :
La 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.
Dans l'exemple ci-dessus, nous identifions une étiquette `foo`. Ensuite, `console.log('first');` est exécuté et l'exécution est interrompue.
En savoir plus sur les étiquettes en JavaScript :
- [**13.13** Labelled Statements](https://tc39.github.io/ecma262/#sec-labelled-statements)
- [Label](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Instructions/label) sur MDN.
## Étiquettes imbriquées
```js
a: b: c: d: e: f: g: 1, 2, 3, 4, 5; // -> 5
```
### 💡 Explication :
Similaire aux exemples précédents, suivez ces liens pour plus d'infos :
- [**12.16** Comma Operator (`,`)](https://www.ecma-international.org/ecma-262/#sec-comma-operator)
- [**13.13** Labeled Statements](https://tc39.github.io/ecma262/#sec-labelled-statements)
- [Label](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Instructions/label) sur MDN.
## `Try...catch` insidieux
Que retournera cette expression ? `2` ou `3` ?
```js
(() => {
try {
return 2;
} finally {
return 3;
}
})();
```
La réponse est `3`. Surprenant ?
### 💡 Explication :
- [**13.15** The `try` Statement](https://www.ecma-international.org/ecma-262/#sec-try-statement)
## Est-ce un héritage multiple ?
Regardez l'exemple ci-dessous :
```js
new class F extends (String, Array) {}(); // -> F []
```
Est-ce un héritage multiple ? Non.
### 💡 Explication :
L'é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`.
- [**14.5** Class Definitions](https://www.ecma-international.org/ecma-262/#sec-class-definitions)
- [**12.16** Comma Operator (`,`)](https://www.ecma-international.org/ecma-262/#sec-comma-operator)
## Un générateur qui se `yield` lui-même
Considérez cet exemple de générateur qui se `yield` lui-même :
```js
(function* f() {
yield f;
})().next();
// -> { value: [GeneratorFunction: f], done: false }
```
Comme 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 :
```js
(function* f() {
yield f;
})()
.next()
.value()
.next()(
// -> { value: [GeneratorFunction: f], done: false }
// and again
function* f() {
yield f;
}
)()
.next()
.value()
.next()
.value()
.next()(
// -> { value: [GeneratorFunction: f], done: false }
// and again
function* f() {
yield f;
}
)()
.next()
.value()
.next()
.value()
.next()
.value()
.next();
// -> { value: [GeneratorFunction: f], done: false }
// and so on
// …
```
### 💡 Explication :
Pour comprendre pourquoi cela fonctionne ainsi, lisez ces sections de la spécification :
- [**25** Control Abstraction Objects](https://www.ecma-international.org/ecma-262/#sec-control-abstraction-objects)
- [**25.3** Generator Objects](https://www.ecma-international.org/ecma-262/#sec-generator-objects)
## Une classe de classe
Considérez cette syntaxe obfusquée :
```js
typeof new class {
class() {}
}(); // -> "object"
```
Il 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"`.
### 💡 Explication :
Depuis 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 :
```js
const foo = {
class: function() {}
};
```
Et 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 :
```js
class {
class() {}
}
```
Le résultat d'une classe par défaut est toujours un objet simple. Et son `typeof` devrait retourner `"object"`.
Plus d'infos ici :
- [**14.3** Method Definitions](https://www.ecma-international.org/ecma-262/#sec-method-definitions)
- [**14.5** Class Definitions](https://www.ecma-international.org/ecma-262/#sec-class-definitions)
## Objets incoercibles
Avec des symboles bien connus, il existe un moyen de se débarrasser de la coercition de type. Examinez l'exemple ci-dessous :
```js
function nonCoercible(val) {
if (val == null) {
throw TypeError(
"inCoercible ne doit pas être appelé avec null ou undefined"
);
}
const res = Object(val);
res[Symbol.toPrimitive] = () => {
throw TypeError("Tente de transformer un objet incoercible");
};
return res;
}
```
Maintenant, nous pouvons l'utiliser de cette manière :
```js
// objets
const foo = nonCoercible({ foo: "foo" });
foo * 10; // -> TypeError: Tente de transformer un objet incoercible
foo + "evil"; // -> TypeError: Tente de transformer un objet incoercible
// chaînes
const bar = nonCoercible("bar");
bar + "1"; // -> TypeError: Tente de transformer un objet incoercible
bar.toString() + 1; // -> bar1
bar === "bar"; // -> false
bar.toString() === "bar"; // -> true
bar == "bar"; // -> TypeError: Tente de transformer un objet incoercible
// nombres
const baz = nonCoercible(1);
baz == 1; // -> Tente de transformer un objet incoercible
baz === 1; // -> false
baz.valueOf() === 1; // -> true
```
### 💡 Explication :
- [A gist by Sergey Rubanov](https://gist.github.com/chicoxyzzy/5dd24608e886adf5444499896dff1197)
- [**6.1.5.1** Well-Known Symbols](https://www.ecma-international.org/ecma-262/#sec-well-known-symbols)
## Fonctions fléchées complexes
Considérez l'exemple ci-dessous :
```js
let f = () => 10;
f(); // -> 10
```
D'accord, d'accord, mais qu'en est-il de celui-ci :
```js
let f = () => {};
f(); // -> undefined
```
### 💡 Explication :
Vous 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 :
```js
let f = () => ({});
f(); // -> {}
```
## Les fonctions fléchées ne peuvent pas être un constructeur
Considérez l'exemple ci-dessous :
```js
let f = function() {
this.a = 1;
};
new f(); // -> { 'a': 1 }
```
Maintenant, essayez de faire la même chose avec une fonction fléchée :
```js
let f = () => {
this.a = 1;
};
new f(); // -> TypeError: f is not a constructor
```
### 💡 Explication :
Les 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.
## `arguments` et fonctions fléchées
Considérez l'exemple ci-dessous :
```js
let f = function() {
return arguments;
};
f("a"); // -> { '0': 'a' }
```
Maintenant, essayez de faire la même chose avec une fonction fléchée :
```js
let f = () => arguments;
f("a"); // -> Uncaught ReferenceError: arguments is not defined
```
### 💡 Explication :
Les 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 :
```js
let f = (...args) => args;
f("a");
```
- [Fonctions fléchées](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Fonctions/Fonctions_fl%C3%A9ch%C3%A9es) sur MDN.
## Retour difficile
La déclaration `return` est compliquée aussi. Considérez ceci :
```js
(function() {
return;
{
b: 10;
}
})(); // -> undefined
```
### 💡 Explication :
`return` et l'expression renvoyée doivent être sur la même ligne :
```js
(function() {
return {
b: 10
};
})(); // -> { b: 10 }
```
Cela 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é.
- [**11.9.1** Rules of Automatic Semicolon Insertion](https://www.ecma-international.org/ecma-262/#sec-rules-of-automatic-semicolon-insertion)
- [**13.10** The `return` Statement](https://www.ecma-international.org/ecma-262/#sec-return-statement)
## Chaînage d'affectations sur un objet
```js
var foo = { n: 1 };
var bar = foo;
foo.x = foo = { n: 2 };
foo.x; // -> undefined
foo; // -> {n: 2}
bar; // -> {n: 1, x: {n: 2}}
```
De 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` ?
### 💡 Explication :
`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`.
Aprè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.
C'est équivalent à :
```js
var foo = { n: 1 };
var bar = foo;
foo = { n: 2 }; // -> {n: 2}
bar.x = foo; // -> {n: 1, x: {n: 2}}
// `bar.x` pointe sur l'adresse du nouvel objet `foo`
// ce n'est pas équivalent à : `bar.x = {n: 2}`
```
## Accéder aux propriétés d'un objet avec des tableaux
```js
var obj = { property: 1 };
var array = ["property"];
obj[array]; // -> 1
```
Qu'en est-il des tableaux pseudo-multidimensionnels ?
```js
var map = {};
var x = 1;
var y = 2;
var z = 3;
map[[x, y, z]] = true;
map[[x + 10, y, z]] = true;
map["1,2,3"]; // -> true
map["11,2,3"]; // -> true
```
### 💡 Explication :
L'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 :
```js
["property"].toString(); // -> 'property'
```
## Opérateurs `null` et relationnels
```js
null > 0; // false
null == 0; // false
null >= 0; // true
```
### 💡 Explication :
En bref, si `null < 0` est `false`, alors `null >= 0` est `true`. Lisez une explication détaillée [ici](https://blog.campvanilla.com/javascript-the-curious-case-of-null-0-7b131644e274).
## `Number.toFixed()` affiche différents nombres
`Number.toFixed()` peut se comporter étrangement selon le navigateur utilisé. Voir cet exemple :
```js
(0.7875).toFixed(3);
// Firefox: -> 0.787
// Chrome: -> 0.787
// IE11: -> 0.788
(0.7876).toFixed(3);
// Firefox: -> 0.788
// Chrome: -> 0.788
// IE11: -> 0.788
```
### 💡 Explication :
Alors 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.
Vous pouvez voir pourquoi cela se produit avec quelques tests rapides :
```js
// Confirme le résultat curieux d'arrondir `5` vers le bas
(0.7875).toFixed(3); // -> 0.787
// Il semble que ce soit juste `5` lorsque vous développez
// les limites de la précision de flottement de 64 bits (double précision)
(0.7875).toFixed(14); // -> 0.78750000000000
// Mais que se passe-t-il si vous allez au-delà de la limite ?
(0.7875).toFixed(20); // -> 0.78749999999999997780
```
Les 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.
Dans 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.
Ceci é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.
Voir pour référence `NOTE 2` sur la définition de ECMA-262 pour `toFixed`.
- [**20.1.3.3** Number.prototype.toFixed (`fractionDigits`)](https://www.ecma-international.org/ecma-262//#sec-number.prototype.tofixed)
## `Math.max()` est moins que `Math.min()`
```js
Math.min(1, 4, 7, 2); // -> 1
Math.max(1, 4, 7, 2); // -> 7
Math.min(); // -> Infinity
Math.max(); // -> -Infinity
Math.min() > Math.max(); // -> true
```
### 💡 Explication :
- [Why is Math.max() less than Math.min()?](https://charlieharvey.org.uk/page/why_math_max_is_less_than_math_min) par Charlie Harvey.
## Comparer `null` à `0`
Les expressions suivantes semblent introduire une contradiction :
```js
null == 0; // -> false
null > 0; // -> false
null >= 0; // -> true
```
Comment `null` peut-il être ni égal ni supérieur à `0`, si `null >= 0` est en fait `true` ? (Ceci fonctionne de la même manière avec inférieur ou égal à (`<=`).)
### 💡 Explication :
Les méthodes d'évaluation de ces trois expressions sont toutes différentes et sont responsables de la production de ce comportement inattendu.
Premiè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 :
```js
// Ce n'est pas ce qui se passe
(null == 0 + null) == +0;
0 == 0;
true;
```
Cependant, 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é.
Ensuite, la comparaison relationnelle `null > 0`. L'algorithme ici, contrairement à celui de l'opérateur d'égalité abstraite, _va_ convertir `null` à un nombre. Donc, nous obtenons ce comportement :
```js
null > 0
+null = +0
0 > 0
false
```
Finalement, la comparaison relationnelle `null >= 0`. Vous pourriez soutenir que cette expression devrait être le résultat de `null > 0 || null == 0`; si tel était le cas, les résultats ci-dessus signifieraient que ceci serait aussi `false`. Toutefois, l'opérateur `>=` fonctionne d'une manière très différente, qui est simplement d'utiliser le contraire de l'opérateur `<`. 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 :
```js
null >= 0;
!(null < 0);
!(+null < +0);
!(0 < 0);
!false;
true;
```
- [**7.2.12** Abstract Relational Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-relational-comparison)
- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)
## Même redéclaration d'une variable
JavaScript autorise la redéclaration de variables :
```js
a;
a;
// Ceci est aussi valide
a, a;
```
Et ça fonctionne aussi en mode `strict` :
```js
var a, a, a;
var a;
var a;
```
### 💡 Explication :
Toutes les définitions fusionnent en une seule définition.
- [**13.3.2** Variable Statement](https://www.ecma-international.org/ecma-262/#sec-variable-statement)
## Comportement par défaut d'`Array.prototype.sort()`
Imaginez que vous ayez besoin de trier un tableau composé de nombres.
```
[ 10, 1, 3 ].sort() // -> [ 1, 10, 3 ]
```
### 💡 Explication :
L'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.
- [**22.1.3.25** Array.prototype.sort ( comparefn )](https://www.ecma-international.org/ecma-262/#sec-array.prototype.sort)
### Indice
Passez `comparefn` si vous essayez de trier n'importe quoi d'autre qu'une chaîne.
```
[ 10, 1, 3 ].sort((a, b) => a - b) // -> [ 1, 3, 10 ]
```
# 📚 Autres ressources
- [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.
- [Wat](https://www.destroyallsoftware.com/talks/wat) — Un discours éclair de Gary Bernhardt de CodeMash 2012.
- [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.
# 🎓 Licence
[![CC 4.0][license-image]][license-url]
© [Denys Dovhan](http://denysdovhan.com)
[license-url]: http://www.wtfpl.net
[license-image]: https://img.shields.io/badge/License-WTFPL%202.0-lightgrey.svg?style=flat-square
[npm-url]: https://npmjs.org/package/wtfjs
[npm-image]: https://img.shields.io/npm/v/wtfjs.svg?style=flat-square
================================================
FILE: README-hi.md
================================================
# f\*ck जावास्क्रिप्ट क्या है
[![WTFPL 2.0][license-image]][license-url]
[![NPM version][npm-image]][npm-url]
> मजाकिया और मुश्किल जावास्क्रिप्ट उदाहरणों की एक सूची
जावास्क्रिप्ट एक महान भाषा है। इसका एक सरल वाक्यविन्यास है, एक बड़ा पारिस्थितिकी तंत्र, और, जो सबसे महत्वपूर्ण है, एक महान समुदाय।
उसी समय, हम सभी जानते हैं कि जावास्क्रिप्ट मुश्किल भागों के साथ काफी मज़ेदार भाषा है। उनमें से कुछ हमारी रोज़मर्रा की नौकरी को जल्दी से नरक में बदल सकते हैं, और उनमें से कुछ हमें ज़ोर से हँसा सकते हैं।
WTFJS के लिए मूल विचार है [Brian Leroux](https://twitter.com/brianleroux). यह सूची उनकी बातों से प्रेरित है [**“WTFJS”** at dotJS 2012](https://www.youtube.com/watch?v=et8xNAc2ic8):
[](https://www.youtube.com/watch?v=et8xNAc2ic8)
# Node पैकेज्ड पांडुलिपि
आप इस हैंडबुक को `npm` का उपयोग करके स्थापित कर सकते हैं। यहां जाओ:
```
$ npm install -g wtfjs
```
अब आपको कमांड लाइन पर `wtfjs` चलाने में सक्षम होना चाहिए। यह आपके चयनित `$ PAGER` में मैनुअल को खोलेगा। अन्यथा, आप यहां पढ़ना जारी रख सकते हैं।
स्रोत यहां उपलब्ध है: <https://github.com/denysdovhan/wtfjs>
# Translations
Currently, there are these translations of **wtfjs**:
- [中文版](./README-zh-cn.md)
- [हिन्दी](./README-hi.md)
[**एक और अनुवाद का अनुरोध करें**][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
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
# Table of Contents
- [💪🏻 प्रेरणा](#-%E0%A4%AA%E0%A5%8D%E0%A4%B0%E0%A5%87%E0%A4%B0%E0%A4%A3%E0%A4%BE)
- [✍🏻 नोटेशन](#-%E0%A4%A8%E0%A5%8B%E0%A4%9F%E0%A5%87%E0%A4%B6%E0%A4%A8)
- [👀 उदाहरण](#-%E0%A4%89%E0%A4%A6%E0%A4%BE%E0%A4%B9%E0%A4%B0%E0%A4%A3)
- [`[]` के बराबर`![]`](#-%E0%A4%95%E0%A5%87-%E0%A4%AC%E0%A4%B0%E0%A4%BE%E0%A4%AC%E0%A4%B0)
- [`true` is not equal `![]`, but not equal `[]` too](#true-is-not-equal--but-not-equal--too)
- [true is false](#true-is-false)
- [baNaNa](#banana)
- [`NaN` is not a `NaN`](#nan-is-not-a-nan)
- [यह विफल है](#%E0%A4%AF%E0%A4%B9-%E0%A4%B5%E0%A4%BF%E0%A4%AB%E0%A4%B2-%E0%A4%B9%E0%A5%88)
- [`[]` is truthy, but not `true`](#-is-truthy-but-not-true)
- [`null` is falsy, but not `false`](#null-is-falsy-but-not-false)
- [`document.all` is an object, but it is undefined](#documentall-is-an-object-but-it-is-undefined)
- [न्यूनतम मान शून्य से अधिक है](#%E0%A4%A8%E0%A5%8D%E0%A4%AF%E0%A5%82%E0%A4%A8%E0%A4%A4%E0%A4%AE-%E0%A4%AE%E0%A4%BE%E0%A4%A8-%E0%A4%B6%E0%A5%82%E0%A4%A8%E0%A5%8D%E0%A4%AF-%E0%A4%B8%E0%A5%87-%E0%A4%85%E0%A4%A7%E0%A4%BF%E0%A4%95-%E0%A4%B9%E0%A5%88)
- [फंक्शन कोई फंक्शन नहीं है](#%E0%A4%AB%E0%A4%82%E0%A4%95%E0%A5%8D%E0%A4%B6%E0%A4%A8-%E0%A4%95%E0%A5%8B%E0%A4%88-%E0%A4%AB%E0%A4%82%E0%A4%95%E0%A5%8D%E0%A4%B6%E0%A4%A8-%E0%A4%A8%E0%A4%B9%E0%A5%80%E0%A4%82-%E0%A4%B9%E0%A5%88)
- [Adding arrays](#adding-arrays)
- [सरणी में अल्पविराम](#%E0%A4%B8%E0%A4%B0%E0%A4%A3%E0%A5%80-%E0%A4%AE%E0%A5%87%E0%A4%82-%E0%A4%85%E0%A4%B2%E0%A5%8D%E0%A4%AA%E0%A4%B5%E0%A4%BF%E0%A4%B0%E0%A4%BE%E0%A4%AE)
- [ऐरे समानता एक राक्षस है](#%E0%A4%90%E0%A4%B0%E0%A5%87-%E0%A4%B8%E0%A4%AE%E0%A4%BE%E0%A4%A8%E0%A4%A4%E0%A4%BE-%E0%A4%8F%E0%A4%95-%E0%A4%B0%E0%A4%BE%E0%A4%95%E0%A5%8D%E0%A4%B7%E0%A4%B8-%E0%A4%B9%E0%A5%88)
- [`undefined` and `Number`](#undefined-and-number)
- [`parseInt` एक बुरा आदमी है](#parseint-%E0%A4%8F%E0%A4%95-%E0%A4%AC%E0%A5%81%E0%A4%B0%E0%A4%BE-%E0%A4%86%E0%A4%A6%E0%A4%AE%E0%A5%80-%E0%A4%B9%E0%A5%88)
- [`सत्य` और` असत्य` के साथ गणित](#%E0%A4%B8%E0%A4%A4%E0%A5%8D%E0%A4%AF-%E0%A4%94%E0%A4%B0-%E0%A4%85%E0%A4%B8%E0%A4%A4%E0%A5%8D%E0%A4%AF-%E0%A4%95%E0%A5%87-%E0%A4%B8%E0%A4%BE%E0%A4%A5-%E0%A4%97%E0%A4%A3%E0%A4%BF%E0%A4%A4)
- [HTML टिप्पणियाँ जावास्क्रिप्ट में मान्य हैं](#html-%E0%A4%9F%E0%A4%BF%E0%A4%AA%E0%A5%8D%E0%A4%AA%E0%A4%A3%E0%A4%BF%E0%A4%AF%E0%A4%BE%E0%A4%81-%E0%A4%9C%E0%A4%BE%E0%A4%B5%E0%A4%BE%E0%A4%B8%E0%A5%8D%E0%A4%95%E0%A5%8D%E0%A4%B0%E0%A4%BF%E0%A4%AA%E0%A5%8D%E0%A4%9F-%E0%A4%AE%E0%A5%87%E0%A4%82-%E0%A4%AE%E0%A4%BE%E0%A4%A8%E0%A5%8D%E0%A4%AF-%E0%A4%B9%E0%A5%88%E0%A4%82)
- [`NaN` is ~~not~~ a number](#nan-is-not-a-number)
- [`[]` and `null` are objects](#-and-null-are-objects)
- [Magically increasing numbers](#magically-increasing-numbers)
- [Precision of `0.1 + 0.2`](#precision-of-01--02)
- [पैचिंग नंबर](#%E0%A4%AA%E0%A5%88%E0%A4%9A%E0%A4%BF%E0%A4%82%E0%A4%97-%E0%A4%A8%E0%A4%82%E0%A4%AC%E0%A4%B0)
- [Comparison of three numbers](#comparison-of-three-numbers)
- [मजेदार गणित](#%E0%A4%AE%E0%A4%9C%E0%A5%87%E0%A4%A6%E0%A4%BE%E0%A4%B0-%E0%A4%97%E0%A4%A3%E0%A4%BF%E0%A4%A4)
- [RegExps का जोड़](#regexps-%E0%A4%95%E0%A4%BE-%E0%A4%9C%E0%A5%8B%E0%A4%A1%E0%A4%BC)
- [स्ट्रिंग्स `स्ट्रिंग` के उदाहरण नहीं हैं](#%E0%A4%B8%E0%A5%8D%E0%A4%9F%E0%A5%8D%E0%A4%B0%E0%A4%BF%E0%A4%82%E0%A4%97%E0%A5%8D%E0%A4%B8-%E0%A4%B8%E0%A5%8D%E0%A4%9F%E0%A5%8D%E0%A4%B0%E0%A4%BF%E0%A4%82%E0%A4%97-%E0%A4%95%E0%A5%87-%E0%A4%89%E0%A4%A6%E0%A4%BE%E0%A4%B9%E0%A4%B0%E0%A4%A3-%E0%A4%A8%E0%A4%B9%E0%A5%80%E0%A4%82-%E0%A4%B9%E0%A5%88%E0%A4%82)
- [बैकटिक्स के साथ कॉलिंग फ़ंक्शन](#%E0%A4%AC%E0%A5%88%E0%A4%95%E0%A4%9F%E0%A4%BF%E0%A4%95%E0%A5%8D%E0%A4%B8-%E0%A4%95%E0%A5%87-%E0%A4%B8%E0%A4%BE%E0%A4%A5-%E0%A4%95%E0%A5%89%E0%A4%B2%E0%A4%BF%E0%A4%82%E0%A4%97-%E0%A4%AB%E0%A4%BC%E0%A4%82%E0%A4%95%E0%A5%8D%E0%A4%B6%E0%A4%A8)
- [पुकार पुकार पुकार](#%E0%A4%AA%E0%A5%81%E0%A4%95%E0%A4%BE%E0%A4%B0-%E0%A4%AA%E0%A5%81%E0%A4%95%E0%A4%BE%E0%A4%B0-%E0%A4%AA%E0%A5%81%E0%A4%95%E0%A4%BE%E0%A4%B0)
- [A `constructor` property](#a-constructor-property)
- [वस्तु की संपत्ति की कुंजी के रूप में वस्तु](#%E0%A4%B5%E0%A4%B8%E0%A5%8D%E0%A4%A4%E0%A5%81-%E0%A4%95%E0%A5%80-%E0%A4%B8%E0%A4%82%E0%A4%AA%E0%A4%A4%E0%A5%8D%E0%A4%A4%E0%A4%BF-%E0%A4%95%E0%A5%80-%E0%A4%95%E0%A5%81%E0%A4%82%E0%A4%9C%E0%A5%80-%E0%A4%95%E0%A5%87-%E0%A4%B0%E0%A5%82%E0%A4%AA-%E0%A4%AE%E0%A5%87%E0%A4%82-%E0%A4%B5%E0%A4%B8%E0%A5%8D%E0%A4%A4%E0%A5%81)
- [प्रोटोटाइपिंग को `__proto__` के साथ एक्सेस करना](#%E0%A4%AA%E0%A5%8D%E0%A4%B0%E0%A5%8B%E0%A4%9F%E0%A5%8B%E0%A4%9F%E0%A4%BE%E0%A4%87%E0%A4%AA%E0%A4%BF%E0%A4%82%E0%A4%97-%E0%A4%95%E0%A5%8B-__proto__-%E0%A4%95%E0%A5%87-%E0%A4%B8%E0%A4%BE%E0%A4%A5-%E0%A4%8F%E0%A4%95%E0%A5%8D%E0%A4%B8%E0%A5%87%E0%A4%B8-%E0%A4%95%E0%A4%B0%E0%A4%A8%E0%A4%BE)
- [`` `$ {{वस्तु}}` ``](#--%E0%A4%B5%E0%A4%B8%E0%A5%8D%E0%A4%A4%E0%A5%81-)
- [डिफ़ॉल्ट मानों के साथ विनाशकारी](#%E0%A4%A1%E0%A4%BF%E0%A4%AB%E0%A4%BC%E0%A5%89%E0%A4%B2%E0%A5%8D%E0%A4%9F-%E0%A4%AE%E0%A4%BE%E0%A4%A8%E0%A5%8B%E0%A4%82-%E0%A4%95%E0%A5%87-%E0%A4%B8%E0%A4%BE%E0%A4%A5-%E0%A4%B5%E0%A4%BF%E0%A4%A8%E0%A4%BE%E0%A4%B6%E0%A4%95%E0%A4%BE%E0%A4%B0%E0%A5%80)
- [डॉट्स और फैल रहा है](#%E0%A4%A1%E0%A5%89%E0%A4%9F%E0%A5%8D%E0%A4%B8-%E0%A4%94%E0%A4%B0-%E0%A4%AB%E0%A5%88%E0%A4%B2-%E0%A4%B0%E0%A4%B9%E0%A4%BE-%E0%A4%B9%E0%A5%88)
- [लेबल](#%E0%A4%B2%E0%A5%87%E0%A4%AC%E0%A4%B2)
- [Nested labels](#nested-labels)
- [कपटी `कोशिश..चेक`](#%E0%A4%95%E0%A4%AA%E0%A4%9F%E0%A5%80-%E0%A4%95%E0%A5%8B%E0%A4%B6%E0%A4%BF%E0%A4%B6%E0%A4%9A%E0%A5%87%E0%A4%95)
- [क्या यह कई विरासत है?](#%E0%A4%95%E0%A5%8D%E0%A4%AF%E0%A4%BE-%E0%A4%AF%E0%A4%B9-%E0%A4%95%E0%A4%88-%E0%A4%B5%E0%A4%BF%E0%A4%B0%E0%A4%BE%E0%A4%B8%E0%A4%A4-%E0%A4%B9%E0%A5%88)
- [एक जनरेटर जो खुद उपजता है](#%E0%A4%8F%E0%A4%95-%E0%A4%9C%E0%A4%A8%E0%A4%B0%E0%A5%87%E0%A4%9F%E0%A4%B0-%E0%A4%9C%E0%A5%8B-%E0%A4%96%E0%A5%81%E0%A4%A6-%E0%A4%89%E0%A4%AA%E0%A4%9C%E0%A4%A4%E0%A4%BE-%E0%A4%B9%E0%A5%88)
- [कक्षा का एक वर्ग](#%E0%A4%95%E0%A4%95%E0%A5%8D%E0%A4%B7%E0%A4%BE-%E0%A4%95%E0%A4%BE-%E0%A4%8F%E0%A4%95-%E0%A4%B5%E0%A4%B0%E0%A5%8D%E0%A4%97)
- [गैर-सहकर्मी वस्तुएं](#%E0%A4%97%E0%A5%88%E0%A4%B0-%E0%A4%B8%E0%A4%B9%E0%A4%95%E0%A4%B0%E0%A5%8D%E0%A4%AE%E0%A5%80-%E0%A4%B5%E0%A4%B8%E0%A5%8D%E0%A4%A4%E0%A5%81%E0%A4%8F%E0%A4%82)
- [मुश्किल तीर कार्य](#%E0%A4%AE%E0%A5%81%E0%A4%B6%E0%A5%8D%E0%A4%95%E0%A4%BF%E0%A4%B2-%E0%A4%A4%E0%A5%80%E0%A4%B0-%E0%A4%95%E0%A4%BE%E0%A4%B0%E0%A5%8D%E0%A4%AF)
- [एरो फ़ंक्शंस एक निर्माता नहीं हो सकता है](#%E0%A4%8F%E0%A4%B0%E0%A5%8B-%E0%A4%AB%E0%A4%BC%E0%A4%82%E0%A4%95%E0%A5%8D%E0%A4%B6%E0%A4%82%E0%A4%B8-%E0%A4%8F%E0%A4%95-%E0%A4%A8%E0%A4%BF%E0%A4%B0%E0%A5%8D%E0%A4%AE%E0%A4%BE%E0%A4%A4%E0%A4%BE-%E0%A4%A8%E0%A4%B9%E0%A5%80%E0%A4%82-%E0%A4%B9%E0%A5%8B-%E0%A4%B8%E0%A4%95%E0%A4%A4%E0%A4%BE-%E0%A4%B9%E0%A5%88)
- [`तर्क` और तीर कार्य](#%E0%A4%A4%E0%A4%B0%E0%A5%8D%E0%A4%95-%E0%A4%94%E0%A4%B0-%E0%A4%A4%E0%A5%80%E0%A4%B0-%E0%A4%95%E0%A4%BE%E0%A4%B0%E0%A5%8D%E0%A4%AF)
- [मुश्किल वापसी](#%E0%A4%AE%E0%A5%81%E0%A4%B6%E0%A5%8D%E0%A4%95%E0%A4%BF%E0%A4%B2-%E0%A4%B5%E0%A4%BE%E0%A4%AA%E0%A4%B8%E0%A5%80)
- [ऑब्जेक्ट पर कार्य असाइन करना](#%E0%A4%91%E0%A4%AC%E0%A5%8D%E0%A4%9C%E0%A5%87%E0%A4%95%E0%A5%8D%E0%A4%9F-%E0%A4%AA%E0%A4%B0-%E0%A4%95%E0%A4%BE%E0%A4%B0%E0%A5%8D%E0%A4%AF-%E0%A4%85%E0%A4%B8%E0%A4%BE%E0%A4%87%E0%A4%A8-%E0%A4%95%E0%A4%B0%E0%A4%A8%E0%A4%BE)
- [सरणियों के साथ ऑब्जेक्ट गुण तक पहुँचना](#%E0%A4%B8%E0%A4%B0%E0%A4%A3%E0%A4%BF%E0%A4%AF%E0%A5%8B%E0%A4%82-%E0%A4%95%E0%A5%87-%E0%A4%B8%E0%A4%BE%E0%A4%A5-%E0%A4%91%E0%A4%AC%E0%A5%8D%E0%A4%9C%E0%A5%87%E0%A4%95%E0%A5%8D%E0%A4%9F-%E0%A4%97%E0%A5%81%E0%A4%A3-%E0%A4%A4%E0%A4%95-%E0%A4%AA%E0%A4%B9%E0%A5%81%E0%A4%81%E0%A4%9A%E0%A4%A8%E0%A4%BE)
- [Null and Relational Operators](#null-and-relational-operators)
- [`Number.toFixed ()` विभिन्न संख्याएँ प्रदर्शित करता है](#numbertofixed--%E0%A4%B5%E0%A4%BF%E0%A4%AD%E0%A4%BF%E0%A4%A8%E0%A5%8D%E0%A4%A8-%E0%A4%B8%E0%A4%82%E0%A4%96%E0%A5%8D%E0%A4%AF%E0%A4%BE%E0%A4%8F%E0%A4%81-%E0%A4%AA%E0%A5%8D%E0%A4%B0%E0%A4%A6%E0%A4%B0%E0%A5%8D%E0%A4%B6%E0%A4%BF%E0%A4%A4-%E0%A4%95%E0%A4%B0%E0%A4%A4%E0%A4%BE-%E0%A4%B9%E0%A5%88)
- [`Math.max()` less than `Math.min()`](#mathmax-less-than-mathmin)
- [तुलना `null` से` 0` तक](#%E0%A4%A4%E0%A5%81%E0%A4%B2%E0%A4%A8%E0%A4%BE-null-%E0%A4%B8%E0%A5%87-0-%E0%A4%A4%E0%A4%95)
- [समान परिवर्तनशील पुनर्वितरण](#%E0%A4%B8%E0%A4%AE%E0%A4%BE%E0%A4%A8-%E0%A4%AA%E0%A4%B0%E0%A4%BF%E0%A4%B5%E0%A4%B0%E0%A5%8D%E0%A4%A4%E0%A4%A8%E0%A4%B6%E0%A5%80%E0%A4%B2-%E0%A4%AA%E0%A5%81%E0%A4%A8%E0%A4%B0%E0%A5%8D%E0%A4%B5%E0%A4%BF%E0%A4%A4%E0%A4%B0%E0%A4%A3)
- [डिफ़ॉल्ट व्यवहार Array.prototyp.sort ()](#%E0%A4%A1%E0%A4%BF%E0%A4%AB%E0%A4%BC%E0%A5%89%E0%A4%B2%E0%A5%8D%E0%A4%9F-%E0%A4%B5%E0%A5%8D%E0%A4%AF%E0%A4%B5%E0%A4%B9%E0%A4%BE%E0%A4%B0-arrayprototypsort-)
- [📚 अन्य संसाधन](#-%E0%A4%85%E0%A4%A8%E0%A5%8D%E0%A4%AF-%E0%A4%B8%E0%A4%82%E0%A4%B8%E0%A4%BE%E0%A4%A7%E0%A4%A8)
- [🎓 License](#-license)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
# 💪🏻 प्रेरणा
> सिर्फ मनोरंजन के लिए
>
> — _[**“सिर्फ मनोरंजन के लिए: एक्सीडेंटल रिवोल्यूशनरी की कहानी”**](https://en.wikipedia.org/wiki/Just_for_Fun), Linus Torvalds_
इस सूची का प्राथमिक लक्ष्य कुछ पागल उदाहरणों को इकट्ठा करना और यह बताना है कि यदि संभव हो तो वे कैसे काम करते हैं। सिर्फ इसलिए कि कुछ ऐसा सीखना मजेदार है जिसे हम पहले नहीं जानते थे।
यदि आप एक शुरुआती हैं, तो आप इन नोटों का उपयोग जावास्क्रिप्ट में गहरा गोता लगाने के लिए कर सकते हैं। मुझे उम्मीद है कि ये नोट्स आपको विनिर्देश पढ़ने में अधिक समय बिताने के लिए प्रेरित करेंगे।
यदि आप एक पेशेवर डेवलपर हैं, तो आप इन उदाहरणों पर सभी उद्धरणों और हमारे प्रिय जावास्क्रिप्ट के अप्रत्याशित किनारों के लिए एक महान संदर्भ के रूप में विचार कर सकते हैं।
किसी भी मामले में, बस इसे पढ़ें। आप शायद कुछ नया खोजने जा रहे हैं।
# ✍🏻 नोटेशन
**`// ->`** एक अभिव्यक्ति का परिणाम दिखाने के लिए प्रयोग किया जाता है. उदाहरण के लिए:
```js
1 + 1; // -> 2
```
**`// >`** का परिणाम है `console.log` या कोई अन्य आउटपुट। उदाहरण के लिए:
```js
console.log("hello, world!"); // > hello, world!
```
**`//`** स्पष्टीकरण के लिए इस्तेमाल की जाने वाली टिप्पणी मात्र है। उदाहरण:
```js
// Assigning a function to foo constant
const foo = function() {};
```
# 👀 उदाहरण
## `[]` के बराबर`![]`
array समान नहीं है:
```js
[] == ![]; // -> true
```
### 💡 व्याख्या:
अमूर्त समानता ऑपरेटर उनकी तुलना करने के लिए दोनों पक्षों को संख्याओं में परिवर्तित करता है और दोनों पक्ष अलग-अलग कारणों से संख्या `0` बन जाते हैं। एरे सत्य हैं, इसलिए दाईं ओर, एक सत्य मूल्य के विपरीत `गलत` है, जो तब` 0` के लिए मजबूर है। बाईं ओर, हालांकि, एक खाली सरणी पहले एक बूलियन बनने के बिना एक संख्या के लिए मजबूर की जाती है, और खाली सरणियों को सत्य होने के बावजूद `0` के लिए मजबूर किया जाता है।
इस प्रकार यह अभिव्यक्ति सरल है:
```js
+[] == +![];
0 == +false;
0 == 0;
true;
```
See also [`[]` is truthy, but not `true`](#-is-truthy-but-not-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` is not equal `![]`, but not equal `[]` too
Array बराबर नहीं है `true`, लेकिन Array बराबर नहीं है` true` भी नहीं;
Array बराबर है 'false', Array बराबर है 'false' भी:
```js
true == []; // -> false
true == ![]; // -> false
false == []; // -> true
false == ![]; // -> true
```
### 💡 व्याख्या:
```js
true == []; // -> false
true == ![]; // -> false
// विनिर्देश के अनुसार
true == []; // -> false
toNumber(true); // -> 1
toNumber([]); // -> 0
1 == 0; // -> false
true == ![]; // -> false
![]; // -> false
true == false; // -> false
```
```js
false == []; // -> true
false == ![]; // -> true
// विनिर्देश के अनुसार
false == []; // -> true
toNumber(false); // -> 0
toNumber([]); // -> 0
0 == 0; // -> true
false == ![]; // -> false
![]; // -> false
false == false; // -> true
```
- [**7.2.13** सार समानता](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)
## true is false
```js
!!"false" == !!"true"; // -> true
!!"false" === !!"true"; // -> true
```
### 💡 व्याख्या:
Consider this step-by-step:
```js
// true is 'truthy' and represented by value 1 (number), 'true' in string form is NaN.
true == "true"; // -> false
false == "false"; // -> false
// 'false' is not the empty string, so it's a truthy value
!!"false"; // -> true
!!"true"; // -> true
```
- [**7.2.13** सार समानता](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)
## baNaNa
```js
"b" + "a" + +"a" + "a"; // -> 'baNaNa'
```
यह जावास्क्रिप्ट में एक पुराने स्कूल का मजाक है, लेकिन फिर से बनाया गया है। यहाँ मूल एक है:
```js
"foo" + +"bar"; // -> 'fooNaN'
```
### 💡 व्याख्या:
अभिव्यक्ति का मूल्यांकन `'फू' + (+ 'बार') के रूप में किया जाता है, जो संख्या को नहीं करने के लिए` 'बार'` को परिवर्तित करता है।
- [**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` is not a `NaN`
```js
NaN === NaN; // -> false
```
### 💡 व्याख्या:
विनिर्देश इस व्यवहार के पीछे तर्क को सख्ती से परिभाषित करता है:
> 1. If `Type(x)` is different from `Type(y)`, return **false**.
> 2. If `Type(x)` is Number, then
> 1. If `x` is **NaN**, return **false**.
> 2. If `y` is **NaN**, return **false**.
> 3. … … …
>
> — [**7.2.14** सख्त समानता की तुलना](https://www.ecma-international.org/ecma-262/#sec-strict-equality-comparison)
Following the definition of `NaN` from the IEEE:
> चार परस्पर अनन्य संबंध संभव हैं: से कम, बराबर, अधिक से अधिक, और अव्यवस्थित। आखिरी मामला तब उठता है जब कम से कम एक ऑपरेंड NaN होता है। प्रत्येक NaN अपने आप सहित हर चीज के साथ अनियंत्रित की तुलना करेगा।
>
> — [“IEEE754 NaN मानों के लिए झूठी वापसी करने वाली सभी तुलनाओं के लिए तर्क क्या है?”](https://stackoverflow.com/questions/1565164/1573715#1573715) at StackOverflow
## यह विफल है
आपको विश्वास नहीं होगा, लेकिन …
```js
(![] + [])[+[]] +
(![] + [])[+!+[]] +
([![]] + [][[]])[+!+[] + [+[]]] +
(![] + [])[!+[] + !+[]];
// -> 'fail'
```
### 💡 व्याख्या:
प्रतीकों के उस द्रव्यमान को टुकड़ों में तोड़कर, हम देखते हैं कि निम्न पैटर्न अक्सर होता है:
```js
![] + []; // -> 'false'
![]; // -> false
```
इसलिए हम `[]` को `गलत` में जोड़ने का प्रयास करते हैं। लेकिन कई आंतरिक फ़ंक्शन कॉल के कारण (`बाइनरी + ऑपरेटर` ->` ToPrimitive` -> `[[DefaultValue]]`) हम एक स्ट्रिंग के लिए सही ऑपरेंड को परिवर्तित करते हैं:
```js
![] + [].toString(); // 'false'
```
एक स्ट्रिंग के रूप में एक सरणी के रूप में सोचकर हम इसके पहले चरित्र तक पहुंच सकते हैं `[0]`:
```js
"false"[0]; // -> 'f'
```
बाकी स्पष्ट है, लेकिन `i` मुश्किल है। `विफल 'में` i` स्ट्रिंग को उत्पन्न करके' 'falseundefined'` को पकड़ा जाता है और सूचकांक पर तत्व को पकड़ा जाता है `[' 10 ']`'
## `[]` is truthy, but not `true`
एक सरणी एक सत्य मूल्य है, हालांकि, यह `सत्य` के बराबर नहीं है।
```js
!![] // -> true
[] == true // -> false
```
### 💡 व्याख्या:
यहाँ 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` is falsy, but not `false`
इस तथ्य के बावजूद कि `null` एक मिथ्या मूल्य है, यह` false` के बराबर नहीं है।
```js
!!null; // -> false
null == false; // -> false
```
इसी समय, अन्य झूठे मूल्य, जैसे `0` या` `` `` झूठ` के बराबर हैं।
```js
0 == false; // -> true
"" == false; // -> true
```
### 💡 व्याख्या:
विवरण पिछले उदाहरण के समान है। यहाँ इसी लिंक है:
- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)
## `document.all` is an object, but it is undefined
> ⚠️ यह ब्राउज़र API का हिस्सा है और यह Node.js वातावरण में काम नहीं करेगा⚠️
इस तथ्य के बावजूद कि `document.all` एक सरणी जैसी वस्तु है और यह पृष्ठ में DOM नोड्स तक पहुँच प्रदान करता है, यह` टाइपोफ` फ़ंक्शन को `अपरिभाषित` के रूप में प्रतिक्रिया देता है।
```js
document.all instanceof Object; // -> true
typeof document.all; // -> 'undefined'
```
इसी समय, ` document.all`` अपरिभाषित ` के बराबर नहीं है।
```js
document.all === undefined; // -> false
document.all === null; // -> false
```
But at the same time:
```js
document.all == null; // -> true
```
### 💡 व्याख्या:
> `document.all` विशेष रूप से IE के पुराने संस्करणों के साथ DOM तत्वों को एक्सेस करने का एक तरीका हुआ करता था। हालांकि यह कभी भी एक मानक नहीं रहा है, लेकिन इसका इस्तेमाल वृद्धावस्था के जेएस कोड में किया जाता था। जब मानक नए एपीआई (जैसे `document.getElementById`) के साथ आगे बढ़ा, तो यह एपीआई कॉल अप्रचलित हो गई और मानक समिति को तय करना था कि इसके साथ क्या करना है। इसके व्यापक उपयोग के कारण उन्होंने एपीआई रखने का फैसला किया, लेकिन जावास्क्रिप्ट विनिर्देश के विलफुल उल्लंघन का परिचय दिया।
> इसका उपयोग करने पर कारण `झूठ` का जवाब देता है [Strict Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-strict-equality-comparison) with `undefined` while `true` when using the [Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison) स्पष्ट रूप से अनुमति देता है कि विनिर्देश के विलफुल उल्लंघन के कारण है।
>
> — [“Obsolete features - document.all”](https://html.spec.whatwg.org/multipage/obsolete.html#dom-document-all) at 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) at YDKJS - Types & Grammar
## न्यूनतम मान शून्य से अधिक है
`Number.MIN_VALUE` सबसे छोटी संख्या है, जो शून्य से अधिक है:
```js
Number.MIN_VALUE > 0; // -> true
```
### 💡 व्याख्या:
> ` नंबर .IN_VALUE`` 5e-324 ` है, यानी सबसे छोटी धनात्मक संख्या जिसे फ्लोट प्रिसिजन के भीतर दर्शाया जा सकता है, यानी कि आप शून्य के जितना करीब हो सकते हैं। यह सबसे अच्छे रिज़ॉल्यूशन को परिभाषित करता है जो तैरता है जो आपको दे सकता है
>
> अब कुल मिलाकर सबसे छोटा मूल्य है `नंबर.नैगेटिव_इनफिनिटी` हालांकि यह एक सख्त अर्थ में वास्तव में संख्यात्मक नहीं है।
>
> — [“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)
## फंक्शन कोई फंक्शन नहीं है
> ⚠️ V8 v5.5 या निम्न में मौजूद बग (Node.js <= 7)⚠️
आप सभी को पता है कि कष्टप्रद _undefined एक function_ नहीं है, लेकिन इस बारे में क्या?
```js
// Declare a class which extends null
class Foo extends null {}
// -> [Function: Foo]
new Foo() instanceof null;
// > TypeError: function is not a function
// > at … … …
```
### 💡 व्याख्या:
यह स्पेसिफिकेशन का हिस्सा नहीं है। यह केवल एक बग है जिसे अब ठीक कर दिया गया है, इसलिए भविष्य में इसके साथ कोई समस्या नहीं होनी चाहिए।
## Adding arrays
यदि आप दो सरणियों को जोड़ने का प्रयास करते हैं तो क्या होगा?
```js
[1, 2, 3] + [4, 5, 6]; // -> '1,2,34,5,6'
```
### 💡 व्याख्या:
संघात होता है। चरण-दर-चरण, ऐसा दिखता है:
```js
[1, 2, 3] +
[4, 5, 6][
// call toString()
(1, 2, 3)
].toString() +
[4, 5, 6].toString();
// concatenation
"1,2,3" + "4,5,6";
// ->
("1,2,34,5,6");
```
## सरणी में अल्पविराम
आपने 4 खाली तत्वों के साथ एक सरणी बनाई है। सभी के बावजूद, आपको अल्पविराम के कारण तीन तत्वों के साथ एक सरणी मिलेगी:
```js
let a = [, , ,];
a.length; // -> 3
a.toString(); // -> ',,'
```
### 💡 व्याख्या:
> **Trailing commas** (कभी-कभी "अंतिम कॉमा" कहा जाता है) जावास्क्रिप्ट कोड में नए तत्वों, मापदंडों या गुणों को जोड़ते समय उपयोगी हो सकता है। यदि आप एक नई संपत्ति जोड़ना चाहते हैं, तो आप बस पिछली पंक्ति को संशोधित किए बिना एक नई रेखा जोड़ सकते हैं यदि वह रेखा पहले से ही एक अल्पविराम का उपयोग करती है। इससे संस्करण-नियंत्रण अलग-अलग हो जाता है और एडिटिंग कोड कम परेशानी वाला हो सकता है।
>
> — [Trailing commas](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas) at MDN
## ऐरे समानता एक राक्षस है
JS में Array समानता एक राक्षस है, जैसा कि आप नीचे देख सकते हैं:
```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
```
### 💡 व्याख्या:
आपको उपरोक्त उदाहरणों के लिए बहुत सावधानी से देखना चाहिए! व्यवहार अनुभाग में वर्णित है[**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison) of the specification.
## `undefined` and `Number`
यदि हम `नंबर` कंस्ट्रक्टर में कोई तर्क नहीं देते हैं, तो हम` 0` प्राप्त करेंगे। मान 'अपरिभाषित' को औपचारिक तर्कों के लिए सौंपा गया है जब कोई वास्तविक तर्क नहीं हैं, तो आप उम्मीद कर सकते हैं कि बिना तर्क के `संख्या` अपने पैरामीटर के मान के रूप में`अपरिभाषित 'लेता है। हालाँकि, जब हम`अपरिभाषित` पास करते हैं, तो हम` NaN` प्राप्त करेंगे।
```js
Number(); // -> 0
Number(undefined); // -> NaN
```
### 💡 व्याख्या:
विनिर्देश के अनुसार:
1. यदि इस फ़ंक्शन के आह्वान पर कोई तर्क नहीं दिया गया, तो `n` को` + 0` होने दें।
2. और, चलो `n` हो? `ToNumber (मान)`।
3. `अपरिभाषित` के मामले में,`ToNumber (अपरिभाषित)`को` NaN` वापस करना चाहिए।
Here's the corresponding section:
- [**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` एक बुरा आदमी है
`parseInt` अपने quirks द्वारा प्रसिद्ध है:
```js
parseInt("f*ck"); // -> NaN
parseInt("f*ck", 16); // -> 15
```
**💡 व्याख्या:** ऐसा इसलिए होता है क्योंकि `parseInt` चरित्र-दर-चरित्र को तब तक जारी रखेगा, जब तक कि वह एक चरित्र को हिट न कर दे, जो उसे पता नहीं है। `F` in` 'f * ck'` हेक्साडेसिमल अंक `15` है।
पूर्णांक के लिए `इन्फिनिटी` को पार्स करना कुछ…
```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
```
Be careful with parsing `null` too:
```js
parseInt(null, 24); // -> 23
```
**💡 व्याख्या:**
> यह `null` को स्ट्रिंग` `null” ` में परिवर्तित कर रहा है और इसे परिवर्तित करने का प्रयास कर रहा है। 23 के माध्यम से मूलांक 0 के लिए, ऐसे कोई अंक नहीं हैं जो इसे रूपांतरित कर सकते हैं, इसलिए यह NaN लौटाता है। 24 में, 14 वें अक्षर `` एन '', को अंक प्रणाली में जोड़ा जाता है। 31 पर, 21 वें अक्षर `` यू '' को जोड़ा जाता है और पूरे स्ट्रिंग को डिकोड किया जा सकता है। 37 पर अब कोई वैध अंक सेट नहीं है जो उत्पन्न किया जा सकता है और `NaN` को लौटा दिया जाता है।
>
> — [“parseInt(null, 24) === 23… wait, what?”](https://stackoverflow.com/questions/6459758/parseintnull-24-23-wait-what) at StackOverflow
अष्टक के बारे में मत भूलना:
```js
parseInt("06"); // 6
parseInt("08"); // 8 if support ECMAScript 5
parseInt("08"); // 0 if not support ECMAScript 5
```
**💡 व्याख्या:**यदि इनपुट स्ट्रिंग "0" से शुरू होती है, तो मूलांक आठ (अष्टक) या 10 (दशमलव) है। वास्तव में जो मूलांक चुना गया है वह कार्यान्वयन-निर्भर है। ECMAScript 5 निर्दिष्ट करता है कि 10 (दशमलव) का उपयोग किया जाता है, लेकिन सभी ब्राउज़र अभी तक इसका समर्थन नहीं करते हैं। इस कारण से `parseInt` का उपयोग करते समय हमेशा एक मूलांक निर्दिष्ट करें।
`parseInt` always convert input to string:
```js
parseInt({ toString: () => 2, valueOf: () => 1 }); // -> 2
Number({ toString: () => 2, valueOf: () => 1 }); // -> 1
```
फ़्लोटिंग पॉइंट मानों को पार्स करते समय सावधान रहें
```js
parseInt(0.000001); // -> 0
parseInt(0.0000001); // -> 1
parseInt(1 / 1999999); // -> 5
```
**💡 व्याख्या:** `ParseInt` एक स्ट्रिंग तर्क लेता है और निर्दिष्ट मूलांक का पूर्णांक देता है। `ParseInt` भी स्ट्रिंग पैरामीटर में पहले गैर-अंक के बाद और सहित कुछ भी स्ट्रिप्स। `0.000001` को स्ट्रिंग में परिवर्तित किया जाता है `0.000001` और ` पार्सेइंट`` 0 ` देता है। जब `0.0000001` को एक स्ट्रिंग में परिवर्तित किया जाता है तो इसे`'1e-7' 'के रूप में माना जाता है और इसलिए`parseInt`` 1` देता है। `1 / 1999999` की व्याख्या` 5.00000250000125e-7` और `पार्सेइंट`` 5` के रूप में की जाती है।
## `सत्य` और` असत्य` के साथ गणित
चलो कुछ गणित करते हैं:
```js
true +
true(
// -> 2
true + true
) *
(true + true) -
true; // -> 3
```
हममम ... 🤔
### 💡 व्याख्या:
हम मानों को 'संख्या' निर्माता के साथ संख्याओं में भिन्न कर सकते हैं। यह काफी स्पष्ट है कि ` सच`` 1 ` के लिए मजबूर किया जाएगा:
```js
Number(true); // -> 1
```
यूनीरी प्लस ऑपरेटर अपने मूल्य को एक संख्या में बदलने का प्रयास करता है। यह पूर्णांकों और फ़्लोट्स के स्ट्रिंग अभ्यावेदन को परिवर्तित कर सकता है, साथ ही साथ गैर-स्ट्रिंग मान `सत्य`,` असत्य`, और `अशक्त`। यदि यह किसी विशेष मूल्य को पार्स नहीं कर सकता है, तो यह `NaN` का मूल्यांकन करेगा। इसका मतलब है कि हम `सच` को` 1` आसान कर सकते हैं:
```js
+true; // -> 1
```
जब आप जोड़ या गुणा कर रहे होते हैं, तो `ToNumber` विधि लागू होती है। विनिर्देश के अनुसार, यह विधि वापस आती है:
> If `argument` is **true**, return **1**. If `argument` is **false**, return **+0**.
इसलिए हम बूलियन मूल्यों को नियमित संख्या के रूप में जोड़ सकते हैं और सही परिणाम प्राप्त कर सकते हैं।
संगत अनुभाग:
- [**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)
## HTML टिप्पणियाँ जावास्क्रिप्ट में मान्य हैं
आप प्रभावित होंगे, लेकिन `<! -` (जिसे HTML टिप्पणी के रूप में जाना जाता है) जावास्क्रिप्ट में एक मान्य टिप्पणी है।
```js
// valid comment
<!-- valid comment too
```
### 💡 व्याख्या:
Impressed? HTML जैसी टिप्पणियों का उद्देश्य उन ब्राउज़रों को अनुमति देना था जो समझ में नहीं आते थे`<script>` सुंदर ढंग से नीचा दिखाने के लिए टैग। ये ब्राउज़र, उदा। नेटस्केप 1.x अब लोकप्रिय नहीं हैं। तो अब आपके स्क्रिप्ट टैग में HTML कमेंट्स डालने का कोई मतलब नहीं है।
चूंकि Node.js V8 इंजन पर आधारित है, इसलिए HTML- जैसी टिप्पणियां Node.js रनटाइम द्वारा भी समर्थित हैं। इसके अलावा, वे विनिर्देश का एक हिस्सा हैं:
- [**B.1.3** HTML-like Comments](https://www.ecma-international.org/ecma-262/#sec-html-like-comments)
## `NaN` is ~~not~~ a number
Type of `NaN` is a `'number'`:
```js
typeof NaN; // -> 'number'
```
### 💡 व्याख्या:
व्याख्याs of how `typeof` and `instanceof` operators work:
- [**12.5.5** The `typeof` Operator](https://www.ecma-international.org/ecma-262/#sec-typeof-operator)
- [**12.10.4** Runtime Semantics: InstanceofOperator(`O`,`C`)](https://www.ecma-international.org/ecma-262/#sec-instanceofoperator)
## `[]` and `null` are objects
```js
typeof []; // -> 'object'
typeof null; // -> 'object'
// however
null instanceof Object; // false
```
### 💡 व्याख्या:
विनिर्देशन के इस भाग में `टाइपोफ़ 'ऑपरेटर के व्यवहार को परिभाषित किया गया है:
- [**12.5.5** The `typeof` Operator](https://www.ecma-international.org/ecma-262/#sec-typeof-operator)
विनिर्देशन के अनुसार, `टाइपऑफ़` ऑपरेटर [तालिका 35:` टाइपोफ़ `ऑपरेटर परिणाम] (https://www.ecma-international.org/ecma-262/#table-35) के अनुसार एक स्ट्रिंग लौटाता है। `Null`, साधारण, मानक विदेशी और गैर-मानक विदेशी वस्तुओं के लिए, जो`[[कॉल]]`को लागू नहीं करते हैं, यह स्ट्रिंग` `ऑब्जेक्ट`` लौटाता है।
हालाँकि, आप `toString` विधि का उपयोग करके किसी ऑब्जेक्ट के प्रकार की जाँच कर सकते हैं।
```js
Object.prototype.toString.call([]);
// -> '[object Array]'
Object.prototype.toString.call(new Date());
// -> '[object Date]'
Object.prototype.toString.call(null);
// -> '[object Null]'
```
## Magically increasing numbers
```js
999999999999999; // -> 999999999999999
9999999999999999; // -> 10000000000000000
10000000000000000; // -> 10000000000000000
10000000000000000 + 1; // -> 10000000000000000
10000000000000000 + 1.1; // -> 10000000000000002
```
### 💡 व्याख्या:
यह बाइनरी फ्लोटिंग-पॉइंट अंकगणित के लिए IEEE 754-2008 मानक के कारण होता है। इस पैमाने पर, यह निकटतम सम संख्या में गोल होता है। अधिक पढ़ें:
- [**6.1.6** The Number Type](https://www.ecma-international.org/ecma-262/#sec-ecmascript-language-types-number-type)
- [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) on Wikipedia
## Precision of `0.1 + 0.2`
A well-known joke. An addition of `0.1` and `0.2` is deadly precise:
```js
0.1 +
0.2(
// -> 0.30000000000000004
0.1 + 0.2
) ===
0.3; // -> false
```
### 💡 व्याख्या:
The answer for the [”Is floating point math broken?”](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) question on StackOverflow:
> आपके कार्यक्रम में स्थिरांक `0.2` और` 0.3` भी उनके वास्तविक मूल्यों के सन्निकटन होंगे। ऐसा होता है कि निकटतम `डबल` से` 0.2` तर्कसंगत संख्या `0.2` से बड़ा है, लेकिन निकटतम` डबल` से `0.3` तर्कसंगत संख्या` 0.3` से छोटा है। `0.1` और` 0.2` हवाओं का योग तर्कसंगत संख्या `0.3` से बड़ा है और इसलिए आपके कोड में निरंतरता से असहमत है।
यह समस्या इतनी ज्ञात है कि यहां तक कि एक वेबसाइट भी है जिसका नाम [0.30000000000000004.com] (http://0.30000000000000004.com/) है। यह हर भाषा में होता है जो फ़्लोटिंग पॉइंट गणित का उपयोग करता है, न कि केवल जावास्क्रिप्ट।
## पैचिंग नंबर
आप रैपर ऑब्जेक्ट्स को `नंबर` या` स्ट्रिंग` जैसे तरीकों से जोड़ सकते हैं।
```js
Number.prototype.isOne = function() {
return Number(this) === 1;
};
(1.0).isOne(); // -> true
(1).isOne(); // -> true
(2.0)
.isOne()(
// -> false
7
)
.isOne(); // -> false
```
### 💡 व्याख्या:
जाहिर है, आप जावास्क्रिप्ट में किसी भी अन्य ऑब्जेक्ट की तरह `नंबर` ऑब्जेक्ट का विस्तार कर सकते हैं। हालाँकि, यह अनुशंसित नहीं है यदि परिभाषित पद्धति का व्यवहार विनिर्देश का हिस्सा नहीं है। यहाँ `नंबर` की संपत्तियों की सूची दी गई है:
- [**20.1** Number Objects](https://www.ecma-international.org/ecma-262/#sec-number-objects)
## Comparison of three numbers
```js
1 < 2 < 3; // -> true
3 > 2 > 1; // -> false
```
### 💡 व्याख्या:
इस तरह से काम क्यों करता है? खैर, समस्या एक अभिव्यक्ति के पहले भाग में है। यहां देखिए यह कैसे काम करता है:
```js
1 < 2 < 3; // 1 < 2 -> true
true < 3; // true -> 1
1 < 3; // -> true
3 > 2 > 1; // 3 > 2 -> true
true > 1; // true -> 1
1 > 1; // -> false
```
हम इसे ठीक कर सकते हैं _Greater than or equal operator (`>=`)_:
```js
3 > 2 >= 1; // true
```
विनिर्देश में रिलेशनल ऑपरेटरों के बारे में अधिक पढ़ें:
- [**12.10** संबंधपरक संकारक](https://www.ecma-international.org/ecma-262/#sec-relational-operators)
## मजेदार गणित
अक्सर जावास्क्रिप्ट में अंकगणितीय संचालन के परिणाम काफी अप्रत्याशित हो सकते हैं। इन उदाहरणों पर विचार करें:
```js
3 - 1 // -> 2
3 + 1 // -> 4
'3' - 1 // -> 2
'3' + 1 // -> '31'
'' + '' // -> ''
[] + [] // -> ''
{} + [] // -> 0
[] + {} // -> '[object Object]'
{} + {} // -> '[object Object][object Object]'
'222' - -'111' // -> 333
[4] * [4] // -> 16
[] * [] // -> 0
[4, 4] * [4, 4] // NaN
```
### 💡 व्याख्या:
पहले चार उदाहरणों में क्या हो रहा है? जावास्क्रिप्ट में अतिरिक्त समझने के लिए यहां एक छोटी तालिका दी गई है:
```
Number + Number -> addition
Boolean + Number -> addition
Boolean + Boolean -> addition
Number + String -> concatenation
String + Boolean -> concatenation
String + String -> concatenation
```
अन्य उदाहरणों के बारे में क्या? एक `ToPrimitive` और` ToString` तरीकों को इसके अलावा `[]` और `{} के लिए निहित किया जा रहा है। विनिर्देश में मूल्यांकन प्रक्रिया के बारे में और पढ़ें:
- [**12.8.3** The Addition Operator (`+`)](https://www.ecma-international.org/ecma-262/#sec-addition-operator-plus)
- [**7.1.1** ToPrimitive(`input` [,`PreferredType`])](https://www.ecma-international.org/ecma-262/#sec-toprimitive)
- [**7.1.12** ToString(`argument`)](https://www.ecma-international.org/ecma-262/#sec-tostring)
## RegExps का जोड़
क्या आप जानते हैं कि आप इस तरह से नंबर जोड़ सकते हैं?
```js
// Patch a toString method
RegExp.prototype.toString =
function() {
return this.source;
} /
7 /
-/5/; // -> 2
```
### 💡 व्याख्या:
- [**21.2.5.10** get RegExp.prototype.source](https://www.ecma-international.org/ecma-262/#sec-get-regexp.prototype.source)
## स्ट्रिंग्स `स्ट्रिंग` के उदाहरण नहीं हैं
```js
"str"; // -> 'str'
typeof "str"; // -> 'string'
"str" instanceof String; // -> false
```
### 💡 व्याख्या:
`स्ट्रिंग` कंस्ट्रक्टर एक स्ट्रिंग लौटाता है:
```js
typeof String("str"); // -> 'string'
String("str"); // -> 'str'
String("str") == "str"; // -> true
```
Let's try with a `new`:
```js
new String("str") == "str"; // -> true
typeof new String("str"); // -> 'object'
```
वस्तु? वह क्या है?
```js
new String("str"); // -> [String: 'str']
```
विनिर्देश में स्ट्रिंग निर्माता के बारे में अधिक जानकारी:
- [**21.1.1** The String Constructor](https://www.ecma-international.org/ecma-262/#sec-string-constructor)
## बैकटिक्स के साथ कॉलिंग फ़ंक्शन
आइए एक फ़ंक्शन की घोषणा करते हैं जो कंसोल में सभी पैराम्स को लॉग करता है:
```js
function f(...args) {
return args;
}
```
कोई शक नहीं, आप जानते हैं कि आप इस फ़ंक्शन को इस तरह से कॉल कर सकते हैं:
```js
f(1, 2, 3); // -> [ 1, 2, 3 ]
```
लेकिन क्या आप जानते हैं कि आप किसी भी फंक्शन को बैकटिक्स कह सकते हैं।
```js
f`true is ${true}, false is ${false}, array is ${[1, 2, 3]}`;
// -> [ [ 'true is ', ', false is ', ', array is ', '' ],
// -> true,
// -> false,
// -> [ 1, 2, 3 ] ]
```
### 💡 व्याख्या:
यदि आप _Tagged टेम्पलेट शाब्दिक_ से परिचित हैं, तो यह बिल्कुल भी जादू नहीं है। ऊपर दिए गए उदाहरण में, `f` फ़ंक्शन टेम्प्लेट शाब्दिक के लिए एक टैग है। टेम्प्लेट शाब्दिक से पहले टैग आपको फ़ंक्शन के साथ टेम्प्लेट शाब्दिकता को पार्स करने की अनुमति देता है। टैग फ़ंक्शन के पहले तर्क में स्ट्रिंग मानों की एक सरणी होती है। शेष तर्क भावों से संबंधित हैं। उदाहरण:
```js
function template(strings, ...keys) {
// do something with strings and keys…
}
```
यह [जादू के पीछे] (http://mxstbr.blog/2016/11/styled-compenders-magic-explained/) प्रसिद्ध पुस्तकालय जिसे [led स्टाइल-कंपोनेंट्स] कहा जाता है (https://www.styled-compenders.com) /), जो प्रतिक्रिया समुदाय में लोकप्रिय है।
विनिर्देशन के लिए लिंक:
- [**12.3.7** Tagged Templates](https://www.ecma-international.org/ecma-262/#sec-tagged-templates)
## पुकार पुकार पुकार
> Found by [@cramforce](http://twitter.com/cramforce)
```js
console.log.call.call.call.call.call.apply(a => a, [1, 2]);
```
### 💡 व्याख्या:
ध्यान दें, यह आपके दिमाग को तोड़ सकता है! अपने सिर में इस कोड को पुन: उत्पन्न करने का प्रयास करें: हम `लागू` विधि का उपयोग करके` कॉल` विधि लागू कर रहे हैं। अधिक पढ़ें:
- [**19.2.3.3** Function.prototype.call(`thisArg`, ...`args`)](https://www.ecma-international.org/ecma-262/#sec-function.prototype.call)
- [**19.2.3.1 ** Function.prototype.apply(`thisArg`, `argArray`)](https://www.ecma-international.org/ecma-262/#sec-function.prototype.apply)
## A `constructor` property
```js
const c = "constructor";
c[c][c]('console.log("WTF?")')(); // > WTF?
```
### 💡 व्याख्या:
आइए इस उदाहरण पर विचार करें चरण-दर-चरण:
```js
// Declare a new constant which is a string 'constructor'
const c = "constructor";
// c is a string
c; // -> 'constructor'
// Getting a constructor of string
c[c]; // -> [Function: String]
// Getting a constructor of constructor
c[c][c]; // -> [Function: Function]
// Call the Function constructor and pass
// the body of new function as an argument
c[c][c]('console.log("WTF?")'); // -> [Function: anonymous]
// And then call this anonymous function
// The result is console-logging a string 'WTF?'
c[c][c]('console.log("WTF?")')(); // > WTF?
```
एक `Object.prototyp.constructor` उदाहरण ऑब्जेक्ट बनाने वाले` Object` कंस्ट्रक्टर फ़ंक्शन का संदर्भ देता है। स्ट्रिंग के साथ मामले में यह `स्ट्रिंग` है, संख्या के मामले में यह` नंबर` और इसी तरह है।
- एमडीएन के लिए [`Object.prototyp.constructor`] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor)
- [** 19.1.3.1 ** Object.prototype.constructor] (https://www.ecma-international.org/ecma-262/#sec-object.prototyp.constructor)
## वस्तु की संपत्ति की कुंजी के रूप में वस्तु
```js
{ [{}]: {} } // -> { '[object Object]': {} }
```
### 💡 व्याख्या:
यह काम क्यों करता है? यहां हम एक _Computed संपत्ति name_ का उपयोग कर रहे हैं। जब आप उन कोष्ठकों के बीच एक वस्तु को पास करते हैं, तो यह एक स्ट्रिंग के लिए आपत्ति करता है, इसलिए हमें संपत्ति कुंजी `'[ऑब्जेक्ट ऑब्जेक्ट]` `और मूल्य` {} `मिलता है।
हम इस तरह "कोष्ठक नरक" बना सकते हैं:
```js
({ [{}]: { [{}]: {} } }[{}][{}]); // -> {}
// structure:
// {
// '[object Object]': {
// '[object Object]': {}
// }
// }
```
वस्तु शाब्दिक के बारे में यहाँ और अधिक पढ़ें:
- एमडीएन पर (ऑब्जेक्ट इनिशलाइज़र] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Oference/Object_initializer)
- [** १२.२.६ ** वस्तु इनिशियलाइज़र] (http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer)
## प्रोटोटाइपिंग को `__proto__` के साथ एक्सेस करना
जैसा कि हम जानते हैं, आदिमों के प्रोटोटाइप नहीं हैं। हालांकि, अगर हम आदिम के लिए `__proto__` का मान प्राप्त करने का प्रयास करते हैं, तो हमें यह मिलेगा:
```js
(1).__proto__.__proto__.__proto__; // -> null
```
### 💡 व्याख्या:
ऐसा इसलिए होता है क्योंकि जब किसी चीज़ का प्रोटोटाइप नहीं होता है, तो इसे `ToObject` मेथड का इस्तेमाल करके रैपर ऑब्जेक्ट में लपेट दिया जाएगा। तो, चरण-दर-चरण:
```js
(1)
.__proto__(
// -> [Number: 0]
1
)
.__proto__.__proto__(
// -> {}
1
).__proto__.__proto__.__proto__; // -> null
```
यहाँ `__proto__` के बारे में अधिक जानकारी है:
- [** B.2.2.1 ** Object.prototype। ** proto **] (https://www.ecma-international.org/ecma-262/#sec-object.prototype.__proto__)
- [** 7.1.13 ** ToObject (`तर्क`)] (https://www.ecma-international.org/ecma-262/#sec-toobject)
## `` `$ {{वस्तु}}` ``
नीचे दिए गए अभिव्यक्ति का परिणाम क्या है?
```js
`${{ Object }}`;
```
The answer is:
```js
// -> '[object Object]'
```
### 💡 व्याख्या:
हमने एक ऑब्जेक्ट को एक संपत्ति के साथ परिभाषित किया है `Object` का उपयोग करके _Shorthand संपत्ति अंकन_:
`` `Js { वस्तु वस्तु; } `` `
फिर हमने इस ऑब्जेक्ट को टेम्पलेट शाब्दिक में पास कर दिया है, इसलिए उस ऑब्जेक्ट के लिए `toString` विधि कॉल करता है। इसलिए हमें स्ट्रिंग मिलती है `'[ऑब्जेक्ट ऑब्जेक्ट]'`।
- [** १२.२.९ ** टेम्पलेट साहित्य] (https://www.ecma-international.org/ecma-262/#sec-template-literals)
- एमडीएन पर (ऑब्जेक्ट इनिशलाइज़र] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Oference/Object_initializer)
## डिफ़ॉल्ट मानों के साथ विनाशकारी
इस उदाहरण पर विचार करें:
```js
let x,
{ x: y = 1 } = { x };
y;
```
उपरोक्त उदाहरण एक साक्षात्कार के लिए एक महान कार्य है। `Y` का मूल्य क्या है? उत्तर है:
```js
// -> 1
```
### 💡 व्याख्या:
```js
let x,
{ x: y = 1 } = { x };
y;
// ↑ ↑ ↑ ↑
// 1 3 2 4
```
ऊपर के उदाहरण के साथ:
1. हम `x` को बिना किसी मूल्य के घोषित करते हैं, इसलिए यह` अपरिभाषित` है।
2. फिर हम `x` का मान ऑब्जेक्ट प्रॉपर्टी` x` में पैक करते हैं।
3. फिर हम विध्वंस का उपयोग करके `x` का मान निकालते हैं और` y` को असाइन करना चाहते हैं। यदि मान परिभाषित नहीं है, तो हम डिफ़ॉल्ट मान के रूप में `1` का उपयोग करने जा रहे हैं।
4. `y` का मान लौटाएँ।
- [Object initializer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer) at MDN
## डॉट्स और फैल रहा है
ऐरे के प्रसार के साथ दिलचस्प उदाहरणों की रचना की जा सकती है। इस पर विचार करो:
```js
[...[..."..."]].length; // -> 3
```
### 💡 व्याख्या:
क्यों `3`? जब हम [स्प्रेड ऑपरेटर] (http://www.ecma-international.org/ecma-262/6.0/#sec-array-initializer) का उपयोग करते हैं, तो '@@ इट्रेटर' विधि को कहा जाता है, और लौटा हुआ पुनरावृत्ति है मूल्यों को पुनरावृत्त करने के लिए उपयोग किया जाता है। स्ट्रिंग के लिए डिफ़ॉल्ट पुनरावृत्ति एक स्ट्रिंग को वर्णों में फैलाता है। फैलने के बाद, हम इन पात्रों को एक सरणी में पैक करते हैं। फिर हम इस सरणी को फिर से फैलाते हैं और इसे वापस सरणी में पैक करते हैं।
A `'...'` स्ट्रिंग में तीन ``वर्ण होते हैं, इसलिए परिणामी सरणी की लंबाई`3` है।
अब, चरण-दर-चरण:
```js
[...'...'] // -> [ '.', '.', '.' ]
[...[...'...']] // -> [ '.', '.', '.' ]
[...[...'...']].length // -> 3
```
जाहिर है, हम सरणी के तत्वों को जितनी बार चाहें उतनी बार फैला और लपेट सकते हैं:
```js
[...'...'] // -> [ '.', '.', '.' ]
[...[...'...']] // -> [ '.', '.', '.' ]
[...[...[...'...']]] // -> [ '.', '.', '.' ]
[...[...[...[...'...']]]] // -> [ '.', '.', '.' ]
// and so on …
```
## लेबल
कई प्रोग्रामर जावास्क्रिप्ट में लेबल के बारे में नहीं जानते हैं। वे दिलचस्प हैं:
```js
foo: {
console.log("first");
break foo;
console.log("second");
}
// > first
// -> undefined
```
### 💡 व्याख्या:
लेबल स्टेटमेंट का उपयोग `ब्रेक` या` जारी` स्टेटमेंट के साथ किया जाता है। आप लूप की पहचान करने के लिए एक लेबल का उपयोग कर सकते हैं, और फिर प्रोग्राम को लूप को बाधित करना चाहिए या इसके निष्पादन को जारी रखने के लिए `ब्रेक` या` जारी` बयान का उपयोग करें।
ऊपर दिए गए उदाहरण में, हम एक लेबल `foo` की पहचान करते हैं। उसके बाद `कंसोल.लॉग ('पहले');` निष्पादित होता है और फिर हम निष्पादन को बाधित करते हैं।
जावास्क्रिप्ट में लेबल के बारे में और पढ़ें:
- [**13.13** Labelled Statements](https://tc39.github.io/ecma262/#sec-labelled-statements)
- [Labeled statements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label) at MDN
## Nested labels
```js
a: b: c: d: e: f: g: 1, 2, 3, 4, 5; // -> 5
```
### 💡 व्याख्या:
पिछले उदाहरणों के समान, इन लिंक का अनुसरण करें:
- [** १२.१६ ** कोमा संचालक (`,`)] (https://www.ecma-international.org/ecma-262/#sec-comma-operator)
- [** 13.13 ** लेबल किए गए विवरण] (https://tc39.github.io/ecma262/#sec-labelled-statements)
- [लेबल किए गए कथन] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label) MDN पर
## कपटी `कोशिश..चेक`
यह अभिव्यक्ति क्या लौटेगी? `2` या` 3`?
```js
(() => {
try {
return 2;
} finally {
return 3;
}
})();
```
उत्तर `3` है। आश्चर्य चकित?
### # व्याख्या:
- [** 13.15 ** द `कोशिश` स्टेटमेंट] (https://www.ecma-international.org/ecma-262/#sec-try-statement)
## क्या यह कई विरासत है?
नीचे दिए गए उदाहरण पर एक नज़र डालें:
```js
new class F extends (String, Array) {}(); // -> F []
```
क्या यह एक बहु विरासत है? नहीं।
### # व्याख्या:
दिलचस्प हिस्सा `फैली` खंड (`(स्ट्रिंग, सरणी)` का मूल्य है। ग्रुपिंग ऑपरेटर हमेशा अपना अंतिम तर्क देता है, इसलिए `(स्ट्रिंग, एरे)` वास्तव में सिर्फ `एरे` है। इसका मतलब है कि हमने सिर्फ एक वर्ग बनाया है जो `एरे` का विस्तार करता है।
- [**14.5** Class Definitions](https://www.ecma-international.org/ecma-262/#sec-class-definitions)
- [**12.16** Comma Operator (`,`)](https://www.ecma-international.org/ecma-262/#sec-comma-operator)
## एक जनरेटर जो खुद उपजता है
एक जनरेटर के इस उदाहरण पर विचार करें जो स्वयं उपज देता है:
```js
(function* f() {
yield f;
})().next();
// -> { value: [GeneratorFunction: f], done: false }
```
जैसा कि आप देख सकते हैं, लौटाया गया मान एक वस्तु है जिसका ` मान`` एफ ` के बराबर है। उस मामले में, हम ऐसा कुछ कर सकते हैं:
```js
(function* f() {
yield f;
})()
.next()
.value()
.next()(
// -> { value: [GeneratorFunction: f], done: false }
// and again
function* f() {
yield f;
}
)()
.next()
.value()
.next()
.value()
.next()(
// -> { value: [GeneratorFunction: f], done: false }
// and again
function* f() {
yield f;
}
)()
.next()
.value()
.next()
.value()
.next()
.value()
.next();
// -> { value: [GeneratorFunction: f], done: false }
// and so on
// …
```
### 💡 व्याख्या:
यह समझने के लिए कि यह इस तरह क्यों काम करता है, विनिर्देश के इन वर्गों को पढ़ें:
- [** २५ ** नियंत्रण अमूर्त वस्तुएं] (https://www.ecma-international.org/ecma-262/#sec-control-abstraction-objects)
- [** २५.३ ** जेनरेटर ऑब्जेक्ट] (https://www.ecma-international.org/ecma-262/#sec-generator-objects)
## कक्षा का एक वर्ग
इस ओफ़्सेटेड सिंटैक्स प्लेइंग पर विचार करें:
```js
typeof new class {
class() {}
}(); // -> 'object'
```
ऐसा लगता है जैसे हम क्लास के अंदर क्लास घोषित कर रहे हैं। एक त्रुटि होनी चाहिए, हालांकि, हमें स्ट्रिंग '' ऑब्जेक्ट '' मिलता है।
### # व्याख्या:
ECMAScript 5 युग के बाद से _keywords_ को _property names_ के रूप में अनुमति दी गई है। तो इस सरल वस्तु उदाहरण के रूप में इसके बारे में सोचो:
```js
const foo = {
class: function() {}
};
```
और ईएस 6 मानकीकृत शॉर्टहैंड विधि परिभाषाएं। साथ ही, कक्षाएं अनाम हो सकती हैं। इसलिए यदि हम ड्रॉप करते हैं `: फ़ंक्शन` भाग, हम प्राप्त करने जा रहे हैं:
```js
class {
class() {}
}
```
डिफ़ॉल्ट वर्ग का परिणाम हमेशा एक साधारण वस्तु होती है। और इसके टाइपोफ को `ऑब्जेक्ट'` वापस करना चाहिए।
यहाँ और पढ़ें:
- [** १४.३ ** विधि परिभाषाएँ] (https://www.ecma-international.org/ecma-262/#sec-method-definitions)
- [** १४.५ ** कक्षा परिभाषाएँ] (https://www.ecma-international.org/ecma-262/#sec-class-definitions)
## गैर-सहकर्मी वस्तुएं
प्रसिद्ध प्रतीकों के साथ, प्रकार की जबरदस्ती से छुटकारा पाने का एक तरीका है। जरा देखो तो:
```js
function nonCoercible(val) {
if (val == null) {
throw TypeError("nonCoercible should not be called with null or undefined");
}
const res = Object(val);
res[Symbol.toPrimitive] = () => {
throw TypeError("Trying to coerce non-coercible object");
};
return res;
}
```
अब हम इसका उपयोग इस तरह कर सकते हैं:
```js
// objects
const foo = nonCoercible({ foo: "foo" });
foo * 10; // -> TypeError: Trying to coerce non-coercible object
foo + "evil"; // -> TypeError: Trying to coerce non-coercible object
// strings
const bar = nonCoercible("bar");
bar + "1"; // -> TypeError: Trying to coerce non-coercible object
bar.toString() + 1; // -> bar1
bar === "bar"; // -> false
bar.toString() === "bar"; // -> true
bar == "bar"; // -> TypeError: Trying to coerce non-coercible object
// numbers
const baz = nonCoercible(1);
baz == 1; // -> TypeError: Trying to coerce non-coercible object
baz === 1; // -> false
baz.valueOf() === 1; // -> true
```
### 💡 व्याख्या:
- [सेर्गेई रुबनोव द्वारा एक तस्वीर] (https://gist.github.com/chicoxyzzy/5dd24608e886adf5444499896dff1197)
- [** ६.१.५.१ ** अच्छी तरह से ज्ञात प्रतीक] (https://www.ecma-international.org/ecma-262/#sec-well-ogn-symbols)
## मुश्किल तीर कार्य
नीचे दिए गए उदाहरण पर विचार करें:
```js
let f = () => 10;
f(); // -> 10
```
ठीक है, ठीक है, लेकिन इस बारे में क्या:
```js
let f = () => {};
f(); // -> undefined
```
### 💡 व्याख्या:
आप `अपरिभाषित` के बजाय`{}`की उम्मीद कर सकते हैं। ऐसा इसलिए है क्योंकि घुंघराले ब्रेसिज़ तीर फ़ंक्शन के सिंटैक्स का हिस्सा हैं, इसलिए `f` अपरिभाषित वापस आ जाएगा। हालांकि, ब्रैकेट के साथ रिटर्न वैल्यू को संलग्न करके, तीर फ़ंक्शन से सीधे `{}` ऑब्जेक्ट को वापस करना संभव है।
```js
let f = () => ({});
f(); // -> {}
```
## एरो फ़ंक्शंस एक निर्माता नहीं हो सकता है
नीचे दिए गए उदाहरण पर विचार करें:
```js
let f = function() {
this.a = 1;
};
new f(); // -> { 'a': 1 }
```
अब, एक तीर फ़ंक्शन के साथ ऐसा करने का प्रयास करें:
```js
let f = () => {
this.a = 1;
};
new f(); // -> TypeError: f is not a constructor
```
### 💡 व्याख्या:
एरो फ़ंक्शंस को कंस्ट्रक्टर के रूप में इस्तेमाल नहीं किया जा सकता है और नए के साथ उपयोग किए जाने पर एक त्रुटि होगी। क्योंकि एक शाब्दिक `यह` है, और एक` प्रोटोटाइप` संपत्ति नहीं है, इसलिए यह बहुत मतलब नहीं होगा।
## `तर्क` और तीर कार्य
नीचे दिए गए उदाहरण पर विचार करें:
```js
let f = function() {
return arguments;
};
f("a"); // -> { '0': 'a' }
```
अब, एक तीर फ़ंक्शन के साथ ऐसा करने का प्रयास करें:
`` `Js let f = () => तर्क; च ( "एक"); // -> अनट्रेक्टेड रेफरेंस: तर्क को परिभाषित नहीं किया गया है `` `
### # व्याख्या:
एरो फ़ंक्शंस शॉर्ट और लेक्सिकल `this` होने पर ध्यान देने के साथ नियमित फ़ंक्शंस का एक हल्का संस्करण है। उसी समय एरो फ़ंक्शंस `आर्ग्यूमेंट्स` ऑब्जेक्ट के लिए बाइंडिंग प्रदान नहीं करते हैं। एक वैध विकल्प के रूप में एक ही परिणाम प्राप्त करने के लिए `बाकी मापदंडों` का उपयोग करें:
```js
let f = (...args) => args;
f("a");
```
- [Arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) at MDN.
## मुश्किल वापसी
`वापसी` बयान भी मुश्किल है। इस पर विचार करो:
```js
(function() {
return
{
b: 10;
}
})(); // -> undefined
```
### 💡 व्याख्या:
`वापसी` और लौटी हुई अभिव्यक्ति एक ही पंक्ति में होनी चाहिए:
```js
(function() {
return {
b: 10
};
})(); // -> { b: 10 }
```
यह एक अवधारणा के कारण है जिसे स्वचालित अर्धविराम सम्मिलन कहा जाता है, जो स्वचालित रूप से अधिकांश न्यूक्लियर के बाद अर्धविराम सम्मिलित करता है। पहले उदाहरण में, `रिटर्न` स्टेटमेंट और ऑब्जेक्ट शाब्दिक के बीच एक अर्धविराम डाला जाता है, इसलिए फ़ंक्शन` अपरिभाषित` देता है और ऑब्जेक्ट शाब्दिक का कभी मूल्यांकन नहीं किया जाता है।
- [** 11.9.1 ** स्वचालित अर्धविराम सम्मिलन के नियम] (https://www.ecma-international.org/ecma-262/#sec-rules-of-automatic-semicolon-insertion)
- [** 13.10 ** द `रिटर्न` स्टेटमेंट] (https://www.ecma-international.org/ecma-262/#sec-return-statement)
## ऑब्जेक्ट पर कार्य असाइन करना
```js
var foo = {n: 1};
var bar = foo;
foo.x = foo = {n: 2};
foo.x // -> undefined
foo // -> {n: 2}
bar // -> {n: 1, x: {n: 2}}
```
दाएं से बाएं, `{n: 2}` को फू को सौंपा गया है, और इस असाइनमेंट का परिणाम `{n: 2}` को foo.x को सौंपा गया है, इसीलिए बार `{n: 1, x: {है n: 2}} `के रूप में बार फू के लिए एक संदर्भ है। लेकिन क्यों foo.x अपरिभाषित है जबकि bar.x नहीं है?
### 💡 व्याख्या:
फू और बार एक ही ऑब्जेक्ट को संदर्भित करते हैं `{n: 1}`, और लवलीन को असाइनमेंट से पहले हल किया जाता है। `foo = {n: 2}` एक नई वस्तु बना रहा है, और इसलिए उस नई वस्तु को संदर्भित करने के लिए foo अपडेट किया गया है। यहाँ चाल को 'foo.x = ...' में foo किया गया है क्योंकि एक लैवल्यू को पहले से हल किया गया था और अभी भी पुराने `foo = {n: 1}` ऑब्जेक्ट को संदर्भित करता है और इसे x मान जोड़कर अपडेट करें। उस श्रृंखला असाइनमेंट के बाद, बार अभी भी पुराने फू ऑब्जेक्ट को संदर्भित करता है, लेकिन फू नए `{n: 2}` ऑब्जेक्ट को संदर्भित करता है, जहां एक्स मौजूद नहीं है।
यह इसके बराबर है:
```js
var foo = {n: 1};
var bar = foo;
foo = {n: 2} // -> {n: 2}
bar.x = foo // -> {n: 1, x: {n: 2}}
// bar.x point to the address of the new foo object
// it's not equivalent to: bar.x = {n: 2}
```
## सरणियों के साथ ऑब्जेक्ट गुण तक पहुँचना
```js
var obj = { property: 1 };
var array = ["property"];
obj[array]; // -> 1
```
छद्म बहुआयामी सरणियों के बारे में क्या?
```js
var map = {};
var x = 1;
var y = 2;
var z = 3;
map[[x, y, z]] = true;
map[[x + 10, y, z]] = true;
map["1,2,3"]; // -> true
map["11,2,3"]; // -> true
```
### 💡 व्याख्या:
कोष्ठक `[]` परिचालक उत्तीर्ण अभिव्यक्ति को `स्ट्रींग` का उपयोग करके परिवर्तित करता है। स्ट्रिंग में एक तत्व तत्व को परिवर्तित करना स्ट्रिंग में निहित तत्व को परिवर्तित करने के लिए एक समान है:
```js
["property"].toString(); // -> 'property'
```
## Null and Relational Operators
```js
null > 0; // false
null == 0; // false
null >= 0; // true
```
### 💡 व्याख्या:
लंबी कहानी छोटी, यदि ` शून्य`` 0 ` से कम है, तो `झूठा` है, तो` शून्य` = 0` `सत्य` है। इसके लिए [यहाँ] (https://blog.campvanilla.com/javascript-the-curious-case-of-null-0-7b131644e274) की गहन व्याख्या पढ़ें।
## `Number.toFixed ()` विभिन्न संख्याएँ प्रदर्शित करता है
`Number.toFixed ()` विभिन्न ब्राउज़रों में थोड़ा अजीब व्यवहार कर सकता है। इस उदाहरण को देखें:
```js
(0.7875).toFixed(3);
// Firefox: -> 0.787
// Chrome: -> 0.787
// IE11: -> 0.788
(0.7876).toFixed(3);
// Firefox: -> 0.788
// Chrome: -> 0.788
// IE11: -> 0.788
```
### 💡 व्याख्या:
हालांकि आपकी पहली वृत्ति यह हो सकती है कि IE11 सही है और फ़ायरफ़ॉक्स / क्रोम गलत है, वास्तविकता यह है कि फ़ायरफ़ॉक्स / क्रोम अधिक सीधे संख्याओं के लिए मानक मान रहे हैं (IEEE-754 फ़्लोटिंग पॉइंट), जबकि IE11 उन्हें पूरी तरह से अवज्ञा करता है (जो शायद है ) स्पष्ट परिणाम देने का प्रयास।
आप देख सकते हैं कि कुछ त्वरित परीक्षणों के साथ ऐसा क्यों होता है:
```js
// 5 नीचे गोलाई के विषम परिणाम की पुष्टि करें
(0.7875).toFixed(3); // -> 0.787
// It looks like it's just a 5 when you expand to the
// limits of 64-bit (double-precision) float accuracy
(0.7875).toFixed(14); // -> 0.78750000000000
// But what if you go beyond the limit?
(0.7875).toFixed(20); // -> 0.78749999999999997780
```
फ़्लोटिंग पॉइंट नंबरों को आंतरिक रूप से दशमलव अंकों की एक सूची के रूप में संग्रहीत नहीं किया जाता है, लेकिन एक अधिक जटिल कार्यप्रणाली के माध्यम से जो छोटी अशुद्धि पैदा करता है जो आमतौर पर स्ट्रींग और इसी तरह की कॉल से गोल होते हैं, लेकिन वास्तव में आंतरिक रूप से मौजूद होते हैं।
इस मामले में, कि अंत में "5" वास्तव में एक सच के नीचे एक बहुत छोटा सा अंश था। किसी भी उचित लंबाई पर इसे 5 के रूप में प्रस्तुत करना ... लेकिन यह वास्तव में आंतरिक रूप से 5 नहीं है।
IE11, हालांकि, केवल (शून्य) मामले में भी अंत तक संलग्न शून्य के साथ मूल्य इनपुट की रिपोर्ट करेगा, क्योंकि यह हार्डवेयर सीमाओं से परेशानियों को कम करने के लिए मूल्य को जबरन गोल करना प्रतीत होता है।
संदर्भ के लिए देखें `नोट 2` ECMA-262 पर` toFixed` के लिए परिभाषा।
- [**20.1.3.3** Number.prototype.toFixed (`fractionDigits`)](https://www.ecma-international.org/ecma-262//#sec-number.prototype.tofixed)
## `Math.max()` less than `Math.min()`
```js
Math.min(1, 4, 7, 2); // -> 1
Math.max(1, 4, 7, 2); // -> 7
Math.min(); // -> Infinity
Math.max(); // -> -Infinity
Math.min() > Math.max(); // -> true
```
### 💡 व्याख्या:
- चार्ली हार्वे द्वारा Math.max () Math.min () से कम क्यों है? (Https://charlieharvey.org.uk/page/why_math_max_is_less_than_math_min)
## तुलना `null` से` 0` तक
निम्नलिखित अभिव्यक्तियाँ विरोधाभास का परिचय देती हैं:
```js
null == 0; // -> false
null > 0; // -> false
null >= 0; // -> true
```
`Null` न तो बराबर हो सकता है और न ही` 0` से अधिक, अगर `null> = 0` वास्तव में` true` है? (यह भी उसी तरह से कम के साथ काम करता है।)
### 💡 व्याख्या:
जिस तरह से इन तीनों भावों का मूल्यांकन किया जाता है, वे सभी भिन्न हैं और इस अप्रत्याशित व्यवहार के उत्पादन के लिए जिम्मेदार हैं।
सबसे पहले, अमूर्त समानता तुलना `null == 0`। आम तौर पर, यदि यह ऑपरेटर दोनों तरफ के मूल्यों की ठीक से तुलना नहीं कर सकता है, तो यह दोनों संख्याओं में परिवर्तित हो जाता है और संख्याओं की तुलना करता है। फिर, आप निम्न व्यवहार की अपेक्षा कर सकते हैं:
```js
// This is not what happens
(null == 0 + null) == +0;
0 == 0;
true;
```
हालांकि, कल्पना के एक करीबी पढ़ने के अनुसार, संख्या रूपांतरण वास्तव में उस तरफ नहीं होता है जो `अशक्त` या` अपरिभाषित` है। इसलिए, यदि आपके पास समान चिह्न के एक तरफ `null` है, तो दूसरी तरफ` true` वापस करने के लिए अभिव्यक्ति के लिए `null` या` अनिर्धारित` होना चाहिए। चूंकि यह मामला नहीं है, `झूठ` वापस आ गया है।
अगला, संबंधपरक तुलना `अशक्त> 0`। एल्गोरिथ्म यहाँ, अमूर्त समानता ऑपरेटर के विपरीत, _will_ एक संख्या के लिए `null` कन्वर्ट। इसलिए, हमें यह व्यवहार मिलता है:
```js
null > 0
+null = +0
0 > 0
false
```
अंत में, संबंधपरक तुलना `शून्य> = 0`। आप तर्क दे सकते हैं कि यह अभिव्यक्ति `शून्य> 0 का परिणाम होना चाहिए null == 0`; अगर ऐसा होता, तो उपरोक्त परिणामों का मतलब यह होगा कि यह भी `गलत` होगा। हालांकि, वास्तव में `> =` ऑपरेटर बहुत अलग तरीके से काम करता है, जो मूल रूप से `<` ऑपरेटर के विपरीत लेना है। क्योंकि ऊपर से ऑपरेटर से अधिक के साथ हमारा उदाहरण भी ऑपरेटर से कम के लिए है, इसका मतलब है कि इस अभिव्यक्ति का वास्तव में मूल्यांकन किया जाता है:
```js
null >= 0;
!(null < 0);
!(+null < +0);
!(0 < 0);
!false;
true;
```
- [**7.2.12** Abstract Relational Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-relational-comparison)
- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)
## समान परिवर्तनशील पुनर्वितरण
JS चरों को फिर से दिखाने की अनुमति देता है:
```js
a;
a;
// यह भी मान्य है
a, a;
```
सख्त मोड में भी काम करता है:
```js
var a, a, a;
var a;
var a;
```
### 💡 व्याख्या:
सभी परिभाषाओं को एक परिभाषा में मिला दिया गया है।
- [** 13.3.2 ** चर कथन] (https://www.ecma-international.org/ecma-262/#sec-variable-statement)
## डिफ़ॉल्ट व्यवहार Array.prototyp.sort ()
कल्पना करें कि आपको संख्याओं की एक संख्या को क्रमबद्ध करना होगा।
```
[ 10, 1, 3 ].sort() // -> [ 1, 10, 3 ]
```
### 💡 व्याख्या:
डिफ़ॉल्ट सॉर्ट ऑर्डर तत्वों को स्ट्रिंग्स में परिवर्तित करने पर बनाया गया है, फिर UTF-16 कोड इकाइयों के उनके अनुक्रमों की तुलना करते हैं।
- [**22.1.3.25** Array.prototype.sort ( comparefn )](https://www.ecma-international.org/ecma-262/#sec-array.prototype.sort)
### संकेत
यदि आप कुछ भी लेकिन स्ट्रिंग को क्रमबद्ध करने की कोशिश करते हैं, तो 'तुलना' पास करें।
```
[ 10, 1, 3 ].sort((a, b) => a - b) // -> [ 1, 3, 10 ]
```
# 📚 अन्य संसाधन
- [wtfjs.com] (http://wtfjs.com/) - वेब की भाषा के लिए उन विशेष अनियमितताओं, विसंगतियों और सीधे सादे दर्दभरे क्षणों का एक संग्रह।
- [वट] (https://www.destroyallsoftware.com/talks/wat) - कोडमश 2012 से गैरी बर्नहार्ट द्वारा एक बिजली की बात
- [क्या ... जावास्क्रिप्ट?] (Https://www.youtube.com/watch?v=2pL28CcEijU) - काइल सिम्पसन फॉरवर्ड 2 के लिए जावास्क्रिप्ट से "पागल को बाहर निकालने" का प्रयास करते हैं। वह क्लीनर, अधिक सुरुचिपूर्ण, अधिक पठनीय कोड बनाने में आपकी सहायता करना चाहता है, फिर लोगों को खुले स्रोत समुदाय में योगदान करने के लिए प्रेरित करता है।
# 🎓 License
[![CC 4.0][license-image]][license-url]
© [Denys Dovhan](http://denysdovhan.com)
[license-url]: http://www.wtfpl.net
[license-image]: https://img.shields.io/badge/License-WTFPL%202.0-lightgrey.svg?style=flat-square
[npm-url]: https://npmjs.org/package/wtfjs
[npm-image]: https://img.shields.io/npm/v/wtfjs.svg?style=flat-square
================================================
FILE: README-it-it.md
================================================
# What the f\*ck JavaScript?
[![WTFPL 2.0][license-image]][license-url]
[![NPM version][npm-image]][npm-url]
> Una raccolta di snippet ingannevoli e divertenti scritti in JavaScript
JavaScript è un ottimo linguaggio. Ha una sintassi semplice, un grande ecosistema e, quello che conta veramente, una community fantastica.
Allo stesso tempo, sappiamo che JavaScript è un linguaggio abbastanza strano con delle parti cervellotiche. Alcune di queste possono rendere il nostro lavoro un inferno, alcune invece possono farci ridere a crepapelle.
L'idea per WTFJS è di [Brian Leroux](https://twitter.com/brianleroux). Questo elenco è largamente ispirato al suo talk [**“WTFJS”** at dotJS 2012](https://www.youtube.com/watch?v=et8xNAc2ic8):
[](https://www.youtube.com/watch?v=et8xNAc2ic8)
# Node Packaged Manuscript
Puoi installare questo manuale con `npm`. Lancia semplicemente:
```
$ npm install -g wtfjs
```
Ora dovresti essere in grado di eseguire `wtfjs` dalla riga di comando. Altrimenti puoi continuare tranquillamente a leggerlo qui.
Il codice sorgente lo puoi trovare qui: <https://github.com/denysdovhan/wtfjs>
# Traduzioni
Attualmente **wtfjs** è disponibile nelle seguenti lingue:
- [中文版](./README-zh-cn.md)
- [Français](./README-fr-fr.md)
- [Português do Brasil](./README-pt-br.md)
- [Polski](./README-pl-pl.md)
- [Italiano](./README-it-it.md)
[**Richiedi un'altra traduzione**][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
<!-- prettier-ignore-start -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
# Table of Contents
- [💪🏻 Motivazione](#-motivazione)
- [✍🏻 Notazione](#-notazione)
- [👀 Esempi](#-esempi)
- [`[]` è uguale a `![]`](#-%C3%A8-uguale-a-)
- [`true` è diverso da `![]`, ma anche diverso da `[]`](#true-%C3%A8-diverso-da--ma-anche-diverso-da-)
- [true è false](#true-%C3%A8-false)
- [baNaNa](#banana)
- [`NaN` non è `NaN`](#nan-non-%C3%A8-nan)
- [È un fail](#%C3%A8-un-fail)
- [`[]` è truthy, ma non `true`](#-%C3%A8-truthy-ma-non-true)
- [`null` è falsy, ma non `false`](#null-%C3%A8-falsy-ma-non-false)
- [`document.all` è un object, ma è undefined](#documentall-%C3%A8-un-object-ma-%C3%A8-undefined)
- [Il numero più piccolo rappresentabile è maggiore di zero](#il-numero-pi%C3%B9-piccolo-rappresentabile-%C3%A8-maggiore-di-zero)
- [function non è una function](#function-non-%C3%A8-una-function)
- [Sommare array](#sommare-array)
- ["Trailing commas" in un array](#trailing-commas-in-un-array)
- [L'operatore di uguaglianza sugli array è un mostro](#loperatore-di-uguaglianza-sugli-array-%C3%A8-un-mostro)
- [`undefined` e `Number`](#undefined-e-number)
- [`parseInt` è bast\*\*do](#parseint-%C3%A8-bast%5C%5Cdo)
- [Math con `true` e `false`](#math-con-true-e-false)
- [I commenti HTML sono validi anche in JavaScript](#i-commenti-html-sono-validi-anche-in-javascript)
- [`NaN` è ~~not~~ a number](#nan-%C3%A8-not-a-number)
- [`[]` e `null` sono objects](#-e-null-sono-objects)
- [Incrementare numeri magicamente](#incrementare-numeri-magicamente)
- [La precisione di `0.1 + 0.2`](#la-precisione-di-01--02)
- [Patchare numeri](#patchare-numeri)
- [Confrontare tre numeri](#confrontare-tre-numeri)
- [Matematica spassosa](#matematica-spassosa)
- [Somma di RegExps](#somma-di-regexps)
- [Le stringhe non sono istanze di `String`](#le-stringhe-non-sono-istanze-di-string)
- [Richiamare funzioni con le backticks](#richiamare-funzioni-con-le-backticks)
- [Call call call](#call-call-call)
- [Una proprietà chiamata `constructor`](#una-propriet%C3%A0-chiamata-constructor)
- [Un Object usato come key nelle property di un oggetto](#un-object-usato-come-key-nelle-property-di-un-oggetto)
- [Accedere ai prototypes con `__proto__`](#accedere-ai-prototypes-con-__proto__)
- [`` `${{Object}}` ``](#-object-)
- [Destructuring con valori di default](#destructuring-con-valori-di-default)
- [Puntini e lo spreading](#puntini-e-lo-spreading)
- [Labels](#labels)
- [Labels annidate](#labels-annidate)
- [Un `try..catch` insidioso](#un-trycatch-insidioso)
- [Si tratta di ereditarietà multipla?](#si-tratta-di-ereditariet%C3%A0-multipla)
- [Un generator che produce se stesso](#un-generator-che-produce-se-stesso)
- [Una classe di tipo class](#una-classe-di-tipo-class)
- [Oggetti non-coercible](#oggetti-non-coercible)
- [Arrow functions strambe](#arrow-functions-strambe)
- [Arrow functions non possono essere un costruttore](#arrow-functions-non-possono-essere-un-costruttore)
- [`arguments` e arrow functions](#arguments-e-arrow-functions)
- [Uno strano return](#uno-strano-return)
- [Concatenare assegnamenti su un object](#concatenare-assegnamenti-su-un-object)
- [Accedere alle properties di un object con gli array](#accedere-alle-properties-di-un-object-con-gli-array)
- [Null e gli operatori relazionali](#null-e-gli-operatori-relazionali)
- [`Number.toFixed()` mostra numeri diversi](#numbertofixed-mostra-numeri-diversi)
- [`Math.max()` più piccolo di `Math.min()`](#mathmax-pi%C3%B9-piccolo-di-mathmin)
- [Confrontare `null` con `0`](#confrontare-null-con-0)
- [Alcune ridichiarazioni di variabili](#alcune-ridichiarazioni-di-variabili)
- [Comportamento di default di Array.prototype.sort()](#comportamento-di-default-di-arrayprototypesort)
- [resolve() non restituisce un'istanza di Promise](#resolve-non-restituisce-unistanza-di-promise)
- [📚 Other resources](#-other-resources)
- [🎓 License](#-license)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- prettier-ignore-end -->
# 💪🏻 Motivazione
> Just for fun
>
> — _[**“Just for Fun: The Story of an Accidental Revolutionary”**](https://en.wikipedia.org/wiki/Just_for_Fun), Linus Torvalds_
Lo scopo principale di questo elenco è quello di raccogliere alcuni esempi strambi e mostrarne il loro funzionamento, se possibile. Semplicemente per il fatto che è divertente imparare qualcosa che non sapevamo prima.
Se sei un principiante puoi utilizzare questi appunti per approfondire JavaScript. Spero che questi appunti ti motivino a leggerne le specifiche.
Se sei uno sviluppatore senior, considera questi esempi come un'ottimo punto di riferimento per tutte quelle stranezze e stramberie del tuo amato JavaScript.
Ad ogni modo, leggilo. Probabilmente imparerai qualcosa di nuovo.
# ✍🏻 Notazione
**`// ->`** viene utilizzato per indicare il risultato di un'espressione. Ad esempio:
```js
1 + 1; // -> 2
```
**`// >`** significa il risultato di `console.log` o di un altro output. Ad esempio:
```js
console.log("hello, world!"); // > hello, world!
```
**`//`** è semplicemente un commento utilizzato per le spiegazioni. Esempio:
```js
// Assegnare una funzione ad una costante
const foo = function() {};
```
# 👀 Esempi
## `[]` è uguale a `![]`
Array è uguale a not array:
```js
[] == ![]; // -> true
```
### 💡 Spiegazione:
L'opratore di abstract equality converte entrambi gli operandi prima di confrontarli, e diventano entrambi `0` per ragioni differenti. Gli Array sono truthy, quindi sulla destra, l'opposto di un valore truthy è `false`, che viene quindi forzato a diventare uno `0`. Sul lato sinistro però l'array vuoto viene forzato a diventare un numero senza prima essere convertito in un valore booleano, e gli array vuoti vengono forzati a `0` a prescindere che siano truthy.
Qui possiamo vedere come viene semplificata l'espressione:
```js
+[] == +![];
0 == +false;
0 == 0;
true;
```
Vedi anche [`[]` è truthy, ma non `true`](#-is-truthy-but-not-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` è diverso da `![]`, ma anche diverso da `[]`
Array è diverso da `true`, ma anche not Array è diverso da `true`;
Array è uguale a `false`, ma anche not Array è uguale a `false`:
```js
true == []; // -> false
true == ![]; // -> false
false == []; // -> true
false == ![]; // -> true
```
### 💡 Spiegazione:
```js
true == []; // -> false
true == ![]; // -> false
// Secondo le specifiche
true == []; // -> false
toNumber(true); // -> 1
toNumber([]); // -> 0
1 == 0; // -> false
true == ![]; // -> false
![]; // -> false
true == false; // -> false
```
```js
false == []; // -> true
false == ![]; // -> true
// Secondo le specifiche
false == []; // -> true
toNumber(false); // -> 0
toNumber([]); // -> 0
0 == 0; // -> true
false == ![]; // -> true
![]; // -> false
false == false; // -> true
```
- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)
## true è false
```js
!!"false" == !!"true"; // -> true
!!"false" === !!"true"; // -> true
```
### 💡 Spiegazione:
Considera questo, step-by-step:
```js
// true è 'truthy' e rappresentato dal valore 1 (number), 'true' in formato stringa è NaN.
true == "true"; // -> false
false == "false"; // -> false
// 'false' non è la stringa vuota, quindi è un valore 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'
```
Questo è un giochino old-school in JavaScript, rivisitato. L'originale è questo:
```js
"foo" + +"bar"; // -> 'fooNaN'
```
### 💡 Spiegazione:
L'espressione viene valutata come `'foo' + (+'bar')`, che converte `'bar'` in "not a number".
- [**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` non è `NaN`
```js
NaN === NaN; // -> false
```
### 💡 Spiegazione:
Le specifiche definiscono rigorosamente la logica dietro a questo comportamento:
> 1. Se `Type(x)` è diverso da `Type(y)`, return **false**.
> 2. Se `Type(x)` è Number, allora
> 1. Se `x` è **NaN**, return **false**.
> 2. Se `y` è **NaN**, return **false**.
> 3. … … …
>
> — [**7.2.14** Strict Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-strict-equality-comparison)
Seguendo la definizione di `NaN` da quella dell'IEEE:
> Sono possibili quattro relazioni mutuamente esclusive: less than, equal, greater than, e unordered. L'ultimo caso si presenta quando almeno un operando è NaN. Tutt i NaN se comparati risulteranno unordered, inclusa la comparazione con se stesso.
>
> — [“What is the rationale for all comparisons returning false for IEEE754 NaN values?”](https://stackoverflow.com/questions/1565164/1573715#1573715) at StackOverflow
## È un fail
Non crederai ai tuoi occhi, ma...
```js
(![] + [])[+[]] +
(![] + [])[+!+[]] +
([![]] + [][[]])[+!+[] + [+[]]] +
(![] + [])[!+[] + !+[]];
// -> 'fail'
```
### 💡 Spiegazione:
Rompendo quell'ammasso di simboli in pezzettini, possiamo notare che il seguente pattern si ripete spesso:
```js
![] + []; // -> 'false'
![]; // -> false
```
Quindi proviamo a sommare `[]` a `false`. Ma a causa di una serie di chiamate interne (`binary + Operator` -> `ToPrimitive` -> `[[DefaultValue]]`) otteniamo la conversione dell'operando a destra in una stringa:
```js
![] + [].toString(); // 'false'
```
Se pensiamo ad una stringa come un Array, possiamo accedere al suo primo elemento con `[0]`:
```js
"false"[0]; // -> 'f'
```
Il resto è ovvio, ma la `i` è complicata. La `i` in `fail` viene ottenuta generando la stringa `'falseundefined'` e prendendo l'elemento all'indice `['10']`
## `[]` è truthy, ma non `true`
Un array è un valore truthy, ma non è uguale a `true`.
```js
!![] // -> true
[] == true // -> false
```
### 💡 Spiegazione:
Ecco i link alle sezioni corrispondenti della specifica 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` è falsy, ma non `false`
Nonostante il fatto che `null` sia un valore falsy, non è uguale a `false`.
```js
!!null; // -> false
null == false; // -> false
```
Allo stesso modo, altri valori falsy, come `0` o `''` sono uguali a `false`.
```js
0 == false; // -> true
"" == false; // -> true
```
### 💡 Spiegazione:
La spiegazione è la stessa dell'esempio precedente. Ecco il link corrispondente:
- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)
## `document.all` è un object, ma è undefined
> ⚠️ Questo fa parte delle Browser API e non funziona su Node.js ⚠️
Nonostante il fatto che `document.all` sia un oggetto array-like e permette l'accesso al DOM della pagina, risponde alla funzione `typeof` con `undefined`.
```js
document.all instanceof Object; // -> true
typeof document.all; // -> 'undefined'
```
Allo stesso modo, `document.all` è diverso da `undefined`.
```js
document.all === undefined; // -> false
document.all === null; // -> false
```
Ma contemporaneamente:
```js
document.all == null; // -> true
```
### 💡 Spiegazione:
> `document.all` veniva utilizzato per accedere agli elementi del DOM, nelle vecchie versioni di IE. Nonostante non sia mai diventato uno standard, veniva ampiamente utilizzato in codice JS non proprio recentissimo. Quando vennero rilasciate le nuove APIs (come `document.getElementById`) questa API divenne obsoleta e il comitato dello standard dovette decidere cosa farne. A causa del suo uso spropositato l'API venne mantenuta ma venne introdotta una violazione intenzionale nelle speficiche di JavaScript.
> Il motivo per il quale risponde a `false` quando si utilizza l'operatore di [Strict Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-strict-equality-comparison) con `undefined`, mentre `true` quando si utilizza l'operatore di [Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison) è a causa della violazione intenzionale inserita nella specifica che la permette in modo esplicito.
> — [“Obsolete features - document.all”](https://html.spec.whatwg.org/multipage/obsolete.html#dom-document-all) at 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) at YDKJS - Types & Grammar
## Il numero più piccolo rappresentabile è maggiore di zero
`Number.MIN_VALUE` è il numero più piccolo rappresentabile, che è maggiore di zero:
```js
Number.MIN_VALUE > 0; // -> true
```
### 💡 Spiegazione:
> `Number.MIN_VALUE` è `5e-324`, ovvero il più piccolo numero positivo che può essere rappresentato con precisione float, cioè quello che si può ottenere il più vicino possibile allo zero. Definisce la migliore risoluzione che un tipo di dato float può fornire.
>
> Il numero più piccolo in assoluto è `Number.NEGATIVE_INFINITY` nonostante non sia effettivamente un tipo numerico.
>
> — [“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)
## function non è una function
> ⚠️ Un bug presente in V8 v5.5 o inferiore (Node.js <=7) ⚠️
Tutti conoscerete la noiosa _undefined is not a function_, ma questa?
```js
// Dichiara una classe che estende null
class Foo extends null {}
// -> [Function: Foo]
new Foo() instanceof null;
// > TypeError: function is not a function
// > at … … …
```
### 💡 Spiegazione:
Questo non è parte delle specifiche. È semplicemente un bug che ora è stato risolto, quindi non dovrebbero esserci problemi con questo in futuro.
## Sommare array
E se provassimo a sommare due array?
```js
[1, 2, 3] + [4, 5, 6]; // -> '1,2,34,5,6'
```
### 💡 Spiegazione:
Viene svolta la concatenazione. il procedimento step-by-step è il seguente:
```js
[1, 2, 3] +
[4, 5, 6][
// chiama toString()
(1, 2, 3)
].toString() +
[4, 5, 6].toString();
// concatenazione
"1,2,3" + "4,5,6";
// ->
("1,2,34,5,6");
```
## "Trailing commas" in un array
Creiamo un array con 4 elementi vuoti. Nonostante ciò, si ottiene un array con 3 elementi, a causa delle "trailing commas":
```js
let a = [, , ,];
a.length; // -> 3
a.toString(); // -> ',,'
```
### 💡 Spiegazione:
> **Trailing commas** (anche chiamate "final commas") sono utili quando si aggiungono nuovi elementi, parametri o proprietà in codice JavaScript. Se si vuole aggiungere una nuova proprietà si può semplicemente aggiungere una nuova riga senza modificare quella precedente, se quella linea presenta già una virgola alla fine. Questo rende i diffs dei sistemi di version-control più puliti e modificare il codice è leggermente meno problematico.
>
> — [Trailing commas](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas) at MDN
## L'operatore di uguaglianza sugli array è un mostro
L'operatore di uguaglianza sugli array in JS è un mostro, come possiamo osservare sotto:
```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
```
### 💡 Spiegazione:
Guarda attentamente gli esempi precedenti! Il comportamento viene spiegato nella sezione [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison) delle specifiche.
## `undefined` e `Number`
Se non passiamo argomenti al costruttore di `Number`, otteniamo `0`. Il valore `undefined` viene assegnato di default quando non viene passato alcun valore, quindi possiamo aspettarci che `Number` senza parametri prenda `undefined` come valore del suo parametro. Invece quando inseriamo `undefined`, otteniamo `NaN`.
```js
Number(); // -> 0
Number(undefined); // -> NaN
```
### 💡 Spiegazione:
In base alle specifiche:
1. Se non viene passato alcun parametro durante l'invocazione della funzione, `n` viene valorizzato a `+0`.
2. Altrimenti, `n` sarà il risultato di `ToNumber(value)`.
3. Nel caso di `undefined`, `ToNumber(undefined)` deve restituire `NaN`.
Qui la sezione corrispondente:
- [**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` è bast\*\*do
`parseInt` è famoso per le sue stranezze:
```js
parseInt("f*ck"); // -> NaN
parseInt("f*ck", 16); // -> 15
```
**💡 Spiegazione:** Questo avviene perchè `parseInt` continuerà a svolgere il parsing carattere per carattere fino a che non trova un carattere che non riconosce. La `f` in `'f*ck'` è la rappresentazione esadecimale di `15`.
Svolgere il parsing di `Infinity` a integer è qualcosa di...
```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
```
Attenzione anche quando si svolge il parsing di `null`:
```js
parseInt(null, 24); // -> 23
```
**💡 Spiegazione:**
> Si sta convertendo `null` alla stringa `"null"` e provando poi a convertirla a sua volta. Per le radici da 0 a 23, non ci sono numerali per svolgere la conversione, quindi viene restituito NaN. A 24, `"n"`, la 14-esima lettera, viene aggiunta al sistema di numerazione. A 31, `"u"`, la 21-esima lettera, viene aggiunta e l'intera stringa può essere decodificata. A 37 non c'è più un valido insieme di numerazione che si può generare quindi viene restituito `NaN`.
>
> — [“parseInt(null, 24) === 23… wait, what?”](https://stackoverflow.com/questions/6459758/parseintnull-24-23-wait-what) at StackOverflow
Non dimentichiamoci del sistema di numerazione ottale:
```js
parseInt("06"); // 6
parseInt("08"); // 8 se è presente il supporto a ECMAScript 5
parseInt("08"); // 0 se assente il supporto a ECMAScript 5
```
**💡 Spiegazione:** Se la stringa in input inizia con "0", la radice è 8 (octal) o 10 (decimal). Quale radice viene scelta dipende dall'implementazione. ECMAScript 5 specifica l'utilizzo di 10 (decimal), Ma non è ancora supportata da tutti i browser. Per questo motivo è sempre meglio specificare una radice quando si utilizza `parseInt`.
`parseInt` converte sempre l'input in stringa:
```js
parseInt({ toString: () => 2, valueOf: () => 1 }); // -> 2
Number({ toString: () => 2, valueOf: () => 1 }); // -> 1
```
Attenzione quando si svolge il parsin di valori in virgola mobile:
```js
parseInt(0.000001); // -> 0
parseInt(0.0000001); // -> 1
parseInt(1 / 1999999); // -> 5
```
**💡 Spiegazione:** `ParseInt` prende una stringa come argomento e restituisce un intero in base alla radice specificata. `ParseInt` inoltre elimina tutto ciò che viene dopo e incluso il primo carattere non numerico nella stringa passata come parametro. `0.000001` Viene convertito nella stringa `"0.000001"` e `parseInt` restituisce `0`. Quando `0.0000001` viene convertito in stringa viene interpretato come `"1e-7"` e quindi `parseInt` restituisce `1`. `1/1999999` viene interpretato come `5.00000250000125e-7` e `parseInt` restituisce `5`.
## Math con `true` e `false`
Facciamo un po' di calcoli:
```js
true -
true +
// -> 2
(true + true) *
(true + true) -
true; // -> 3
```
Hmmm... 🤔
### 💡 Spiegazione:
Possiamo forzare dei valori a numeri utilizzando il costruttore di `Number`. È abbastanza ovvio che `true` venga forzato a `1`:
```js
Number(true); // -> 1
```
L'operatore unario `+` prova a convertire il suo valore in un numero. Può convertire la rappresentazione testuale di interie e float, così come i valori non testuali `true`, `false`, e `null`. Se non riesce a svolgere il parsing di un particolare valore, restuituirà `NaN`. Questo significa che possiamo forzare facilmente `true` a `1`:
```js
+true; // -> 1
```
Quando svolgiamo addizioni o moltiplicazioni, viene invocato il metodo `ToNumber`. In base alla specifica questo metodo restituisce:
> Se `parametro` è **true**, restituisci **1**. Se `parametro` è **false**, restituisci **+0**.
È questo il motivo per il quale possiamo sommare valori booleani e ottenere risultati corretti.
Sezioni corrispondenti:
- [**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)
## I commenti HTML sono validi anche in JavaScript
Non ci crederai, ma `<!--` (ovvero un commento in HTML) è un commento valido in JavaScript.
```js
// commento valido
<!-- anche questo
```
### 💡 Spiegazione:
Stupito? Commenti HTML-like sono stati pensati per permettere ai browser che non capivano il tag `<script>` di degradare in modo soft. Questi browser, ad esempio Netscape 1.x non sono più diffusi. Quindi non c'è proprio più alcun motivo per inserire commenti HTML nei tag `script`
Dato che Node.js è basato sull'engine V8, i commenti HTML-like sono supportati anche dal runtime di the Node.js. Inoltre sono parte delle specifiche:
- [**B.1.3** HTML-like Comments](https://www.ecma-international.org/ecma-262/#sec-html-like-comments)
## `NaN` è ~~not~~ a number
Il tipo di `NaN` è `'number'`:
```js
typeof NaN; // -> 'number'
```
### 💡 Spiegazione:
Spiegazione di come funzionano gli operatori `typeof` e `instanceof`:
- [**12.5.5** The `typeof` Operator](https://www.ecma-international.org/ecma-262/#sec-typeof-operator)
- [**12.10.4** Runtime Semantics: InstanceofOperator(`O`,`C`)](https://www.ecma-international.org/ecma-262/#sec-instanceofoperator)
## `[]` e `null` sono objects
```js
typeof []; // -> 'object'
typeof null; // -> 'object'
// però
null instanceof Object; // false
```
### 💡 Spiegazione:
Il comportamento dell'operatore `typeof` è definito nella seguente sezione delle specifiche:
- [**12.5.5** The `typeof` Operator](https://www.ecma-international.org/ecma-262/#sec-typeof-operator)
Secondo le specifiche, l'operatore `typeof` restituisce una stringa in base alla [Table 35: `typeof` Operator Results](https://www.ecma-international.org/ecma-262/#table-35). Per `null`, gli oggetti ordinari, esotici standard e non standard che non implementano `[[Call]]`, restituisce la stringa `"object"`.
Comunque si può anche controllare il tipo di un oggetto utilizzando il metodo `toString`.
```js
Object.prototype.toString.call([]);
// -> '[object Array]'
Object.prototype.toString.call(new Date());
// -> '[object Date]'
Object.prototype.toString.call(null);
// -> '[object Null]'
```
## Incrementare numeri magicamente
```js
999999999999999; // -> 999999999999999
9999999999999999; // -> 10000000000000000
10000000000000000; // -> 10000000000000000
10000000000000000 + 1; // -> 10000000000000000
10000000000000000 + 1.1; // -> 10000000000000002
```
### 💡 Spiegazione:
Questo è causato dallo standard IEEE 754-2008 per l'aritmetica binaria dei numeri in virgola mobile. A questa grandezze numeriche, arrotonda al numero pari più vicino. Leggi di più qui:
- [**6.1.6** The Number Type](https://www.ecma-international.org/ecma-262/#sec-ecmascript-language-types-number-type)
- [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) on Wikipedia
## La precisione di `0.1 + 0.2`
Un giochino ben noto. La somma di `0.1` e `0.2` è completamente sbagliata:
```js
0.1 +
0.2(
// -> 0.30000000000000004
0.1 + 0.2
) ===
0.3; // -> false
```
### 💡 Spiegazione:
La risposta alla domanda [”La matematica in virgola mobile è completamente rotta? ”](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) su StackOverflow:
> Le costanti `0.2` e `0.3` nel programma saranno approssimazioni del loro vero valore. Il valore `double` più vicino a `0.2` è più grande del numero razionale `0.2` ma il `double` più vicino a `0.3` è più piccolo del numero razionale `0.3`. La somma di `0.1` e `0.2` risulta essere più grande del numero razionale `0.3` e quindi risultando diverso dalla costante presente nel codice.
Questo problema è talmente noto che esiste anche il sito web [0.30000000000000004.com](http://0.30000000000000004.com/). Capita in tutti i linguaggi di programmazione che svolgono calcoli in virgola mobile, non solo JavaScript.
## Patchare numeri
Possiamo aggiungere metodi nostri agli oggetti wrapper come `Number` o `String`.
```js
Number.prototype.isOne = function() {
return Number(this) === 1;
};
(1.0).isOne(); // -> true
(1).isOne(); // -> true
(2.0)
.isOne()(
// -> false
7
)
.isOne(); // -> false
```
### 💡 Spiegazione:
Ovviamente possiamo estendere l'oggetto `Number` così come ogni altro oggetto in JavaScript. Non è comunque una pratica consigliata se il metodo definito non è parte delle specifiche. Ecco la lista delle proprietà dell'oggetto `Number`:
- [**20.1** Number Objects](https://www.ecma-international.org/ecma-262/#sec-number-objects)
## Confrontare tre numeri
```js
1 < 2 < 3; // -> true
3 > 2 > 1; // -> false
```
### 💡 Spiegazione:
Perchè funziona in questo modo? Beh, il problema è nella prima parte dell'espressione. Ecco come funziona:
```js
1 < 2 < 3; // 1 < 2 -> true
true < 3; // true -> 1
1 < 3; // -> true
3 > 2 > 1; // 3 > 2 -> true
true > 1; // true -> 1
1 > 1; // -> false
```
Possiamo correggerlo con l'operatore _Greater than or equal (`>=`)_:
```js
3 > 2 >= 1; // true
```
Leggi più a riguardo degli operatori relazionali nelle specifiche:
- [**12.10** Relational Operators](https://www.ecma-international.org/ecma-262/#sec-relational-operators)
## Matematica spassosa
Spesso il risultato delle operazioni aritmetiche in JavaScript risulta essere abbastanza strano. Consideriamo questi esempi:
```js
3 - 1 // -> 2
3 + 1 // -> 4
'3' - 1 // -> 2
'3' + 1 // -> '31'
'' + '' // -> ''
[] + [] // -> ''
{} + [] // -> 0
[] + {} // -> '[object Object]'
{} + {} // -> '[object Object][object Object]'
'222' - -'111' // -> 333
[4] * [4] // -> 16
[] * [] // -> 0
[4, 4] * [4, 4] // NaN
```
### 💡 Spiegazione:
Cosa succede nei primi quattro esempi? Ecco una piccola tabella per comprendere la somma in JavaScript:
```
Number + Number -> addition
Boolean + Number -> addition
Boolean + Boolean -> addition
Number + String -> concatenation
String + Boolean -> concatenation
String + String -> concatenation
```
E per quanto riguarda gli altri esempi? I metodi `ToPrimitive` e `ToString` vengono chiamati implicitamente per `[]` e `{}` prima della somma. Leggi di più riguardo a questo processo nelle specifiche:
- [**12.8.3** The Addition Operator (`+`)](https://www.ecma-international.org/ecma-262/#sec-addition-operator-plus)
- [**7.1.1** ToPrimitive(`input` [,`PreferredType`])](https://www.ecma-international.org/ecma-262/#sec-toprimitive)
- [**7.1.12** ToString(`argument`)](https://www.ecma-international.org/ecma-262/#sec-tostring)
In particolare l'eccezione è in `{} + []`. Il motivo per cui differisce da `[] + {}` è che, senza parentesi, viene interpretato come un blocco di codice seguito dall'operatore unario +, convertendo `[]` in un numero. Come viene spiegato di seguito:
```js
{
// qui un blocco di codice
}
+[]; // -> 0
```
Per ottenere lo stesso risultato di `[] + {}` possiamo racchiuderlo tra parentesi.
```js
({} + []); // -> [object Object]
```
## Somma di RegExps
Sapevi che si possono sommare numero in questo modo?
```js
// Patch a toString method
RegExp.prototype.toString =
function() {
return this.source;
} /
7 /
-/5/; // -> 2
```
### 💡 Spiegazione:
- [**21.2.5.10** get RegExp.prototype.source](https://www.ecma-international.org/ecma-262/#sec-get-regexp.prototype.source)
## Le stringhe non sono istanze di `String`
```js
"str"; // -> 'str'
typeof "str"; // -> 'string'
"str" instanceof String; // -> false
```
### 💡 Spiegazione:
Il costruttore di `String` restituisce una stringa:
```js
typeof String("str"); // -> 'string'
String("str"); // -> 'str'
String("str") == "str"; // -> true
```
Proviamo con `new`:
```js
new String("str") == "str"; // -> true
typeof new String("str"); // -> 'object'
```
Object? eh?
```js
new String("str"); // -> [String: 'str']
```
Più informazioni sul costruttore di String nelle specifiche:
- [**21.1.1** The String Constructor](https://www.ecma-international.org/ecma-262/#sec-string-constructor)
## Richiamare funzioni con le backticks
Dichiariamo una funzione che logga tutti i parametri nella console:
```js
function f(...args) {
return args;
}
```
Senza dubbio, saprai che possiamo richiamarla nel modo seguente:
```js
f(1, 2, 3); // -> [ 1, 2, 3 ]
```
Ma sapevi di poter chiamare qualsiasi funzione con le backticks?
```js
f`true is ${true}, false is ${false}, array is ${[1, 2, 3]}`;
// -> [ [ 'true is ', ', false is ', ', array is ', '' ],
// -> true,
// -> false,
// -> [ 1, 2, 3 ] ]
```
### 💡 Spiegazione:
Beh, questa non è per niente magia se hai familiarità con i _Tagged template literals_. Nell'esempio precedente, la funzione f `f` è un tag per i template literal. I tag prima dei template literals permettono di svolgere il parsing dei template con una funzione. Il primo parametro di una "funzione tag" contiene un array di stringhe. I parametri restanti sono relativi alle espressioni. Ad esempio:
```js
function template(strings, ...keys) {
// fai qualcosa con strings and keys…
}
```
Questa è la [magia dietro](http://mxstbr.blog/2016/11/styled-components-magic-explained/) famosa libreria chiamata [💅 styled-components](https://www.styled-components.com/), molto popolare tra la community di React.
Link alle specifiche:
- [**12.3.7** Tagged Templates](https://www.ecma-international.org/ecma-262/#sec-tagged-templates)
## Call call call
> Trovato da [@cramforce](http://twitter.com/cramforce)
```js
console.log.call.call.call.call.call.apply(a => a, [1, 2]);
```
### 💡 Spiegazione:
Attenzione, ti può mettere in crisi il cervello! Prova ad eseguire questo codice a mente: stiamo applicando il metodo `call` usando il metodo `apply`.
Leggi di più:
- [**19.2.3.3** Function.prototype.call(`thisArg`, ...`args`)](https://www.ecma-international.org/ecma-262/#sec-function.prototype.call)
- [**19.2.3.1 ** Function.prototype.apply(`thisArg`, `argArray`)](https://www.ecma-international.org/ecma-262/#sec-function.prototype.apply)
## Una proprietà chiamata `constructor`
```js
const c = "constructor";
c[c][c]('console.log("WTF?")')(); // > WTF?
```
### 💡 Spiegazione:
Consideriamo questo esempio passo passo:
```js
// Dichiariamo una costante che è la stringa 'constructor'
const c = "constructor";
// c è una stringa
c; // -> 'constructor'
// Otteniamo il costruttore di string
c[c]; // -> [Function: String]
// Otteniamo il costruttore di constructor
c[c][c]; // -> [Function: Function]
// chiamiamo la funzione costruttore e gli passiamo
// il corpo di una nuova funzione come parametro
c[c][c]('console.log("WTF?")'); // -> [Function: anonymous]
// Chiamiamo la funzione anonima risultante
// Il risultato è loggare sulla console la stringa 'WTF?'
c[c][c]('console.log("WTF?")')(); // > WTF?
```
`Object.prototype.constructor` restituisce un riferimento al costruttore di `Object` che ha creato l'oggetto. Con le stringhe è `String`, nel caso dei numeri è `Number` e così via.
- [`Object.prototype.constructor`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor) at MDN
- [**19.1.3.1** Object.prototype.constructor](https://www.ecma-international.org/ecma-262/#sec-object.prototype.constructor)
## Un Object usato come key nelle property di un oggetto
```js
{ [{}]: {} } // -> { '[object Object]': {} }
```
### 💡 Spiegazione:
Perchè funziona così? Qui stiamo utilizzando le _Computed property name_. Quando passiamo un oggetto tra parentesi quadre, forza la conversione di quell'oggetto a stringa, quindi otteniamo la proprietà `'[object Object]'` e il valore `{}`.
Possiamo realizzare un "brackets hell" in questo modo:
```js
({ [{}]: { [{}]: {} } }[{}][{}]); // -> {}
// structure:
// {
// '[object Object]': {
// '[object Object]': {}
// }
// }
```
Leggi di più a riguardo degli object literals qui:
- [Object initializer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer) at MDN
- [**12.2.6** Object Initializer](http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer)
## Accedere ai prototypes con `__proto__`
Come sappiamo, i tipi primitivi non hanno prototipi. Però, se proviamo ad ottenere il valore di `__proto__` per i tipi primitivi, otteniamo questo:
```js
(1).__proto__.__proto__.__proto__; // -> null
```
### 💡 Spiegazione:
Questo accade perchè quando qualcosa non ha un prototype, verrà inserito in un oggetto wrapper con un metodo `ToObject`. Quindi, passo passo:
```js
(1)
.__proto__(
// -> [Number: 0]
1
)
.__proto__.__proto__(
// -> {}
1
).__proto__.__proto__.__proto__; // -> null
```
Qui più informazioni riguardo a `__proto__`:
- [**B.2.2.1** Object.prototype.**proto**](https://www.ecma-international.org/ecma-262/#sec-object.prototype.__proto__)
- [**7.1.13** ToObject(`argument`)](https://www.ecma-international.org/ecma-262/#sec-toobject)
## `` `${{Object}}` ``
Quale è il risultato dell'espressione qui sotto?
```js
`${{ Object }}`;
```
La risposta è:
```js
// -> '[object Object]'
```
### 💡 Spiegazione:
Abbiamo definito un oggetto con una proprietà `Object` usando la _Shorthand property notation_:
```js
{
Object: Object;
}
```
Quindi abbiamo passato questo oggetto al template literal, seguirà la chiamata al metodo `toString` per quell'oggetto. Ecco perchè otteniamo la stringa `'[object Object]'`.
- [**12.2.9** Template Literals](https://www.ecma-international.org/ecma-262/#sec-template-literals)
- [Object initializer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer) at MDN
## Destructuring con valori di default
Considera l'esempio seguente:
```js
let x,
{ x: y = 1 } = { x };
y;
```
L'esempio precedente è un ottima domanda per un colloquio di lavoro. Quale è il valore di `y`? La risposta è:
```js
// -> 1
```
### 💡 Spiegazione:
```js
let x,
{ x: y = 1 } = { x };
y;
// ↑ ↑ ↑ ↑
// 1 3 2 4
```
Con l'esempio precedente:
1. Dichiariamo `x` senza alcun valore, quindi risulta `undefined`.
2. Quindi inseriamo il valore di `x` all'interno della proprietà `x` dell'oggetto.
3. Quindi estraiamo il valore di `x` usando il destructuring e lo assegniamo a `y`. Se il valore non è definito, allora utilizziamo `1` come valore di default.
4. Restituiamo il valore di `y`.
- [Object initializer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer) su MDN
## Puntini e lo spreading
Si possono realizzare esempi interessanti utilizzando l'operatore di spreading e gli array. Considera questo:
```js
[...[..."..."]].length; // -> 3
```
### 💡 Spiegazione:
Perchè `3`? Quando utilizziamo [l'operatore di spread](http://www.ecma-international.org/ecma-262/6.0/#sec-array-initializer), viene chiamato il metodo `@@iterator`, e l'iteratore che viene restituito viene utilizzato per ottenere i valori sui quali iterare. L'iteratore di default per le stringhe separa la stringa in caratteri. Dopo lo spreading, vengono inseriti questi valori in un array. Quindi viene svolto nuovamente lo spread sull'array e il risultato viene nuovamente inserito al suo interno.
La stringa `'...'` è composta da tre caratteri `.`, quindi la dimensione dell'array risultante è `3`.
Ora, passo passo:
```js
[...'...'] // -> [ '.', '.', '.' ]
[...[...'...']] // -> [ '.', '.', '.' ]
[...[...'...']].length // -> 3
```
Chiaramente, possiamo svolgere questo procedimento di spread e wrap quante volte vogliamo:
```js
[...'...'] // -> [ '.', '.', '.' ]
[...[...'...']] // -> [ '.', '.', '.' ]
[...[...[...'...']]] // -> [ '.', '.', '.' ]
[...[...[...[...'...']]]] // -> [ '.', '.', '.' ]
// and so on …
```
## Labels
Sono in pochi i programmatori che sono a conoscenza delle Labels in JavaScript. Sono abbastanza interessanti:
```js
foo: {
console.log("first");
break foo;
console.log("second");
}
// > first
// -> undefined
```
### 💡 Spiegazione:
L'istruzione etichettata viene utilizzata con le istruzioni di `break` o `continue`. Possiamo usare un'etichetta per identificare costrutto iterativo, e usare le istruzioni `break` o `continue` per indicare se il programma deve interrompere l'iterazione o continuarla.
Nell'esempio precedente, identifichiamo l'etichetta `foo`. Dopo che `console.log('first');` viene eseguita l'esecuzione viene fermata.
Approfondisci le etichette in JavaScript:
- [**13.13** Labelled Statements](https://tc39.github.io/ecma262/#sec-labelled-statements)
- [Labeled statements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label) su MDN
## Labels annidate
```js
a: b: c: d: e: f: g: 1, 2, 3, 4, 5; // -> 5
```
### 💡 Spiegazione:
Simile agli esempi precedenti, clicca sui seguenti link:
- [**12.16** Comma Operator (`,`)](https://www.ecma-international.org/ecma-262/#sec-comma-operator)
- [**13.13** Labelled Statements](https://tc39.github.io/ecma262/#sec-labelled-statements)
- [Labeled statements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label) su MDN
## Un `try..catch` insidioso
Cosa restituisce questa espressione? `2` o `3`?
```js
(() => {
try {
return 2;
} finally {
return 3;
}
})();
```
La risposta è `3`. Sorpreso?
### 💡 Spiegazione:
- [**13.15** The `try` Statement](https://www.ecma-international.org/ecma-262/#sec-try-statement)
## Si tratta di ereditarietà multipla?
Dai uno sguardo all'esempio sottostante:
```js
new class F extends (String, Array) {}(); // -> F []
```
Si tratta di ereditarietà multipla? Negativo.
### 💡 Spiegazione:
La parte interessante è il valore della clausola (`(String, Array)`) di `extends`. L'operatore di grouping restituisce sempre il suo ultimo parametro, quindi `(String, Array)` è semplicemente `Array`. Questo significa che abbiamo creato una classe che estende `Array`.
- [**14.5** Class Definitions](https://www.ecma-international.org/ecma-262/#sec-class-definitions)
- [**12.16** Comma Operator (`,`)](https://www.ecma-international.org/ecma-262/#sec-comma-operator)
## Un generator che produce se stesso
Guarda questo esempio di generator che produce se stesso:
```js
(function* f() {
yield f;
})().next();
// -> { value: [GeneratorFunction: f], done: false }
```
Come possiamo notare, il valore restituito è un oggetto con `value` uguale a `f`. In quel caso, possiamo fare una cosa del genere:
```js
(function* f() {
yield f;
})()
.next()
.value()
.next()(
// -> { value: [GeneratorFunction: f], done: false }
// and again
function* f() {
yield f;
}
)()
.next()
.value()
.next()
.value()
.next()(
// -> { value: [GeneratorFunction: f], done: false }
// and again
function* f() {
yield f;
}
)()
.next()
.value()
.next()
.value()
.next()
.value()
.next();
// -> { value: [GeneratorFunction: f], done: false }
// and così via
// …
```
### 💡 Spiegazione:
Per capirne il suo funzionamento, leggi queste sezioni delle specifiche:
- [**25** Control Abstraction Objects](https://www.ecma-international.org/ecma-262/#sec-control-abstraction-objects)
- [**25.3** Generator Objects](https://www.ecma-international.org/ecma-262/#sec-generator-objects)
## Una classe di tipo class
Considera questa sintassi offuscata in gioco:
```js
typeof new class {
class() {}
}(); // -> 'object'
```
Sembra la dichiarazione di una classe all'interno di un'altra classe. Dovrebbe essere un errore, invece otteniamo `'object'`.
### 💡 Spiegazione:
Da ECMAScript 5, possiamo usare le _keywords_ come _property names_. Quindi immaginalo come nel seguente esempio:
```js
const foo = {
class: function() {}
};
```
ES6 ha standardizzato la definizione compatta per i metodi. Inoltre, le classi possono essere anonime. Quindi se togliamo la parte con `: function`, otteniamo:
```js
class {
class() {}
}
```
Il risultato di una default class è sempre un oggetto semplice. E il tuo typeof dovrebbe restituire `'object'`.
Leggi di più qui:
- [**14.3** Method Definitions](https://www.ecma-international.org/ecma-262/#sec-method-definitions)
- [**14.5** Class Definitions](https://www.ecma-international.org/ecma-262/#sec-class-definitions)
## Oggetti non-coercible
Con i ben noti, esiste un modo per evitare la type-coercion. Guarda un po':
```js
function nonCoercible(val) {
if (val == null) {
throw TypeError("nonCoercible should not be called with null or undefined");
}
const res = Object(val);
res[Symbol.toPrimitive] = () => {
throw TypeError("Trying to coerce non-coercible object");
};
return res;
}
```
Adesso possiamo utilizzarla in questo modo:
```js
// objects
const foo = nonCoercible({ foo: "foo" });
foo * 10; // -> TypeError: Trying to coerce non-coercible object
foo + "evil"; // -> TypeError: Trying to coerce non-coercible object
// strings
const bar = nonCoercible("bar");
bar + "1"; // -> TypeError: Trying to coerce non-coercible object
bar.toString() + 1; // -> bar1
bar === "bar"; // -> false
bar.toString() === "bar"; // -> true
bar == "bar"; // -> TypeError: Trying to coerce non-coercible object
// numbers
const baz = nonCoercible(1);
baz == 1; // -> TypeError: Trying to coerce non-coercible object
baz === 1; // -> false
baz.valueOf() === 1; // -> true
```
### 💡 Spiegazione:
- [A gist by Sergey Rubanov](https://gist.github.com/chicoxyzzy/5dd24608e886adf5444499896dff1197)
- [**6.1.5.1** Well-Known Symbols](https://www.ecma-international.org/ecma-262/#sec-well-known-symbols)
## Arrow functions strambe
Considera l'esempio sottostante:
```js
let f = () => 10;
f(); // -> 10
```
Okay, va bene, ma guarda questo:
```js
let f = () => {};
f(); // -> undefined
```
### 💡 Spiegazione:
Potresti aspettarti `{}` anzichè `undefined`. Questo è perchè le parentesi graffe fanno parte della sintassi per le arrow functions, quindi `f` restituirà undefined. È comunque possibile restituire l'oggetto `{}` direttamente da una arrow function, racchiudendo il valore di ritorno tra parentesi.
```js
let f = () => ({});
f(); // -> {}
```
## Arrow functions non possono essere un costruttore
Considera l'esempio sottostante:
```js
let f = function() {
this.a = 1;
};
new f(); // -> f { 'a': 1 }
```
Ora, prova a fare la stessa cosa con una arrow function:
```js
let f = () => {
this.a = 1;
};
new f(); // -> TypeError: f is not a constructor
```
### 💡 Spiegazione:
Le arrow function non possono essere utilizzate come costruttore e lanceranno un errore se usate con `new`. Dato che hanno un `this` lessicale, e non hanno la proprietà `prototype`, non avrebbe molto senso.
## `arguments` e arrow functions
Considera l'esempio sottostante:
```js
let f = function() {
return arguments;
};
f("a"); // -> { '0': 'a' }
```
Ora, prova a fare la stessa cosa con una arrow function:
```js
let f = () => arguments;
f("a"); // -> Uncaught ReferenceError: arguments is not defined
```
### 💡 Spiegazione:
Le arrow functions sono una versione alleggerita delle funzioni tradizionali con un focus sull'essere concise e con un `this` lessicale. Allo stesso tempo le arrow function non forniscono un binding per l'oggetto `arguments`. Un'alternativa valida per ottenere lo stesso risultato è utilizzare i `rest parameters`:
```js
let f = (...args) => args;
f("a");
```
- [Arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) at MDN.
## Uno strano return
anche l'istruzione `return` può essere complicata. Considera questo:
<!-- prettier-ignore-start -->
```js
(function() {
return
{
b: 10;
}
})(); // -> undefined
```
<!-- prettier-ignore-end -->
### 💡 Spiegazione:
`return` e l'espressione da restituire devono essere sulla stessa linea:
```js
(function() {
return {
b: 10
};
})(); // -> { b: 10 }
```
Questo a causa di un concetto chiamato Automatic Semicolon Insertion, che inserisce automagicamente punti e virgola dopo la maggior parte degli a capo. Nel primo esempio, c'è un punto e virgola inserito tra l'istruzione `return` e l'oggetto, quindi la funzione restituisce `undefined` e l'oggetto non viene mai valutato.
- [**11.9.1** Rules of Automatic Semicolon Insertion](https://www.ecma-international.org/ecma-262/#sec-rules-of-automatic-semicolon-insertion)
- [**13.10** The `return` Statement](https://www.ecma-international.org/ecma-262/#sec-return-statement)
## Concatenare assegnamenti su un object
```js
var foo = { n: 1 };
var bar = foo;
foo.x = foo = { n: 2 };
foo.x; // -> undefined
foo; // -> {n: 2}
bar; // -> {n: 1, x: {n: 2}}
```
Da destra a sinistra, `{n: 2}` viene assegnato a foo, e il risultato di questo assegnamento `{n: 2}` viene assegnato a foo.x, ecco perchè bar è `{n: 1, x: {n: 2}}` in quanto bar è un riferimento a foo. Ma perchè foo.x è undefined mentre bar.x non lo è?
### 💡 Spiegazione:
Foo e bar referenziano lo stesso oggetto `{n: 1}`, e gli lvalues vengono risolti prima dell'assegnamento. `foo = {n: 2}` sta creando un nuovo oggetto, quindi foo viene aggiornato per referenziare il nuovo oggetto. Il trick qui è in `foo.x = ...` in quanto il lvalue è stato risolto precedentemente e referenzia ancora il vecchio oggetto `foo = {n: 1}` e lo aggiorna inserendo il valore x. Dopo questa catena di assegnamenti, bar continua a referenziare il vecchio oggetto foo, ma foo referenzia il nuovo oggetto `{n: 2}`, dove x non esiste.
È equivalente a:
```js
var foo = { n: 1 };
var bar = foo;
foo = { n: 2 }; // -> {n: 2}
bar.x = foo; // -> {n: 1, x: {n: 2}}
// bar.x point to the address of the new foo object
// it's not equivalent to: bar.x = {n: 2}
```
## Accedere alle properties di un object con gli array
```js
var obj = { property: 1 };
var array = ["property"];
obj[array]; // -> 1
```
E per quanto concerne gli array pseudo-multidimensionali?
```js
var map = {};
var x = 1;
var y = 2;
var z = 3;
map[[x, y, z]] = true;
map[[x + 10, y, z]] = true;
map["1,2,3"]; // -> true
map["11,2,3"]; // -> true
```
### 💡 Spiegazione:
L'operatore parentesi quadre `[]` converte l'espressione usando il metodo `toString`. Convertire un array di un solo elemento in una stringa è come convertire l'elemento contenuto nell'array in stringa.
```js
["property"].toString(); // -> 'property'
```
## Null e gli operatori relazionali
```js
null > 0; // false
null == 0; // false
null >= 0; // true
```
### 💡 Spiegazione:
Per farla breve, se `null` che è minore di `0` è `false`, allora `null >= 0` è `true`. Leggi la spiegazione approfondita per questo [qui](https://blog.campvanilla.com/javascript-the-curious-case-of-null-0-7b131644e274).
## `Number.toFixed()` mostra numeri diversi
`Number.toFixed()` può comportarsi in modo bizzarro in certi browser. Guarda l'esempio seguente:
```js
(0.7875).toFixed(3);
// Firefox: -> 0.787
// Chrome: -> 0.787
// IE11: -> 0.788
(0.7876).toFixed(3);
// Firefox: -> 0.788
// Chrome: -> 0.788
// IE11: -> 0.788
```
### 💡 Spiegazione:
L'istinto potrebbe farci pensare che IE11 sia corretto e Firefox/Chrome sbaglino, la realtà è che Firefox/Chrome stanno rispettando gli standard per i numeri in virgola mobile (IEEE-754 Floating Point), mentre IE11 sta evitando di rispettarli (quello che probabilmente è) uno sforzo per restituire dei risultati più chiari.
Possiamo vedere perchè questo accade con un semplice test:
```js
// Confermare lo strano risultato dell'arrotondamento per difetto di 5
(0.7875).toFixed(3); // -> 0.787
// Sembra essere 5 quando si estende il
// limite a 64-bit (double-precision) di precisione
(0.7875).toFixed(14); // -> 0.78750000000000
// Ma se si supera il limite?
(0.7875).toFixed(20); // -> 0.78749999999999997780
```
I numeri floating point non sono memorizzati come una sequenza di cifre decimali, ma attraverso un metodo più elaborato che produce delle piccole inacuratezze the solitamente vengono eliminate dalle chiamate a toString o simili, ma queste imprecisioni rimangono comunque presenti internamente.
In questo caso, il "5" alla fine era un numero infinitesimamente più piccolo del vero 5. Arrotondandolo ad una precisione ragionevole verrà mostrato come 5... ma internamente non è un 5.
IE11, invece, mostrerà il valore dato in input con degli zeri in coda, anche nel caso di toFixed(20), in quanto sembra forzare l'arrotondamento del valore per evitare problematiche causate dai limiti hardware.
Guarda il riferimento a `NOTE 2` sulla definizione per `toFixed` nelle specifiche ECMA-262.
- [**20.1.3.3** Number.prototype.toFixed (`fractionDigits`)](https://www.ecma-international.org/ecma-262//#sec-number.prototype.tofixed)
## `Math.max()` più piccolo di `Math.min()`
```js
Math.min(1, 4, 7, 2); // -> 1
Math.max(1, 4, 7, 2); // -> 7
Math.min(); // -> Infinity
Math.max(); // -> -Infinity
Math.min() > Math.max(); // -> true
```
### 💡 Spiegazione:
- [Perchè Math.max() è più piccolo di Math.min()?](https://charlieharvey.org.uk/page/why_math_max_is_less_than_math_min) by Charlie Harvey
## Confrontare `null` con `0`
La seguente espressione sembra introdurre una contraddizione:
```js
null == 0; // -> false
null > 0; // -> false
null >= 0; // -> true
```
Come può `null` non essere uguale a, o maggiore di `0`, se `null >= 0` è effettivamente `true`? (Funziona anche con "inferiore a" nello stesso modo.)
### 💡 Spiegazione:
Il modo in cui queste tre espressioni vengono valutate sono tutti diversi ed è per questo che viene prodotto questo comportamento un po' inaspettato.
Per prima cosa analizziamo il comportamento dell'operatore di abstract equality comparison, `null == 0`.
Solitamente, se l'operatore non riesce a confrontare i suoi operanti in modo opportuno, li converte in numeri e compara questi ultimo. Quindi ci si può aspettare il seguente comportamento:
```js
// This is not what happens
(null == 0 + null) == +0;
0 == 0;
true;
```
Invece, secondo una lettura attenta delle specifiche, la conversione a numero non avviene per l'operando che ha valore `null` o `undefined`. Quindi, se abbiamo `null` da un lato del simbolo uguale, l'altro lato deve essere `null` o `undefined` per fare in modo che venga restituito `true`. Dato che non è questo il caso, verrà restituito `false`.
Ora analizziamo l'operatore di comparazione `null > 0`. Qui l'algoritmo, a differenza dell'operatore di abstract equality, _convertirà_ `null` in un numero. Quindi il comportamento sarà il seguente:
```js
null > 0
+null = +0
0 > 0
false
```
Infine, analizziamo l'operatore relazionale `null >= 0`. Si può obiettare che questa espressione dovrebbe essere il risultato di `null > 0 || null == 0`; se fosse così, allora il risultato dell'espressione dovrebbe essere `false`. Invece l'operatore `>=` funziona in un modo completamente diverso, dove praticamente prende l'opposto dell'operatore `<`. Dato che l'esempio con l'operatore "maggiore di" produce lo stesso valore dell'operatore "minore di", l'espressione verrà valutata nel modo seguente:
```js
null >= 0;
!(null < 0);
!(+null < +0);
!(0 < 0);
!false;
true;
```
- [**7.2.12** Abstract Relational Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-relational-comparison)
- [**7.2.13** Abstract Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)
## Alcune ridichiarazioni di variabili
JS permette la ridichiarazione di variabili:
```js
a;
a;
// È valida anche questa
a, a;
```
Funziona anche in modalità strict:
```js
var a, a, a;
var a;
var a;
```
### 💡 Spiegazione:
Tutte le definizione sono state unite in una sola.
- [**13.3.2** Variable Statement](https://www.ecma-international.org/ecma-262/#sec-variable-statement)
## Comportamento di default di Array.prototype.sort()
Supponiamo di voler ordinare un array di numeri.
```
[ 10, 1, 3 ].sort() // -> [ 1, 10, 3 ]
```
### 💡 Spiegazione:
L'ordinamento di default viene realizzato convertendo gli elementi in stringhe, quindi confrontando i loro valore in UTF-16.
- [**22.1.3.25** Array.prototype.sort ( comparefn )](https://www.ecma-international.org/ecma-262/#sec-array.prototype.sort)
### Suggerimento
Passa una `comparefn` se vuoi ordinare qualcosa che non è una stringa.
```
[ 10, 1, 3 ].sort((a, b) => a - b) // -> [ 1, 3, 10 ]
```
## resolve() non restituisce un'istanza di Promise
```javascript
const theObject = {
a: 7
};
const thePromise = new Promise((resolve, reject) => {
resolve(theObject);
}); // -> Instance object di Promise
thePromise.then(value => {
console.log(value === theObject); // -> true
console.log(value); // -> { a: 7 }
});
```
Il `value` che viene risolto da `thePromise` è esattamente `theObject`.
E se inserissimo un'altra `Promise` all'interno della funzione `resolve`?
```javascript
const theObject = new Promise((resolve, reject) => {
resolve(7);
}); // -> Promise instance object
const thePromise = new Promise((resolve, reject) => {
resolve(theObject);
}); // -> Promise instance object
thePromise.then(value => {
console.log(value === theObject); // -> false
console.log(value); // -> 7
});
```
### 💡 Spiegazione:
> Questa funzione appiattisce livelli annidati di oggetti promise-like (ad esempio una promise che risolve a una promise che risolve a qualcosa) in un singolo livello.
– [Promise.resolve() on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve)
La specifica è [ECMAScript 25.6.1.3.2 Promise Resolve Functions](https://tc39.es/ecma262/#sec-promise-resolve-functions). But it is not quite human-friendly.
# 📚 Other resources
- [wtfjs.com](http://wtfjs.com/) — una raccolta di irregolarità e stranezze davvero speciali con un pizzico di momenti dolorosamente controintuitivi per il linguaggio del web.
- [Wat](https://www.destroyallsoftware.com/talks/wat) — A lightning talk by Gary Bernhardt from CodeMash 2012
- [What the... JavaScript?](https://www.youtube.com/watch?v=2pL28CcEijU) — Il talk di Kyle Simpsons alla Forward 2 che prova a "estrarre le stramberie” da JavaScript. Il suo desiderio è aiutare a scrivere un codice più pulito, elegante e leggibile, ispirare le persone a contribuire alla community open source.
# 🎓 License
[![CC 4.0][license-image]][license-url]
© [Denys Dovhan](http://denysdovhan.com)
[license-url]: http://www.wtfpl.net
[license-image]: https://img.shields.io/badge/License-WTFPL%202.0-lightgrey.svg?style=flat-square
[npm-url]: https://npmjs.org/package/wtfjs
[npm-image]: https://img.shields.io/npm/v/wtfjs.svg?style=flat-square
================================================
FILE: README-kr.md
================================================
# 아니 X발? 자바스크립트 이게 뭐야??
[![WTFPL 2.0][license-image]][license-url]
[![NPM version][npm-image]][npm-url]
> 재미있고 교묘한 JavaScript 예제
JavaScript는 훌륭한 언어입니다. JavaScript는 구문이 단순하며 큰 생태계를 가지고 있습니다. 가장 중요한 점은 훌륭한 공동체를 가지고 있다는 것입니다.
동시에, 우리 모두는 JavaScript가 까다로운 부분을 가진 꽤 재미있는 언어라는 것을 알고 있습니다. 몇몇 특징은 우리의 일상적인 일을 순식간에 지옥으로 바꾸기도 하고, 우리를 크게 웃게 만들기도 합니다.
WTFJS의 아이디어는 [Brian Leroux](https://twitter.com/brianleroux)에 속해있습니다. 이 목록들은 그의 이야기에서 꽤 영감을 받았습니다. [**“WTFJS”** at dotJS 2012](https://www.youtube.com/watch?v=et8xNAc2ic8):
[](https://www.youtube.com/watch?v=et8xNAc2ic8)
# NPM 패키지 메뉴스크립트
이 핸드북은 `npm`를 이용하여 설치할 수 있습니다. 그냥 실행합시다:
```
$ npm install -g wtfjs
```
이제 당신은 커맨드 창에서 'wtfjs'를 실행할 수 있게 되었습니다. 당신이 선택한 '$PAGER'에서 'wtfjs'가 열릴 것 입니다. 아니면 계속 여기서 읽어도 됩니다.
출처는 <https://github.com/denysdovhan/wtfjs> 여기에서 확인 할 수 있습니다.
# 번역
현재, **wtfjs**는 아래와 같은 언어로 번역되었습니다:
- [中文版](./README-zh-cn.md)
- [हिंदी](./README-hi.md)
- [Français](./README-fr-fr.md)
- [Português do Brasil](./README-pt-br.md)
- [Polski](./README-pl-pl.md)
- [Italiano](./README-it-it.md)
- [Russian](https://habr.com/ru/company/mailru/blog/335292/) (on Habr.com)
- [한국어](./README-kr.md)
[**다른 번역 **][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
<!-- prettier-ignore-start -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
# Table of Contents
- [💪🏻 시작하기에 앞서](#-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0%EC%97%90-%EC%95%9E%EC%84%9C)
- [✍🏻 표기법](#-%ED%91%9C%EA%B8%B0%EB%B2%95)
- [👀 예제](#-%EC%98%88%EC%A0%9C)
- [`[]`와 `![]은 같다`](#%EC%99%80-%EC%9D%80-%EA%B0%99%EB%8B%A4)
- [`true`는 `![]`와 같지 않지만, `[]`와도 같지 않다](#true%EB%8A%94-%EC%99%80-%EA%B0%99%EC%A7%80-%EC%95%8A%EC%A7%80%EB%A7%8C-%EC%99%80%EB%8F%84-%EA%B0%99%EC%A7%80-%EC%95%8A%EB%8B%A4)
- [true는 false](#true%EB%8A%94-false)
- [baNaNa](#banana)
- [`NaN`은 `NaN`이 아니다](#nan%EC%9D%80-nan%EC%9D%B4-%EC%95%84%EB%8B%88%EB%8B%A4)
- [이것은 실패다](#%EC%9D%B4%EA%B2%83%EC%9D%80-%EC%8B%A4%ED%8C%A8%EB%8B%A4)
- [`[]`은 truthy 이지만 `true`는 아니다](#%EC%9D%80-truthy-%EC%9D%B4%EC%A7%80%EB%A7%8C-true%EB%8A%94-%EC%95%84%EB%8B%88%EB%8B%A4)
- [`null`은 falsy 이지만 `false`은 아니다](#null%EC%9D%80-falsy-%EC%9D%B4%EC%A7%80%EB%A7%8C-false%EC%9D%80-%EC%95%84%EB%8B%88%EB%8B%A4)
- [`document.all`은 객체이지만 `undefined`이다](#documentall%EC%9D%80-%EA%B0%9D%EC%B2%B4%EC%9D%B4%EC%A7%80%EB%A7%8C-undefined%EC%9D%B4%EB%8B%A4)
- [최소 값은 0 보다 크다](#%EC%B5%9C%EC%86%8C-%EA%B0%92%EC%9D%80-0-%EB%B3%B4%EB%8B%A4-%ED%81%AC%EB%8B%A4)
- [함수는 함수가 아니다](#%ED%95%A8%EC%88%98%EB%8A%94-%ED%95%A8%EC%88%98%EA%B0%80-%EC%95%84%EB%8B%88%EB%8B%A4)
- [배열 추가](#%EB%B0%B0%EC%97%B4-%EC%B6%94%EA%B0%80)
- [배열의 후행 쉼표](#%EB%B0%B0%EC%97%B4%EC%9D%98-%ED%9B%84%ED%96%89-%EC%89%BC%ED%91%9C)
- [배열 평등은 몬스터](#%EB%B0%B0%EC%97%B4-%ED%8F%89%EB%93%B1%EC%9D%80-%EB%AA%AC%EC%8A%A4%ED%84%B0)
- [`undefined`과 `Number`](#undefined%EA%B3%BC-number)
- [`parseInt`은 나쁜 놈이다](#parseint%EC%9D%80-%EB%82%98%EC%81%9C-%EB%86%88%EC%9D%B4%EB%8B%A4)
- [`true`와 `false`를 이용한 수학](#true%EC%99%80-false%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%88%98%ED%95%99)
- [HTML 주석은 JavaScript에서도 유효하다](#html-%EC%A3%BC%EC%84%9D%EC%9D%80-javascript%EC%97%90%EC%84%9C%EB%8F%84-%EC%9C%A0%ED%9A%A8%ED%95%98%EB%8B%A4)
- [`NaN`은 숫자가 아니다](#nan%EC%9D%80-%EC%88%AB%EC%9E%90%EA%B0%80-%EC%95%84%EB%8B%88%EB%8B%A4)
- [`[]`과 `null`은 객체이다](#%EA%B3%BC-null%EC%9D%80-%EA%B0%9D%EC%B2%B4%EC%9D%B4%EB%8B%A4)
- [마법처럼 증가하는 숫자](#%EB%A7%88%EB%B2%95%EC%B2%98%EB%9F%BC-%EC%A6%9D%EA%B0%80%ED%95%98%EB%8A%94-%EC%88%AB%EC%9E%90)
- [정확도 `0.1 + 0.2`](#%EC%A0%95%ED%99%95%EB%8F%84-01--02)
- [패치 번호](#%ED%8C%A8%EC%B9%98-%EB%B2%88%ED%98%B8)
- [세 숫자의 비교](#%EC%84%B8-%EC%88%AB%EC%9E%90%EC%9D%98-%EB%B9%84%EA%B5%90)
- [재미있는 수학](#%EC%9E%AC%EB%AF%B8%EC%9E%88%EB%8A%94-%EC%88%98%ED%95%99)
- [RegExps 추가](#regexps-%EC%B6%94%EA%B0%80)
- [문자열은 `String`의 인스턴스가 아니다](#%EB%AC%B8%EC%9E%90%EC%97%B4%EC%9D%80-string%EC%9D%98-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4%EA%B0%80-%EC%95%84%EB%8B%88%EB%8B%A4)
- [backticks으로 함수 호출](#backticks%EC%9C%BC%EB%A1%9C-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C)
- [Call call call](#call-call-call)
- [`constructor` 속성](#constructor-%EC%86%8D%EC%84%B1)
- [객체 속성의 키로서의 객체](#%EA%B0%9D%EC%B2%B4-%EC%86%8D%EC%84%B1%EC%9D%98-%ED%82%A4%EB%A1%9C%EC%84%9C%EC%9D%98-%EA%B0%9D%EC%B2%B4)
- [`__proto__`을 사용한 프로토 타입 접근](#__proto__%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%9C-%ED%94%84%EB%A1%9C%ED%86%A0-%ED%83%80%EC%9E%85-%EC%A0%91%EA%B7%BC)
- [`` `${{Object}}` ``](#-object-)
- [디폴트 값으로 구조 해제](#%EB%94%94%ED%8F%B4%ED%8A%B8-%EA%B0%92%EC%9C%BC%EB%A1%9C-%EA%B5%AC%EC%A1%B0-%ED%95%B4%EC%A0%9C)
- [Dots와 spreading](#dots%EC%99%80-spreading)
- [라벨](#%EB%9D%BC%EB%B2%A8)
- [중첩된 라벨들](#%EC%A4%91%EC%B2%A9%EB%90%9C-%EB%9D%BC%EB%B2%A8%EB%93%A4)
- [교활한 `try..catch`](#%EA%B5%90%ED%99%9C%ED%95%9C-trycatch)
- [이것은 다중 상속인가?](#%EC%9D%B4%EA%B2%83%EC%9D%80-%EB%8B%A4%EC%A4%91-%EC%83%81%EC%86%8D%EC%9D%B8%EA%B0%80)
- [스스로 생성되는 Generator](#%EC%8A%A4%EC%8A%A4%EB%A1%9C-%EC%83%9D%EC%84%B1%EB%90%98%EB%8A%94-generator)
- [클래스의 클래스](#%ED%81%B4%EB%9E%98%EC%8A%A4%EC%9D%98-%ED%81%B4%EB%9E%98%EC%8A%A4)
- [강제할 수 없는 객체](#%EA%B0%95%EC%A0%9C%ED%95%A0-%EC%88%98-%EC%97%86%EB%8A%94-%EA%B0%9D%EC%B2%B4)
- [까다로운 화살표 함수](#%EA%B9%8C%EB%8B%A4%EB%A1%9C%EC%9A%B4-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98)
- [화살표 함수는 생성자가 될 수 없다](#%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98%EB%8A%94-%EC%83%9D%EC%84%B1%EC%9E%90%EA%B0%80-%EB%90%A0-%EC%88%98-%EC%97%86%EB%8B%A4)
- [`arguments`와 화살표 함수](#arguments%EC%99%80-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98)
- [까다로운 return](#%EA%B9%8C%EB%8B%A4%EB%A1%9C%EC%9A%B4-return)
- [객체에 할당 연결](#%EA%B0%9D%EC%B2%B4%EC%97%90-%ED%95%A0%EB%8B%B9-%EC%97%B0%EA%B2%B0)
- [배열을 사용한 객체 속성 접근 s](#%EB%B0%B0%EC%97%B4%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%9C-%EA%B0%9D%EC%B2%B4-%EC%86%8D%EC%84%B1-%EC%A0%91%EA%B7%BC-s)
- [Null 및 관계 연산자](#null-%EB%B0%8F-%EA%B4%80%EA%B3%84-%EC%97%B0%EC%82%B0%EC%9E%90)
- [`Number.toFixed()` 다른 숫자 표시](#numbertofixed-%EB%8B%A4%EB%A5%B8-%EC%88%AB%EC%9E%90-%ED%91%9C%EC%8B%9C)
- [`Math.max()` 이하 `Math.min()`](#mathmax-%EC%9D%B4%ED%95%98-mathmin)
- [`null`과 `0` 비교](#null%EA%B3%BC-0-%EB%B9%84%EA%B5%90)
- [동일한 변수 재선언](#%EB%8F%99%EC%9D%BC%ED%95%9C-%EB%B3%80%EC%88%98-%EC%9E%AC%EC%84%A0%EC%96%B8)
- [디폴트 동작 Array.prototype.sort()](#%EB%94%94%ED%8F%B4%ED%8A%B8-%EB%8F%99%EC%9E%91-arrayprototypesort)
- [resolve()은 Promise instance를 반환하지 않는다](#resolve%EC%9D%80-promise-instance%EB%A5%BC-%EB%B0%98%ED%99%98%ED%95%98%EC%A7%80-%EC%95%8A%EB%8A%94%EB%8B%A4)
- [📚 기타 resources](#-%EA%B8%B0%ED%83%80-resources)
- [🎓 License](#-license)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- prettier-ignore-end -->
# 💪🏻 시작하기에 앞서
> — _[**“Just for Fun: 우연한 혁명가의 이야기”**](https://en.wikipedia.org/wiki/Just_for_Fun), Linus Torvalds_
이 목록의 주요 목표는 가능한 JavaScript의 몇 가지의 엄청난 예제들을 모으고, 작동 방식을 설명하는 것 입니다. 이전에 우리가 몰랐던 것들을 배우는 것이 재미있기 때문입니다.
당신이 초보자라면, 이 노트를 사용하여 JavaScript에 대해 자세히 알아볼 수 있을 것입니다. 이 노트의 설명을 읽는 것에 더 많은 시간을 할애할 수 있기를 바랍니다.
당신이 전문 개발자라면, 우리가 사랑하는 JavaScript의 모든 기이한 점과 예상치 못한 것들에 대한 예시에 훌륭한 참조로 간주할 수 있습니다.
어쨌든, 이것을 읽읍시다. 당신은 아마 새로운 것들을 찾을 수 있을 것입니다.
# ✍🏻 표기법
**`// ->`** 식의 결과를 표시하는 데 사용됩니다. 예를 들면:
```js
1 + 1; // -> 2
```
**`// >`** `console.log` 또는 다른 출력의 결과를 의미합니다. 예를 들면:
```js
console.log("hello, world!"); // > hello, world!
```
**`//`** 설명에 사용되는 주석입니다. 예를 들면:
```js
// Assigning a function to foo constant
const foo = function() {};
```
# 👀 예제
## `[]`와 `![]은 같다`
배열은 배열이 아닙니다:
```js
[] == ![]; // -> true
```
### 💡 설명:
추상 항등 연산자는 양쪽을 숫자로 변환하여 비교하고, 서로 다른 이유로 양 쪽의 숫자는 `0`이 됩니다. 배열은 truthy 하므로, 오른쪽의 값은 `0`을 강요하는 truthy value의 반대 값 즉, `false`입니다. 그러나 왼쪽은 빈 배열은 먼저 boolean이 되지 않고 숫자로 강제 변환되고 빈 배열은 truthy 임에도 불구하고 `0`으로 강요됩니다.
이 표현식이 어떻게 단순화 되는지는 아래와 같습니다:
```js
+[] == +![];
0 == +false;
0 == 0;
true;
```
참조 [`[]`은 truthy 이지만 `true`은 아니다](#%EC%9D%80-truthy-%EC%9D%B4%EC%A7%80%EB%A7%8C-true%EB%8A%94-%EC%95%84%EB%8B%88%EB%8B%A4).
- [**12.5.9** 논리 연산자 NOT (`!`)](https://www.ecma-international.org/ecma-262/#sec-logical-not-operator)
- [**7.2.13** 추상 평등](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)
## `true`는 `![]`와 같지 않지만, `[]`와도 같지 않다
배열은 `true`와 같지 않지만 배열이 아닌것도 `true`와 같지 않습니다;
배열은 `false`와 같지만 배열이 아닌것도 `false`와 같습니다:
```js
true == []; // -> false
true == ![]; // -> false
false == []; // -> true
false == ![]; // -> true
```
### 💡 설명:
```js
true == []; // -> false
true == ![]; // -> false
// According to the specification
true == []; // -> false
toNumber(true); // -> 1
toNumber([]); // -> 0
1 == 0; // -> false
true == ![]; // -> false
![]; // -> false
true == false; // -> false
```
```js
false == []; // -> true
false == ![]; // -> true
// According to the specification
false == []; // -> true
toNumber(false); // -> 0
toNumber([]); // -> 0
0 == 0; // -> true
false == ![]; // -> true
![]; // -> false
false == false; // -> true
```
- [**7.2.13** 추상 평등 비교](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)
## true는 false
```js
!!"false" == !!"true"; // -> true
!!"false" === !!"true"; // -> true
```
### 💡 설명:
다음 단계를 고려합시다:
```js
// true is 'truthy' and represented by value 1 (number), 'true' in string form is NaN.
true == "true"; // -> false
false == "false"; // -> false
// 'false' is not the empty string, so it's a truthy value
!!"false"; // -> true
!!"true"; // -> true
```
- [**7.2.13** 추상 평등 비교](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)
## baNaNa
```js
"b" + "a" + +"a" + "a"; // -> 'baNaNa'
```
이것은 JavaScript에서 구식 농담이지만 재해석 되었습니다. 원본은 다음과 같습니다:
```js
"foo" + +"bar"; // -> 'fooNaN'
```
### 💡 설명:
식은 `'foo' + (+'bar')`으로 평가되고 숫자가 아닌 `'bar'` 형태로 변환됩니다.
- [**12.8.3** 덧셈 연산자 (`+`)](https://www.ecma-international.org/ecma-262/#sec-addition-operator-plus)
- [12.5.6 단항 + 연산자](https://www.ecma-international.org/ecma-262/#sec-unary-plus-operator)
## `NaN`은 `NaN`이 아니다
```js
NaN === NaN; // -> false
```
### 💡 설명:
아래의 사항들로 동작의 논리를 엄격하게 정의합니다:
> 1. 만약 `Type(x)`와 `Type(y)`가 다르면 **false**를 반환합니다.
> 2. 만약 `Type(x)`이 숫자이고
> 1. `x`가 **NaN**이면 **false**를 반환합니다.
> 2. `y`가 **NaN**이면 **false**를 반환합니다.
> 3. … … …
>
> — [**7.2.14** 염격한 평등 비교](https://www.ecma-international.org/ecma-262/#sec-strict-equality-comparison)
IEEE에서 정의한 `NaN`:
> 4 개의 상호 배타적인 관계 : 보다 작음, 같음, 보다 큼, 순서 없음. 마지막의 경우 하나 이상의 피연산자가 NaN일 때 발생합니다. 모든 NaN은 자신을 포함한 모든 것과 순서 없이 비교해야 합니다.
>
> — [“IEEE754 NaN 값에 false를 반환하는 것의 근거는 무엇입니까?”](https://stackoverflow.com/questions/1565164/1573715#1573715) StackOverflow에서
## 이것은 실패다
당신은 믿지 않을지도 모르지만 …
```js
(![] + [])[+[]] +
(![] + [])[+!+[]] +
([![]] + [][[]])[+!+[] + [+[]]] +
(![] + [])[!+[] + !+[]];
// -> 'fail'
```
### 💡 설명:
기호를 하나하나 나누면 아래와 같은 패턴이 자주 발생하는 것을 알 수 있습니다:
```js
![] + []; // -> 'false'
![]; // -> false
```
그래서 `[]`를 `false`으로 바꾸는 시도를 해봅니다. 하지만 많은 내부 함수 호출(`binary + Operator` -> `ToPrimitive` -> `[[DefaultValue]]`)때문에 오른쪽 피 연산 문자열로 변환하게 됩니다:
```js
![] + [].toString(); // 'false'
```
문자열을 배열로 생각하면 `[0]`을 통해 첫 번째 문자에 접근할 수 있습니다:
```js
"false"[0]; // -> 'f'
```
나머지는 분명하지만 `i`는 꽤 까다롭습니다. `fail` 속 `i`는 'falseundefined'라는 문자열을 생성하고 `['10']` 인덱스를 사용하여 요소를 잡습니다.
## `[]`은 truthy 이지만 `true`는 아니다
배열은 truthy 한 값이지만 `true`와 같지는 않다.
```js
!![] // -> true
[] == true // -> false
```
### 💡 설명:
다음은 ECMA-262 명세된 것의 세션에 대한 링크입니다:
- [**12.5.9** 논리 NOT 연산자 (`!`)](https://www.ecma-international.org/ecma-262/#sec-logical-not-operator)
- [**7.2.13** 추상 평등 비교](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)
## `null`은 falsy 이지만 `false`은 아니다
`null`은 falsy 값이라는 사실에도 불구하고 `false`는 아닙니다.
```js
!!null; // -> false
null == false; // -> false
```
동시에 `0` 또는 `''`와 같은 falsy 값은 `false`와 동일합니다.
```js
0 == false; // -> true
"" == false; // -> true
```
### 💡 설명:
설명은 이전 예제와 동일합니다. 다음은 해당 링크입니다:
- [**7.2.13** 추상 평등 비교](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)
## `document.all`은 객체이지만 `undefined`이다
> ⚠️ 이 파트는 브라우저 API 의 일부이며 Node.js 환경에서는 작동하지 않습니다.⚠️
`document.all`은 배열과 같은 클래스이고 페이지의 DOM 노드에 대한 엑세스를 제공한다는 사실에도 불구하고 `typeof`함수의 `undefined`으로 반응합니다.
```js
document.all instanceof Object; // -> true
typeof document.all; // -> 'undefined'
```
동시에 `document.all`은 `undefined`와 동일하지 않습니다.
```js
document.all === undefined; // -> false
document.all === null; // -> false
```
하지만 동시에:
```js
document.all == null; // -> true
```
### 💡 설명:
> 특히 이전 버전의 IE에서 `document.all`은 DOM 요소에 접근하는 방법을 사용했습니다. 이것은 표준이 된 적은 없지만 이전 JavaScript 코드에서 사용되었습니다. 새로운 APIs(`document.getElementById`와 같은)에서 표준이 진행되었을 때 이 API 호출은 쓸모 없게 되었고 표준 위원회는 이를 어떻게 처리할지 결정해야 했습니다. 광범위하게 사용되기 때문에 그들은 API를 유지하기로 결정했지만 JavaScript 명세된 것을 고의로 위반했습니다.
> 이것이 `undefined`의 상황에서 [엄격한 평등 비교](https://www.ecma-international.org/ecma-262/#sec-strict-equality-comparison)을 사용했을 때 `false`를 응답하고 [추상 평등 비교](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)을 사용할 때 `true`로 응답하는 이유는 명시적으로 허용하는 명세된 것의 의도적인 위반 때문입니다.
>
> — [“오래된 특징 - document.all”](https://html.spec.whatwg.org/multipage/obsolete.html#dom-document-all) WhatWG의 HTML 명세된 것
> — [“Chapter 4 - ToBoolean - Falsy values”](https://github.com/getify/You-Dont-Know-JS/blob/0d79079b61dad953bbfde817a5893a49f7e889fb/types%20%26%20grammar/ch4.md#falsy-objects) YDKJS의 Types & Grammar
## 최소 값은 0 보다 크다
`Number.MIN_VALUE`은 0 보다 큰 가장 작은 숫자입니다:
```js
Number.MIN_VALUE > 0; // -> true
```
### 💡 설명:
> `Number.MIN_VALUE`은 `5e-324`입니다. 즉, 부동 소수점 정밀도 내에서 표현할 수 있는 가장 작은 양수입니다. 이 말은 0 에 도달할 수 있는 가장 가까운 값이라는 의미 입니다. 이것은 소수가 제공할 수 있는 최상의 값이라고 정의할 수 있습니다.
>
> 비록 엄격하게 실제로 숫자는 아니지만 전체적으로 가장 작은 값은 `Number.NEGATIVE_INFINITY`이라고 할 수 있습니다.
>
> — [“자바 스크립트에서 왜 `0`은 `Number.MIN_VALUE`보다 작습니까?”](https://stackoverflow.com/questions/26614728/why-is-0-less-than-number-min-value-in-javascript) StackOverflow에서
- [**20.1.2.9** Number.MIN_VALUE](https://www.ecma-international.org/ecma-262/#sec-number.min_value)
## 함수는 함수가 아니다
> ⚠️ V8 v5.5 또는 그 이하의 버전에서는 버그가 있을 수 있습니다.(Node.js <=7) ⚠️
이것을 _undefined is not a function_ 모두가 알고 있지만 이건 어떨까요?
```js
// Declare a class which extends null
class Foo extends null {}
// -> [Function: Foo]
new Foo() instanceof null;
// > TypeError: function is not a function
// > at … … …
```
### 💡 설명:
이것은 명세된 것의 일부가 아닙니다. 현재 수정된 버그 일 뿐이므로 향후 아무 문제 없을 것입니다.
## 배열 추가
두 개의 배열을 추가하려면 어떻게 해야 할까요?
```js
[1, 2, 3] + [4, 5, 6]; // -> '1,2,34,5,6'
```
### 💡 설명:
연결이 발생합니다.차근차근 다음을 봅시다:
```js
[1, 2, 3] +
[4, 5, 6][
// call toString()
(1, 2, 3)
].toString() +
[4, 5, 6].toString();
// concatenation
"1,2,3" + "4,5,6";
// ->
("1,2,34,5,6");
```
## 배열의 후행 쉼표
4 개의 빈 배열을 만듭니다. 그럼에도 불구하고 후행 쉼표로 인해 세가지 , 요소가 있는 배열을 얻게 됩니다:
```js
let a = [, , ,];
a.length; // -> 3
a.toString(); // -> ',,'
```
### 💡 설명:
> **후행 쉼표** ("마지막 쉼표"라고도 함)는 JavaScript 에 새로운 요소, 매개 변수 또는 속성을 추가할 때 유용하게 사용할 수 있습니다. 만약 새 속성을 추가하려는 상황에서 이미 후행 쉼표를 사용하고 있는 경우 이전 마지막 줄을 수정하지 않고 새 줄을 추가할 수 있습니다. 이렇게 하면 버전 관리가 더 깔끔 해지고 코드 편집이 덜 번거로울 수 있습니다.
>
> — [후행 쉼표](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas) MDN에서
## 배열 평등은 몬스터
배열 평등은 아래에서 볼 수 있듯 JavaScript에서는 몬스터입니다:
```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
```
### 💡 설명:
아래의 예제를 주의 깊게 살펴 보아야 합니다! 이 동작은 [**7.2.13** 추상 동등 비교](https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison)에 설명되어 있습니다.
## `undefined`과 `Number`
`Number`생성자에 인수를 전달하지 않으면 `0` 값을 얻게 됩니다. 실제 인수가 없는 경우 `undefined`값이 형식 인수에 할당되기 때문에 인수가 없는 `Number`는 매개 변수 값으로 `undefined`를 사용합니다. 그러나 `undefined`를 통과하면 `NaN`을 얻을 수 있습니다.
```js
Number(); // -> 0
Number(undefined); // -> NaN
```
### 💡 설명:
명세된 것에 따르면:
1. 함수의 호출로 인수가 전달되지 않은 경우 `n`은 `+0`이 됩니다.
2. 또는 let `n` be ? `ToNumber(value)`.
3. `undefined`의 경우 `ToNumber(undefined)`는 `NaN`으로 반환해야 합니다.
다음은 해당 부분입니다:
- [**20.1.1** 숫자 생성자](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`은 나쁜 놈이다
`parseInt`은 특이한 점으로 유명합니다:
```js
parseInt("f*ck"); // -> NaN
parseInt("f*ck", 16); // -> 15
```
**💡 설명:** 이는 `parseInt`알 수 없는 문자에 도달할 때까지 문자별로 계속 구문 분석을 하기 때문에 발생합니다. `'f*ck'`에서 `f`는 16 진수로 `15`입니다.
`Infinity`정수로 파싱하는 것은…
```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
```
`null`을 파싱하는 것에도 주의합시다:
```js
parseInt(null, 24); // -> 23
```
**💡 설명:**
> `null`을 문자열 `"null"`로 변환하려고 합니다. 0 부터 23 까지의 기수에 대해서 변환할 수 있는 숫자가 없으므로 NaN을 반환합니다. 24 에, `"n"`, 14 번째 문자가 숫자 체계에 추가됩니다
gitextract_53_zsuvp/ ├── .editorconfig ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ └── new-example.md │ ├── PULL_REQUEST_TEMPLATE/ │ │ ├── new_example.md │ │ └── translation.md │ ├── dependabot.yml │ └── workflows/ │ ├── release.yml │ └── validate.yml ├── .gitignore ├── .husky/ │ └── pre-commit ├── CONTRIBUTING.md ├── LICENSE ├── README-fr-fr.md ├── README-hi.md ├── README-it-it.md ├── README-kr.md ├── README-pl-pl.md ├── README-pt-br.md ├── README-si.md ├── README-zh-cn.md ├── README.md ├── package.json └── wtfjs.js
Condensed preview — 23 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (611K chars).
[
{
"path": ".editorconfig",
"chars": 203,
"preview": "root = true\n\n[*]\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[package."
},
{
"path": ".github/FUNDING.yml",
"chars": 80,
"preview": "github: denysdovhan\npatreon: denysdovhan\ncustom: [buymeacoffee.com/denysdovhan]\n"
},
{
"path": ".github/ISSUE_TEMPLATE/new-example.md",
"chars": 487,
"preview": "---\nname: New Example\nabout: A new example for wtfjs collection\ntitle: ''\nlabels: new-example\nassignees: ''\n\n---\n\n<!--\n*"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE/new_example.md",
"chars": 373,
"preview": "<!--\n**New examples will be accepted only if they have an explanation.** Preferably, the explanation should contain link"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE/translation.md",
"chars": 404,
"preview": "<!--\n**If you want a translation, please, make one.** Issues with translation requests will be closed in favor of PRs.\n\n"
},
{
"path": ".github/dependabot.yml",
"chars": 320,
"preview": "version: 2\nupdates:\n # Maintain dependencies for GitHub Actions\n - package-ecosystem: \"github-actions\"\n directory: "
},
{
"path": ".github/workflows/release.yml",
"chars": 756,
"preview": "name: Release\non:\n push:\n branches:\n - master\njobs:\n release:\n name: Prepare release\n runs-on: ubuntu-la"
},
{
"path": ".github/workflows/validate.yml",
"chars": 512,
"preview": "name: Validate\non:\n push:\n pull_request:\n\njobs:\n validate:\n name: Validate\n runs-on: ubuntu-latest\n steps:\n "
},
{
"path": ".gitignore",
"chars": 37,
"preview": ".DS_Store\nnode_modules\nnpm-debug.log\n"
},
{
"path": ".husky/pre-commit",
"chars": 58,
"preview": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nnpx lint-staged\n"
},
{
"path": "CONTRIBUTING.md",
"chars": 1084,
"preview": "# Contributing Guidelines\n\nThis guide will help you to contribute to this project smoothly. Please, read carefully to ma"
},
{
"path": "LICENSE",
"chars": 460,
"preview": " DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE\n Version 2, December 2004\n\nCopyright (C) 2017"
},
{
"path": "README-fr-fr.md",
"chars": 58484,
"preview": "# What the f\\*ck JavaScript?\n\n[![WTFPL 2.0][license-image]][license-url]\n[![NPM version][npm-image]][npm-url]\n\n> Une lis"
},
{
"path": "README-hi.md",
"chars": 58882,
"preview": "# f\\*ck जावास्क्रिप्ट क्या है\n\n[![WTFPL 2.0][license-image]][license-url]\n[![NPM version][npm-image]][npm-url]\n\n> मजाकिय"
},
{
"path": "README-it-it.md",
"chars": 58139,
"preview": "# What the f\\*ck JavaScript?\n\n[![WTFPL 2.0][license-image]][license-url]\n[![NPM version][npm-image]][npm-url]\n\n> Una rac"
},
{
"path": "README-kr.md",
"chars": 45679,
"preview": "# 아니 X발? 자바스크립트 이게 뭐야??\n\n[![WTFPL 2.0][license-image]][license-url]\n[![NPM version][npm-image]][npm-url]\n\n> 재미있고 교묘한 Jav"
},
{
"path": "README-pl-pl.md",
"chars": 55077,
"preview": "# What the f\\*ck JavaScript?\n\n[![WTFPL 2.0][license-image]][license-url]\n[![NPM version][npm-image]][npm-url]\n\n> Lista z"
},
{
"path": "README-pt-br.md",
"chars": 55476,
"preview": "# What the f\\*ck JavaScript?\n\n[![WTFPL 2.0][license-image]][license-url]\n[![NPM version][npm-image]][npm-url]\n\n> Uma lis"
},
{
"path": "README-si.md",
"chars": 123853,
"preview": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD "
},
{
"path": "README-zh-cn.md",
"chars": 52847,
"preview": "# What the f\\*ck JavaScript?\n\n[![WTFPL 2.0][license-image]][license-url]\n[![NPM version][npm-image]][npm-url]\n[](https://sta"
},
{
"path": "package.json",
"chars": 1983,
"preview": "{\n \"name\": \"wtfjs\",\n \"version\": \"1.22.8\",\n \"description\": \"A list of funny and tricky JavaScript examples\",\n \"bin\": "
},
{
"path": "wtfjs.js",
"chars": 1915,
"preview": "#!/usr/bin/env node\n\nconst fs = require(\"fs\");\nconst obj = require(\"through2\").obj;\nconst pager = require(\"default-pager"
}
]
About this extraction
This page contains the full source code of the denysdovhan/wtfjs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 23 files (575.4 KB), approximately 217.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.