JavaScript plus Homme de Paille et HOP : La cohérence aux chiottes

Allez, on casse un petit homme de paille en informatique avec un jolie exemple JavaScript qui nous est joliment illustré par Luc Damas sur le site HOP (pour Houblon Oriented Programming. Oui, il y a de la bière !).

Homme de paille sur JS array keys
Source : https://www.luc-damas.fr/

Si vous ne le savez pas, JavaScript souffre de harcèlement de la part de ses petits camarades à l'école car il est différent. Même si j'ai trouvé aussi cela drôle (oui, j'aime me moquer parfois) encore faut t-il que ce le soit pour de bonne raison. Nous avons ici à faire à de mauvaises raisons.

Définition Qu'est ce qu'un homme de paille ?

“L’épouvantail, parfois appelé « argument de l'homme de paille » par traduction littérale de l'expression anglaise « straw man », est un sophisme qui consiste à présenter la position de son adversaire de façon volontairement erronée. Créer un argument épouvantail consiste à formuler un argument facilement réfutable puis à l'attribuer à son opposant.” — Wikipédia

PS : je ne dis pas qu'il n'existe pas de bonnes raisons de se moquer du JavaScript.

PS2 : je ne dis pas que c'est bien de se moquer.

PS3 : (PS signifie Post-scriptum et non pas PlayStation).

Bref, soyons un peu plus critique.

Les faits

Exposons plusieurs faits de ce pas.

Boucle for

Seul le premier type de boucle garanti que i soit de type number puisque nous décidons nous même d'en faire un tel type (let i = 0, puis i++).

Rien ne nous empêcherait, par exemple, d'en faire un type string à chaque itération.

Ainsi i dans l'exemple suivant...

let t = ['h', 'o', 'p'];
for (let i = '0'; i < t.length; i = +i + 1 + '') {
    console.log(i);
    console.log(typeof i);
}

...sera de type string.

Boucle for ... of

En ce qui concerne l'opérateur for ... of, l'exemple est fallacieux puisqu'en réalité i n'est pas censé représenter nécessairement un nombre, mais l'objet qui se trouve dans le tableau.

Aussi l'exemple suivant...

var t = ['h', 'o', 'p'];
for (var i of t) {
    console.log(i);
    console.log(typeof i);
}

...retournera des types string (et pas number comme l'utilisation de t.keys().

Donc naturellement, l'exemple suivant...

var t = [true, false, true];
for (var i of t) {
    console.log(i);
    console.log(typeof i);
}

...retournera pour i un type boolean.

Le fait qu'avec l'utilisation de .keys() la valeur soit un number n'est donc pas de notre ressors mais de celui de cette fonction (qui retourne l'indice qui est un number).

Boucle for ... in

Pour finir, l'opérateur for ... in semble, lui, affecter à i une string (ce qui effectivement n'est pas la même chose que l'utilisation de for ou de for ... of couplé .keys()). Je me serai également attendu à ce qu'il affecte un number comme ça sans trop y réfléchir mais il n'y a rien d’étonnant non plus : for ... in n'est pas réservé aux Array mais peut également fonctionner avec des Object. Et les indices des objets ne sont pas nécessairement des nombres.

Regardez l'exemple suivant :

let v = {
    'str1': 'h',
    'str2': 'o',
    'str3': 'p',
};

for (var i in v) {
    console.log(i);
    console.log(typeof i);
}

Logique que ça retourne un type string (str1, str2, str3).

Regardez également l'exemple suivant :

const symbol1 = Symbol('h');
const symbol2 = Symbol('o');
const symbol3 = Symbol('p');

let t = {
    symbol1: 'h',
    symbol2: 'o',
    symbol3: 'p',
};

for (var i in t) {
    console.log(i);
    console.log(typeof i);
}

Ainsi on utilise .toString() pour « représenter » le Symbol.

Il n'est pas illogique que le système nous retourne une string (symbol1, symbol2 et symbol3). Puisque for ... in doit être en mesure de retourner différent type de valeur.

Mon opinion

Il a été décidé « arbitrairement » que le système retourne les indices en utilisant la valeur toString() (ce qui est quand même pratique pour les string ou les Symbol et accessoirement, fonctionne également avec number.

Bref, c'est bien marrant à première vu, mais il n'y a rien qui me choque nécessairement. Faire le choix de la string ou du number est quelque chose « d'arbitraire ».

Si vous êtes sur que votre indice sera de type number, vous pouvez tout simplement convertir la valeur en number avec l'opérateur + si cela est réellement nécessaire.

var t = ['h', 'o', 'p'];
for (var i in t) {
    console.log(+i);
    console.log(typeof +i);
}

Et oui, « si l'objet est de type Array », alors faire que for ... in retourne un number plutôt qu'une string était quelque chose que arbitrairement il aurait été convenable de faire : pour preuve, cette image le montre. Mais ce n'était pas nécessairement plus « logique » que l'état actuelle en fonction du point de vu adopté.

Maintenant, au delà de ça, l'argument « j'aime pas le JavaScript » est une idée valide (et une opinion) pour justifier le fait de jeter son PC dans les chiottes (même si la finalité me semble un peu excessive :D).

Ma nouvelle illustration

Pas besoin d'homme de paille donc, rectifions ça !

Homme de paille sur JS array keys
Source : https://www.luc-damas.fr/

Merci à Pierre Ammeloot pour le partage ;)

Lire dans une autre langue