为什么2 + 40等于42?

时间:2015-07-19 23:48:32

标签: javascript unicode

当一位同事向我展示这一行警告42时,我感到很困惑。

alert(2+ 40);

很快就会发现看起来像减号的实际上是一个神秘的Unicode字符,其语义明显不同。

这让我想知道为什么该字符在解析表达式时不会产生语法错误。我还想知道是否有更多的角色表现得像这样。

5 个答案:

答案 0 :(得分:464)

该字符为"OGHAM SPACE MARK",这是一个空格字符。所以代码相当于alert(2+ 40)

  

我还想知道是否有更多的人物表现得像这样。

Zs类中的任何Unicode字符is a white space character in JavaScriptbut there don't seem to be that many

但是,JavaScript also allows Unicode characters in identifiers允许您使用有趣的变量名称,例如ಠ_ಠ

答案 1 :(得分:81)

在阅读完其他答案之后,我写了一个简单的脚本来查找U + 0000-U + FFFF范围内的所有Unicode字符,其行为类似于空格。看起来,有26或27个取决于浏览器,对U + 0085和U + FFFE有不同意见。

请注意,大多数这些字符看起来都像普通的空白区域。



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 + '"';
    }
}
&#13;
div { font-family: monospace; }
&#13;
&#13;
&#13;

答案 2 :(得分:56)

您使用的角色实际上比实际减号(连字符)更长。

 
-

顶部是您正在使用的,底部是减号应该是什么。你似乎已经知道了,所以现在让我们看看为什么Javascript会这样做。

您使用的字符实际上是ogham space mark,它是一个空白字符,因此它基本上被解释为与空格相同的东西,这意味着您的语句看起来像{Javascript的alert(2+ 40)

在Javascript中还有其他类似的字符。您可以看到完整列表here on Wikipedia

我注意到有关此角色的有趣内容是Google Chrome(以及可能的其他浏览器)在页面顶部栏中解释它的方式。

enter image description here

它内部有一个1680的块。这实际上是ogham空间标记的unicode数字。它似乎只是我的机器这样做,但这是一件奇怪的事情。

我决定用其他语言尝试一下,看看会发生什么,这些都是我得到的结果。

它不起作用的语言:

Python 2&amp; 3

>> 2+ 40
  File "<stdin>", line 1
    2+ 40
        ^
SyntaxError: invalid character in identifier

Ruby

>> 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 (在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

<强> C

>> 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

<强>开始

>> 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.

它可以使用的语言:

<强>方案

>> (+ 2  40)
=> 42

<强> C# (在Main()方法内)

Console.WriteLine(2+ 40);

Output: 42

Perl 6

>> ./perl6 -e'say 2+ 40' 
42

答案 3 :(得分:43)

我想它必须做一些事情,因为一些奇怪的原因它被归类为空格:

$ unicode  
U+1680 OGHAM SPACE MARK
UTF-8: e1 9a 80  UTF-16BE: 1680  Decimal: &#5760;
  ( )
Uppercase: U+1680
Category: Zs (Separator, Space)
Bidi: WS (Whitespace)

答案 4 :(得分:6)

  

我还想知道是否有更多的人物表现得像这样。

我似乎记得有一段时间读过一篇关于用U + 037E(希腊问号)恶意替换某人代码中的半冒号(U + 003B)的文章。

它们看起来都一样(我认为希腊人自己使用的是U + 003B),但是这篇文章说另一个不行。

有关维基百科的更多信息,请访问:https://en.wikipedia.org/wiki/Question_mark#Greek_question_mark

关于使用这个来自SO本身的恶作剧的一个(封闭的)问题。不是我最初读它的地方AFAIR: JavaScript Prank / Joke