为什么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>' 

Javamain方法里面)

 >> 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: &#5760; ( ) 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恶作剧/笑话