ทำไม 2+ 40 เท่ากับ 42


360

ฉันรู้สึกงุนงงเมื่อเพื่อนร่วมงานแสดงบรรทัด JavaScript นี้ให้ฉัน 42

alert(2+ 40);

มันกลับกลายเป็นว่าสิ่งที่ดูเหมือนเครื่องหมายลบจริงๆแล้วคืออักขระ Unicode แบบอาร์เคนที่มีความหมายต่างกันอย่างชัดเจน

นี่ทำให้ฉันสงสัยว่าทำไมตัวละครตัวนั้นถึงไม่สร้างข้อผิดพลาดทางไวยากรณ์เมื่อมีการวิเคราะห์คำ ฉันก็อยากจะรู้ว่ามีตัวละครมากขึ้นเช่นนี้หรือไม่


28
@Elyasin คุณคัดลอก / วางหรือพิมพ์อีกครั้งหรือไม่
253751

4
ใช้งานได้ใน Visual C # เช่นกัน เมื่อวางอักขระแปลก ๆ ลงใน Visual Studio IDE หรือเมื่อดำเนินการตามคำสั่งโดยพิมพ์;ตัวแก้ไขมีแนวโน้มที่จะเปลี่ยนอักขระ `` แปลก ๆ ให้เป็นช่องว่างปกติ แต่ถ้าคุณเลิกทำการ "แก้ไขอัตโนมัติ" คุณจะมีพฤติกรรมแบบเดียวกัน . ตัวละครนั้นมีความหมายเช่นเดียวกับช่องว่างแม้ว่ามันจะดูเหมือนยัติภังค์หรือลบ (ในแบบอักษรปกติ)
Jeppe Stig Nielsen

4
ตรงกันข้ามสามารถเกิดขึ้นได้เช่นกัน บางภาษาที่สนับสนุนยูนิโค้ดในตัวระบุยอมรับอักขระยูนิโค้ดที่ดูเหมือน white space (กล่าวอีกนัยหนึ่งคุณไม่สามารถมองเห็นพวกเขา) มันอาจเป็นไปได้ที่จะมีตัวระบุที่มองไม่เห็นอย่างสมบูรณ์
gnasher729

58
(OT) เพราะ 42 เป็นคำตอบของทุกสิ่งใช่ไหม
ivan_pozdeev

4
@ โทมัสความจริงที่ว่าผลลัพธ์ที่ไม่คาดคิดนั้นเกิดจากตัวอักษร Unicode นั้นชัดเจนแล้ว
GOTO 0

คำตอบ:


470

ตัวละครนั้นคือ"OGHAM SPACE MARK"ซึ่งเป็นอักขระเว้นวรรค alert(2+ 40)ดังนั้นรหัสเทียบเท่ากับ

ฉันก็อยากจะรู้ว่ามีตัวละครมากขึ้นเช่นนี้หรือไม่

ใดอักขระ Unicode ในชั้น Zs เป็นตัวละครที่พื้นที่สีขาวใน JavaScript , แต่มีดูเหมือนจะไม่เป็นไปได้ว่าหลาย ๆ

อย่างไรก็ตามจาวาสคริปต์ยังช่วยให้ตัวอักษร Unicode ในตัวบ่งชี้ಠ_ಠซึ่งจะช่วยให้คุณใช้ชื่อตัวแปรที่น่าสนใจเช่น


3
Box-with-a-hex-code ขีดเส้นใต้ box-with-a-hex-code มันหมายถึงตัวละครตัวไหน?
253751

12
@immibis ส่วนสุดท้ายของคำตอบนี้เป็นอิโมติคอนที่มีอยู่ในแบบฟอร์มรูปภาพที่ไม่ลงรอยกัน
Mark S.

3
โปรดทราบว่าไม่ใช่แค่Zsตัวอักษรเท่านั้นที่ถือเป็นช่องว่างใน JavaScript มีอีกมากมาย: github.com/mathiasbynens/regexpu/blob/…
Mathias Bynens

20
ปฏิกิริยาของฉันเมื่อಠ_ಠสามารถใช้เป็นตัวระบุใน JS: ಠ_ಠ
คริส Cirefice

2
@ChrisCirefice ขีดล่างได้รับการปฏิบัติในฐานะที่เป็นจดหมายยืนยาวในภาษา C- สไตล์ การได้รับการปฏิบัติเสมือนเป็นจดหมายเป็นเพียงสามัญสำนึกเนื่องจากเป็นจดหมาย มันจะเป็นข้อผิดพลาดที่ชัดเจนหากಠ_ಠไม่สามารถใช้เป็นตัวระบุ
Jon Hanna

81

หลังจากอ่านคำตอบอื่น ๆ ฉันเขียนสคริปต์ง่าย ๆ เพื่อค้นหาอักขระ Unicode ทั้งหมดในช่วง U + 0000 – U + FFFF ที่มีลักษณะเหมือนช่องว่างสีขาว ตามที่ปรากฏมี 26 หรือ 27 ของพวกเขาขึ้นอยู่กับเบราว์เซอร์ที่มีความขัดแย้งเกี่ยวกับ U + 0085 และ U + FFFE

โปรดทราบว่าอักขระเหล่านี้ส่วนใหญ่มีลักษณะเหมือนพื้นที่สีขาวปกติ


17
U + 0085 "NEL" ถูกกำหนดให้เป็นช่องว่างโดย Unicode แต่มีประวัติอันยาวนานในการผิดพลาด U + FFFE เป็นตัวละครที่ไม่มีชื่อและไม่มีคุณสมบัติใด ๆ นอกเหนือจาก NChar และไม่ควรได้รับการพิจารณาว่าเป็นช่องว่างโดยอะไรก็ตามที่สมเหตุสมผล ที่กล่าวว่าไม่เห็นด้วยเบราว์เซอร์ของฉันกับฉันทั้งจุด :)
ฮอบส์

4
@hobbs U + FFFE นี้ยังมีไม่เพียง\p{Default Ignorable Code Point} \p{Noncharacter Code Pount}U + 0085 เป็น\p{Whitespace}จุดรหัสเสมอ สิ่งที่ชั่วร้ายคือ U + 180E MONGOLIAN SEPARATOR ซึ่ง "เพิ่ง" สูญเสีย\p{Whitespace}ทรัพย์สินไป โปรดทราบว่า\p{Pattern Whitespace}เป็นชุดที่เล็กกว่ามากและเป็นคุณสมบัติที่ไม่เปลี่ยนรูป แต่\p{Whitespace}ไม่ใช่
tchrist

2
FEFFคือ BOM และสามารถถือว่าเป็น "ช่องว่างแบบไม่มีช่องว่างความกว้างเป็นศูนย์" ภายในข้อความ FFFEมันคือ endian แลกเปลี่ยนเทียบเท่า บางทีนั่นอาจเป็นเหตุผลที่เบราว์เซอร์ปฏิบัติเช่นเดียวกับช่องว่าง
CodesInChaos

ecma-international.org/ecma-262/6.0/#sec-white-space (ที่เชื่อมโยงจากคำตอบของเฟลิกซ์คิง) เรียกร้องให้ U + FEFF พิจารณาช่องว่างในซอร์สโค้ดของ JS U + FFFE ไม่ได้อยู่ในรายการ แต่สิ่งนี้ทำให้ฉันเป็นข้อผิดพลาดในการละเลย
zwol

1
@zwol ไม่ใช่ข้อผิดพลาดของการละเว้นเนื่องจากไม่มีอักขระ U + FFFE ถือว่าเป็นช่องว่างเป็นข้อผิดพลาด ที่จริงแล้วการถือมันเป็นตัวละครที่ถูกต้องเป็นข้อบกพร่องในกรณีส่วนใหญ่ U + 0085 ไม่ใช่พื้นที่สีขาวตามสเปคของ JS แต่สเป็คที่ต้องการเคสพิเศษของ U + 0085 เพื่อไม่ให้ขึ้นบรรทัดใหม่นั้นแปลกประหลาดและเป็นจุดบกพร่องของสเป็ค
Jon Hanna

56

ปรากฏว่าตัวละครที่คุณใช้นั้นยาวกว่าเครื่องหมายลบจริง (ยัติภังค์) จริง

 
-

ด้านบนคือสิ่งที่คุณกำลังใช้ด้านล่างคือเครื่องหมายลบควรเป็น คุณดูเหมือนจะรู้แล้วตอนนี้ดังนั้นมาดูกันว่าทำไม Javascript ถึงทำเช่นนี้

อักขระที่คุณใช้จริง ๆ แล้วเป็นเครื่องหมายช่องว่างของ oghamซึ่งเป็นอักขระช่องว่างดังนั้นโดยทั่วไปจะถูกตีความว่าเป็นสิ่งเดียวกับช่องว่างซึ่งหมายความว่าคำสั่งของคุณดูเหมือนalert(2+ 40)จาวาสคริปต์

มีตัวละครอื่น ๆ เช่นนี้ใน Javascript คุณสามารถดูรายการเต็มรูปแบบที่นี่ในวิกิพีเดีย


สิ่งที่น่าสนใจที่ฉันสังเกตเห็นเกี่ยวกับตัวละครนี้คือวิธีที่ Google Chrome (และเบราว์เซอร์อื่น ๆ ที่เป็นไปได้) ตีความมันในแถบด้านบนของหน้า

ป้อนคำอธิบายรูปภาพที่นี่

มันเป็นบล็อกที่มี1680ด้านในของมัน นั่นคือหมายเลขยูนิโค้ดสำหรับเครื่องหมายช่องว่างของ ogham มันดูเหมือนจะเป็นแค่เครื่องจักรของฉันที่ทำสิ่งนี้ แต่มันแปลก


ฉันตัดสินใจลองใช้ภาษาอื่นเพื่อดูว่าเกิดอะไรขึ้นและนี่คือผลลัพธ์ที่ฉันได้รับ


ภาษาที่ใช้ไม่ได้:

Python 2 และ 3

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

ทับทิม

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

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

ภาษาใช้งานได้:

โครงการ

>> (+ 240)
=> 42

C # (ภายในMain()วิธีการ)

Console.WriteLine(2+ 40);

Output: 42

Perl 6

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

34
Ubuntu ไม่ใช่ปัญหา แบบอักษรชื่อหน้าต่างที่คุณใช้คือ
PSkocik

2
firefox (iceweasel) และ google chrome บนเดเบียนดูเหมือนจะแสดงตัวยูนิโค้ดถ่านได้ดีแม้ว่าฉันจะใช้งานได้นานพอที่จะให้ความเข้ากันได้กับ Unicode ในระบบของฉัน (อันที่จริงสิ่งที่มีประโยชน์ที่สุดที่ฉันทำคือเรียบง่ายที่สุด: sudo apt-get install unicodeแม้ว่าจะผ่านไปหลายชั่วโมงหลังจากการวิจัยและความพยายามที่ล้มเหลว)
sig_seg_v

@PSkocik ที่น่าสนใจฉันมีปัญหาเกี่ยวกับแบบอักษรที่นี่ก่อนเพื่อที่จะเป็นไปได้
michaelpri

51
@PSkocik “ Ubuntu ไม่ใช่ปัญหา แบบอักษรชื่อหน้าต่างที่คุณใช้คือ” …ซึ่งก็คือ“ Ubuntu
user4642212

1
@PSkocik ในที่สุดฉันก็ซ่อมมัน :) เพียงแค่ต้องเปลี่ยนแบบอักษรของแถบชื่อระบบ
michaelpri

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)

unicodeหากเป็นสำเนาและวางจากสถานีของคุณผมอยากทราบว่าคุณพบคำสั่ง
BenjiWiebe

16
มาจากแพ็คเกจ Ubuntu ที่มีชื่อว่า (รอเลย ... ) unicodeโดย Radovan Garabík ซื้อคืนภาคที่สอดคล้องกันคือที่github.com/garabik/unicode
PSkocik

ตกลงขอบคุณสำหรับลิงค์ github AFAICT ไม่ใช่ใน repos ของ Fedora
BenjiWiebe

@PSkocik ' '.codePointAt(0)ที่คอนโซลจะให้ผล 5760 ตอนนี้ google 5760 unicode
Royi Namir

6

ฉันก็อยากจะรู้ว่ามีตัวละครมากขึ้นเช่นนี้หรือไม่

ฉันดูเหมือนจะจำการอ่านสักครู่เกี่ยวกับการแทนที่เซมิโคลอน (U + 003B) ในโค้ดของบางคนด้วย U + 037E ซึ่งเป็นเครื่องหมายคำถามกรีก

พวกเขาทั้งสองมีลักษณะเหมือนกัน (เท่าที่ฉันเชื่อว่าชาวกรีกใช้ U + 003B) แต่บทความนี้ระบุว่าอีกคนไม่ทำงาน

ข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้จาก Wikipedia อยู่ที่นี่: https://en.wikipedia.org/wiki/Question_mark#Greek_question_mark

และคำถาม (ปิด) เกี่ยวกับการใช้สิ่งนี้เป็นเรื่องตลกจากตัวมันเอง ไม่ใช่ที่แรกเริ่มฉันอ่านว่า AFAIR: JavaScript Prank / Joke

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.