Du fait que JavaScript soit un langage très dynamiques, on peut s'attendre à des comportements que nous n'avons pas l'habitude d'avoir si on vient d'autres langages.

L'objectif principal de cette liste est de recueillir des exemples fous et d'expliquer comment ils fonctionnent, si possible. Juste parce que c'est amusant d'apprendre quelque chose que nous ne savions pas auparavant.

Si vous êtes un débutant, vous pouvez utiliser ces notes pour plonger plus profondément dans JavaScript. J'espère que ces notes vous motiveront à passer plus de temps à lire les spécifications.

Si vous êtes un développeur professionnel, vous pouvez considérer ces exemples comme une excellente référence pour toutes les bizarreries et les bords inattendus de notre JavaScript bien-aimé.

Vous allez probablement trouver quelque chose de nouveau.

Je vais en faire une petite série des bouts de codes de blagues qu'on peut trouver sur le net. 😀

Souvent, les résultats dans JavaScript peuvent être tout à fait inattendus :

	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

Que se passe-t-il dans les quatre premiers exemples ?

  • Number + Number -> addition
  • Booléen + Number -> addition
  • Booléen + Booléen -> addition
  • Number + String -> concaténation
  • String + Booléen -> concaténation
  • String + String -> concaténation

Qu'en est-il d'autres exemples ? Une méthode ToPrimitive et ToString sont implicitement appelées pour [] et {} avant l'addition.

L'arrondis assez violent

999999999999999  // -> 999999999999999
9999999999999999 // -> 10000000000000000

10000000000000000       // -> 10000000000000000
10000000000000000 + 1   // -> 10000000000000000
10000000000000000 + 1.1 // -> 10000000000000002

Il y a un article sur Wikipedia qui explique pourquoi et comment, à cette échelle le nombre s'arrondis au nombre le plus proche.

Les Strings ne sont pas des instances de String

'unestring' // -> 'unestring'
typeof 'unestring' // -> 'string'
'unestring' instanceof String // -> false

Le constructeur String renvoie une chaîne:

typeof String('unestring')   // -> 'string'
String('unestring')          // -> 'unestring'
String('unestring') == 'unestring' // -> true

Essayons avec un nouveau:

new String('unestring') == 'unestring' // -> true
typeof new String('unestring')   // -> 'object'

Objet? Qu'est-ce que c'est?

new String('unestring') // -> [String: 'unestring']

Fonction fléchée

Syntaxe et contexte

let f = () => 10
f() // -> 10

Ok mais pour ça du coup ?

let f = () => {}
f() // -> undefined

Vous pourriez vous attendre à un objet {} au lieu undefined. C'est parce que les accolades font partie de la syntaxe des fonctions fléchée, donc f retournera undefined. Il est cependant possible de retourner l'objet {} directement à partir d'une fonction fléchée, en incluant la valeur de retour avec des crochets.

let f = () => ({})
f() // -> {}

Cette pratique est assez courante avec React !

Constructeur

let f = function () {
  this.a = 1;
}
new f(); // -> { 'a': 1 }

Maintenant, essayons de faire la même chose avec une fonction fléchée :

let f = () => {
  this.a = 1;
};
new f(); // -> TypeError: f is not a constructor

Les fonctions fléchées ne peuvent pas être utilisées en tant que constructeurs et généreront une erreur lorsqu'elles seront utilisées avec new.

Du fait qu'elles n'ont pas de contexte mais dépendent du scope d'où elles trouvent, donc pas de propriété prototype !

Retour d'arguments

let f = function(){
  return arguments;
}
f('a'); // -> { '0': 'a' }

Faisons la même chose avec une fonction fléchée :

let f = () =>  arguments;
f('a'); // -> Uncaught ReferenceError: arguments is not defined

Les fonctions fléchées sont une version allégée des fonctions régulières, l'accent étant mis sur le fait d'être court.

En même temps, les fonctions fléchées ne fournissent pas de contexte pour l'objet arguments. Comme alternative valide, utilisez la syntaxe d'un rest parameter pour obtenir le même résultat :

let f = (...args) => args;
f('a');

Le return

Celui là est mon préféré, il est simple et suffit à rendre fou quelqu'un qui ne fait pas attention.

Imaginons une IIFE :

(function () {
  return
  {
    b : 10
  }
})() // -> undefined

Tout simplement parce que l'expression qu'on retourne doit être sur la même ligne que le return.

(function () {
  return {
    b : 10
  }
})() // -> { b: 10 }

C'est dû à un concept appelé Automatic Semicolon Insertion, qui insère automagiquement des points-virgules après la plupart des nouvelles lignes.

Dans le premier exemple, un point-virgule est inséré entre l'instruction return et l'objet, de sorte que la fonction renvoie undefined et que l'objet n'est jamais évalué par le moteur JavaScript.

function userInteraction(article) {

	const { user, david } = article.humans;

	if (user.likeArticle) {
		if (!user.isFanFacebookPage) {
			user.likeFacebookPage();
		}
		user.shareFacebook();
		user.shareTwitter();
		user.shareLinkedin();
		david.notifyThankYou();
	} else {
		david.noOffence();
		david.notifyStillLoveYou();
	}

}

userInteraction(this);
Partages ! 😉