为什么2+ 40等于42?
当一位同事向我展示了这一行的JavaScript警报时,我感到莫名其妙。
alert(2+ 40);
很快就会发现,看起来像一个负号的实际上是一个具有明显不同语义的神秘Unicode字符。
这让我想知道为什么这个字符在parsingexpression式时不会产生语法错误。 我也想知道是否有更多的人物像这样的行为。
该字符是“OGHAM SPACE MARK” ,这是一个空格字符。 所以代码相当于alert(2+ 40)
。
我也想知道是否有更多的人物像这样的行为。
Zs类中的任何Unicode字符都是JavaScript中的空格字符 , 但似乎没有那么多 。
但是, JavaScript也允许在标识符中使用Unicode字符 ,这使您可以使用有趣的variables名称,如ಠ_ಠ
。
在阅读其他答案之后,我写了一个简单的脚本来查找范围为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; }
看来你正在使用的字符实际上比实际的减号(连字符)长。
-
最上面是你正在使用的东西,底部是减号应该是什么。 你似乎已经知道,所以现在让我们来看看为什么Javascript这样做。
你使用的字符实际上是一个空白字符的ogham空格标记 ,所以它基本上被解释为与空格相同的东西,这意味着你的语句看起来像alert(2+ 40)
到Javascript。
在Javascript中有这样的其他字符。 您可以在维基百科上看到完整列表。
我注意到有关这个angular色的一些有趣的事情是Google Chrome浏览器(以及其他可能的浏览器)在页面的顶部栏中解释它的方式。
里面有1680
块。 这实际上是ogham空间标记的统一码。 这似乎只是我的机器这样做,但这是一个奇怪的事情。
我决定尝试用其他语言来看看会发生什么,这些都是我得到的结果。
语言不起作用:
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
走
>> 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
我想它必须做一些事实,因为一些奇怪的原因,它分类为空白:
$ 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)
我也想知道是否有更多的人物像这样的行为。
我似乎还记得读过一篇关于用希腊问号U + 037E替代分号(U + 003B)的方法。
他们看起来都是一样的(就我相信希腊人自己使用U + 003B而言),但是这篇文章指出另外一个是行不通的。
有关维基百科的更多信息,请访问: https : //en.wikipedia.org/wiki/Question_mark#Greek_question_mark
和一个(封闭的)关于使用这个恶作剧从SO本身的问题。 不是我最初阅读它AFAIR: JavaScript恶作剧/笑话