web-dev-qa-db-ja.com

2 + 40が42に等しいのはなぜですか?

同僚がこのJavaScriptのJavaScript警告の行を私に見せたとき私は困惑しました42。

alert(2+ 40);

マイナス記号のように見えるのは、実際には明らかに異なる意味を持つ難解なUnicode文字であることがすぐにわかります。

これは、式が解析されたときになぜその文字が構文エラーを生成しないのか疑問に思いました。このように振る舞うキャラクターがもっといるかどうかも知りたいです。

355
GOTO 0

その文字は "OGHAM SPACE MARK" で、これはスペース文字です。そのため、コードはalert(2+ 40)と同等です。

このように振る舞うキャラクターがもっといるかどうかも知りたいです。

Zsクラスの任意のUnicode文字 JavaScriptでは空白文字ですしかしそれほど多くはないようです

ただし、 JavaScriptでも識別子にUnicode文字を使用できます では、ಠ_ಠのような興味深い変数名を使用できます。

465
Felix Kling

他の答えを読んだ後、私は空白のように振る舞う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; }
81
GOTO 0

実際に使用している文字は、実際のマイナス記号(ハイフン)よりも長いようです。

 
-

一番上があなたが使っているもの、一番下がマイナス記号です。あなたはすでにそれを知っているように思われるので、今度はJavascriptがこれを行う理由を見てみましょう。

実際に使用する文字は空白文字である oghamスペースマーク です。したがって、基本的にスペースと同じものとして解釈されます。つまり、ステートメントはJavascriptに対してalert(2+ 40)のようになります。

Javascriptにはこのような他の文字があります。あなたは完全なリストを見ることができます ここウィキペディアで


この文字について私が気づいた何か面白いことは、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>'

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.

それが働く言語:

スキーム

>> (+ 2  40)
=> 42

C#Main()メソッド内)

Console.WriteLine(2+ 40);

Output: 42

Perl 6

>> ./Perl6 -e'say 2+ 40' 
42
56
michaelpri

私はそれが何か奇妙な理由でそれが空白として分類されるという事実で何かをしなければならないと思います:

$ 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)
43
PSkocik

このように振る舞うキャラクターがもっといるかどうかも知りたいです。

誰かのコードの中のセミコロン(U + 003B)をギリシャの疑問符であるU + 037Eにいたずらに置き換えたことについて、少し前に読んだことを覚えているようです。

両方とも同じように見えますが(ギリシャ人自身がU + 003Bを使用していると私が信じている範囲で)、この記事ではもう一方はうまくいかないと述べました。

ウィキペディアからのこれに関するより多くの情報はここにあります: https://en.wikipedia.org/wiki/Question_mark#Greek_question_mark

そして、これをSO自体からのいたずらとして使うことに関する(閉じた)質問です。私がもともとそれを読んでいた場所ではありませんでした: JavaScript Prank/Joke

6
noonand