(! [] + []) [+ []]… Expliquez pourquoi cela fonctionne


107
alert((![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]);

La sortie de ce code est: fail. Pourquoi?

Au fait (![]+[])[+!+[]] == 'false'[1], non ?. Mais pourquoi ![]+[] == "false"et pourquoi +!+[] == 1?


14
@Snoob Je ne te fais pas confiance. En fin de compte, c'est une bombe à fourche.
Johannes Schaub - allumé

3
C'est une chaîne littérale, bien sûr;)
Yi Jiang

3
(![]+[])[+[]]est "f" (le premier caractère de "false"), (![]+[])[+!+[]]est "a", etc.
Mauricio Scheffer

3
@Snoob: comme vous l'avez dit, vous pouvez tester chaque expression sur votre navigateur. Essayez alert(![]+[])alors alert(+!+[])et vous verrez.
Mauricio Scheffer

12
Inutile ou pas, je trouve que c'est une question intéressante et j'aimerais voir une explication bien formulée. De nombreux Code Golfs seraient fermés si l'utilité ou l'aspect pratique étaient considérés. Les exercices et les jeux sont utiles en eux-mêmes pour élargir l'esprit et le processus de réflexion.
John K

Réponses:


127

Comme @Mauricio l'a commenté (![]+[])[+[]]est "f" (le premier caractère de "faux"), (![]+[])[+!+[]])est "a", etc ...

Comment ça marche?

Examinons le premier caractère, 'f':

(![]+[])[+[]]; // 'f'

La première partie de l'expression - entre parenthèses - est composée par ![]+[], le premier opérande de l'opérateur Addition est ![]et il produira false, car un objet tableau - comme toute autre instance d'Objet - est véridique , et en appliquant la logique (!) PAS unaire opérateur, il produit la valeur false, par exemple.

![]; // false, it was truthy
!{}; // false, it was truthy
!0;  // true, it was falsey
!NaN;  // true, it was falsey

Après cela, nous avons le deuxième opérande de l'addition, un tableau vide [], ceci est fait juste pour convertir la falsevaleur en String, car la représentation sous forme de chaîne d'un tableau vide est juste une chaîne vide, équivaut à:

false+[]; // "false"
false+''; // "false"

La dernière partie, la paire de crochets après les parenthèses, ils sont l'accesseur de propriété et ils reçoivent une expression, qui est formée par l'opérateur unaire plus appliqué à nouveau à un tableau vide.

Ce que fait l'opérateur Unary Plus, c'est la conversion de type Number, par exemple:

typeof +"20"; // "number"

Une fois de plus, cela est appliqué à un tableau vide, et comme je l'ai déjà dit, la représentation String d'un tableau est une chaîne vide, et lorsque vous convertissez une chaîne vide en nombre, elle est convertie en zéro:

+[]; // 0, because
+[].toString(); // 0, because
+""; // 0

Par conséquent, nous pouvons "décoder" l'expression en quelques étapes:

(![]+[])[+[]];
(false+[])[+[]];
(false+'')[+[]];
(false+'')[0];
('false')[0];  // "f"

Notez que l'accès aux caractères en utilisant la notation entre crochets sur les valeurs String ne faisait pas partie de ECMAScript 3rd. Spécification d'édition, (c'est pourquoi la charAtméthode existait).

Cependant ce type de "propriétés d'index" qui représentent les caractères d'une chaîne était standardisé sur ECMAScript 5, et avant même la standardisation, la fonctionnalité était disponible dans un bon nombre de navigateurs (même dans IE8 (mode standard)).


46
J'espère juste que ce n'est jamais une question d'entrevue.
Inisheer

4
@JTA: J'espère que c'est ! J'aurais réussi :-D
Mauricio Scheffer

18
D'où vient le "i"?
Josh Stodola

5
@rlemon, il n'y a pas intde type de données sur le langage, en fait tous les nombres sont au format 64 bits double précision (valeurs IEEE 754), même si certains opérateurs fonctionnent en interne avec des valeurs Integer (comme les opérateurs bit à bit) le résultat est toujours un double . Le 'i'vient dans cet exemple de undefined, mais il pourrait provenir Infinitypar exemple: (+!+[]/+[+[]]+[])[!+[]+!+[]+!+[]]=> (1/0+'')[3]=> (Infinity+'')[3]=>'i'
CMS

5
@JoshStodola Eh bien, ~ 3 mois plus tard, une clarification supplémentaire. Le "i" dans ce cas vient de "undefined", oui, mais il y a une autre astuce impliquée ici. Le code concatène «faux» à «indéfini» pour former "falseundefined"(construit en utilisant:) [![]]+[][[]]dans lequel l'indice de «i» est 10. +!+[]+[+[]]donne "10". Ceci est utilisé pour extraire le "i" (les indices de chaîne peuvent être utilisés en javascript s'ils peuvent être forcés à des entiers apparemment). La construction finale qui le produit est:([![]]+[][[]])[+!+[]+[+[]]]
entropie du
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.