首页 文章

为什么2 40等于42?

提问于
浏览
353

当一位同事向我展示这一系列的JavaScript警报42时,我感到很困惑 .

alert(2+ 40);

事实证明,看起来像减号的实际上是一个神秘的Unicode字符,具有明显不同的语义 .

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

5 回答

  • 6

    该字符是"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,它允许您使用有趣的变量名称,如 ಠ_ಠ .

  • 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 + '"';
        }
    }
    
    div { font-family: monospace; }
    
  • 43

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

     
    -
    

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

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

    在Javascript中还有其他类似的字符 . 你可以看到一个完整的列表here on Wikipedia .


    我注意到这个角色的有趣之处在于Google Chrome(以及可能的其他浏览器)在页面顶部栏中解释它的方式 .

    enter image description here

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


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


    它不起作用的语言:

    Python 2 & 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
    

    Go

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

    语言确实有效:

    Scheme

    >> (+ 2  40)
    => 42
    

    C# (在 Main() 方法内)

    Console.WriteLine(2+ 40);
    
    Output: 42
    

    Perl 6

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

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

    $ 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)
    
  • 461

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

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

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

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

    还有一个(封闭的)关于将其用作SO本身的恶作剧的问题 . 不是我最初读它AFAIR的地方:JavaScript Prank / Joke

相关问题