41 votes

Pourquoi et comment ([! []] + [] [[]]) [+! + [] + [+]] Correspond-il à la lettre "i"?

Lors de la lecture de cet article publié sur dzone j'ai trouvé un extrait de code de JavaScript initialement posté sur Twitter par Marcus Lagergren.

Le code suivant apparemment affiche la chaîne de caractères "fail"

(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]];

Cela implique implicitement le type coulée et j'essaie de comprendre exactement comment cette ligne est interprété.

J'ai isolé de chaque personnage

  • (![]+[])[+[]] tirages "f"
  • (![]+[])[+!+[]] tirages "a"
  • ([![]]+[][[]])[+!+[]+[+[]]] tirages "i"
  • (![]+[])[!+[]+!+[]] tirages "l"

J'ai aussi réussi à briser les expressions qui reviennent chaque lettre en dehors de "i"

lettre "f"

![] un tableau vide est un Objet, qui, selon ECMAScript documentation, point 9.2 évalue true après conversion en boolean donc c'est false

false+[] par Point 11.6.1 les deux arguments de la binaire + opérateur se converti en Chaîne de caractères, par conséquent, nous obtenons "false"+"", qui évalue "false"

+[] unaire opérateur plus provoque une ToNumber conversion suivie par un ToPrimitive de conversion si l'argument est une Object. Le résultat de la conversion est déterminée par l'appel de la [[DefaultValue]] méthode interne de l'objet. Dans le cas d'un tableau vide, la valeur par défaut est 0. (ECMAScript de la Documentation, de sections: 11.4.6, 9.3, 9.1 )

"false"[0] nous sommes accéder au caractère à l'indice 0, d'où l' "f"

lettre "a"

Même histoire, la seule différence ici sont des conversions supplémentaires dans la partie entre crochets (ce qui donne un nombre de point à un autre caractère dans la chaîne "false"), déclenchée par l'utilisation de unaire + et ! opérateurs.

+[] évalue 0, comme expliqué ci-dessus.

!0 évalue true tel que défini à l'Article 9.2 et à l'Article 11.4.9. Tout d'abord, 0 , est converti en une valeur de type boolean false puis l'opérateur inverse de la valeur.

+true nouveau, la unaires plus déclenche une ToNumber de conversion, qui renvoie un 1 pour les binaires true (Section 11.4.6 et 9.3)

"false"[1] renvoie le deuxième caractère de la chaîne, qui est "a"

la lettre "l"

!+[] évalue true comme expliqué ci-dessus

true+true en utilisant le binaire + sur les primitives déclenche une ToNumber de conversion. En cas de vrai, son résultat est 1 et 1+1 équivaut 2

"false"[2] - auto-explicatif

lettre "i"

Ce qui me laisse perplexe, c'est la lettre "i". Je peux voir que la deuxième partie (entre crochets) renvoie la chaîne de caractères "10" et que la première partie (entre parenthèses) renvoie "falseundefined" mais je ne peux pas faire des têtes ou queues de comment cela se passe. Quelqu'un pourrait-il expliquer étape par étape? Surtout la magie qui se passe avec les crochets? (tableaux et d'accès au tableau)

Si possible, j'aimerais que chaque étape pour contenir un lien vers le sous-jacent ECMAScript règles.

Ce que je trouve le plus cryptique est cette partie: [][[]]

36voto

Blender Points 114729

Votre cryptique n'est pas tout ce qui cryptique si vous réécrire un peu:

[]['']

[] va être convertie en une chaîne de caractères, car il n'est pas un nombre entier, de sorte que vous êtes à la recherche d'une propriété de [] avec le nom '' (une chaîne vide). Il vous suffit de faire undefined, comme il n'existe aucune propriété de ce nom.

Comme pour la lettre réelle, briser l'expression dans les deux principales composantes:

  • La chaîne ([![]]+[][[]]):
    • [![]] est [false].
    • [][[]] est undefined.
    • Ajoutez-les ensemble et vous obtenez "falseundefined".
  • Et de l'indice: [+!+[]+[+[]]]. Certains espaces et les parenthèses rendre les opérations plus clair: [+(!(+[])) + [+[]]]:
    • [+[]] est [0].
    • +[] contraint [] pour un entier, de sorte que vous obtenez de l' 0.
    • !+[] contraint 0 booléenne et la négation d'elle, de sorte que vous obtenez de l' true.
    • +!+[] contraint true pour un entier, de sorte que vous obtenez de l' 1.
    • Ajoutez-les ensemble, et vous obtenez ["10"].

Lors de l'utilisation d'une chaîne de caractères pour accéder aux propriétés de la matrice et la chaîne se trouve être un élément de la matrice, la chaîne est contrainte d'un nombre entier et d'en obtenir les éléments réels de la matrice:

> [1, 2, 3]["0"]
1
> [1, 2, 3]["1"]
2

Le résultat final est:

> "falseundefined"["10"]
"i"

Lire cette réponse pour une explication de l' [false] + undefined partie.

1voto

Ven Points 7349

([![]]+[][[]])[+!+[]+[+[]]] a deux parties :

([![]]+[][[]]) , et l'autre qui vous avez trouvé vous-même.

![] retours false. Ensuite, nous utilisons [...] pour obtenir le .toString() le comportement de l' +. ([]+[] est le même que [].toString()+[].toString()) l' [][[]] n'est pas défini parce que nous essayons d'accéder à l'index [] (ou [].toString(), ce qui est '') de l' [] qui n'est pas défini.

Désolé pour la précédente réponse, j'ai mal lu votre commentaire totalement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X