javascript - special - ¿Por qué 2+ 40 es igual a 42?
javascript utf8 encode (5)
También me gustaría saber si hay más personajes que se comportan así.
Me parece recordar haber leído un artículo hace un tiempo sobre el reemplazo travieso de punto y coma (U + 003B) en el código de alguien con U + 037E, que es el signo de interrogación griego.
Ambos se ven iguales (en la medida en que creo que los propios griegos usan U + 003B), pero este artículo declaró que el otro no funcionaría.
Puede encontrar más información sobre esto en Wikipedia aquí: https://en.wikipedia.org/wiki/Question_mark#Greek_question_mark
Y una pregunta (cerrada) sobre el uso de esto como una broma del propio SO. No es donde originalmente lo leí AFAIR: JavaScript Prank / Joke
Estaba desconcertado cuando un colega me mostró esta línea de alertas de JavaScript 42.
alert(2+ 40);
Resulta rápidamente que lo que parece un signo menos es en realidad un personaje arcano de Unicode con una semántica claramente diferente.
Esto me dejó preguntándome por qué ese personaje no produce un error de sintaxis cuando se analiza la expresión. También me gustaría saber si hay más personajes que se comportan así.
Después de leer las otras respuestas, escribí un script simple para encontrar todos los caracteres Unicode en el rango U + 0000 – U + FFFF que se comportan como espacios en blanco. Como parece, hay 26 o 27 de ellos dependiendo del navegador, con desacuerdos sobre U + 0085 y U + FFFE.
Tenga en cuenta que la mayoría de estos caracteres se parecen a un espacio en blanco normal.
function isSpace(ch)
{
try
{
return Function(''return 2 +'' + ch + '' 2'')() === 4;
}
catch(e)
{
return false;
}
}
for (var i = 0; i <= 0xffff; ++i)
{
var ch = String.fromCharCode(i);
if (isSpace(ch))
{
document.body.appendChild(document.createElement(''DIV'')).textContent = ''U+'' + (''000'' + i.toString(16).toUpperCase()).slice(-4) + '' "'' + ch + ''"'';
}
}
div { font-family: monospace; }
Ese personaje es
"OGHAM SPACE MARK"
, que es un personaje espacial.
Entonces el código es equivalente a
alert(2+ 40)
.
También me gustaría saber si hay más personajes que se comportan así.
Cualquier carácter Unicode en la clase Zs es un espacio en blanco en JavaScript , pero no parece haber tantos .
Sin embargo,
JavaScript también permite caracteres Unicode en los identificadores
, lo que le permite usar nombres de variables interesantes como
ಠ_ಠ
.
Parece que el carácter que está utilizando es en realidad más largo que el signo menos real (un guión).
-
La parte superior es lo que está utilizando, la parte inferior es lo que debería ser el signo menos. Parece que ya lo sabes, así que ahora veamos por qué Javascript hace esto.
El carácter que usa es en realidad la
marca de espacio ogham,
que es un carácter de espacio en blanco, por lo que básicamente se interpreta como lo mismo que un espacio, lo que significa que su declaración parece
alert(2+ 40)
a Javascript.
Hay otros caracteres como este en Javascript. Puedes ver una lista completa aquí en Wikipedia .
Algo interesante que noté sobre este personaje es la forma en que Google Chrome (y otros posibles navegadores) lo interpreta en la barra superior de la página.
Es un bloque con
1680
interior.
Ese es en realidad el número unicode para la marca de espacio ogham.
Parece que solo mi máquina está haciendo esto, pero es algo extraño.
Decidí probar esto en otros idiomas para ver qué pasa y estos son los resultados que obtuve.
Idiomas en los que no funciona:
Python 2 y 3
>> 2+ 40
File "<stdin>", line 1
2+ 40
^
SyntaxError: invalid character in identifier
Rubí
>> 2+ 40
NameError: undefined local variable or method ` 40'' for main:Object
from (irb):1
from /home/michaelpri/.rbenv/versions/2.2.2/bin/irb:11:in `<main>''
Java
(dentro del método
main
)
>> System.out.println(2+ 40);
Main.java:3: error: illegal character: /5760
System.out.println(2+?40);
^
Main.java:3: error: '';'' expected
System.out.println(2+?40);
^
Main.java:3: error: illegal start of expression
System.out.println(2+?40);
^
3 errors
PHP
>> 2+ 40;
Use of undefined constant 40 - assumed '' 40'' :1
do
>> 2+ 40
main.c:1:1: error: expected identifier or ''('' before numeric constant
2+ 40
^
main.c:1:1: error: stray ''/341'' in program
main.c:1:1: error: stray ''/232'' in program
main.c:1:1: error: stray ''/200'' in program
exit status 1
Ir
>> 2+ 40
can''t load package: package .:
main.go:1:1: expected ''package'', found ''INT'' 2
main.go:1:3: illegal character U+1680
exit status 1
Perl 5
>> perl -e''2+ 40''
Unrecognized character /xE1; marked by <-- HERE after 2+<-- HERE near column 3 at -e line 1.
Idiomas en los que funciona:
Esquema
>> (+ 2 40)
=> 42
C #
(dentro del método
Main()
)
Console.WriteLine(2+ 40);
Output: 42
Perl 6
>> ./perl6 -e''say 2+ 40''
42
Supongo que tiene que ver algo con el hecho de que por alguna extraña razón se clasifica como espacio en blanco:
$ unicode
U+1680 OGHAM SPACE MARK
UTF-8: e1 9a 80 UTF-16BE: 1680 Decimal:  
( )
Uppercase: U+1680
Category: Zs (Separator, Space)
Bidi: WS (Whitespace)