2+ 40 neden 42'ye eşittir?


360

Bir meslektaşım 42 JavaScript uyarısını bu satırda gösterdiğinde şaşırdım.

alert(2+ 40);

Bir eksi işaretine benzeyen şeyin aslında açıkça farklı semantiklere sahip bir gizli Unicode karakteri olduğu ortaya çıkıyor.

Bu, ifade ayrıştırıldığında neden bu karakterin sözdizimi hatası üretmediğini merak etmemi sağladı. Ayrıca böyle davranan daha fazla karakter olup olmadığını bilmek istiyorum.


28
@Elyasin Kopyaladınız / yapıştırdınız veya yeniden yazdınız mı?
user253751

4
Bu, Visual C # ile de çalışır. Garip karakteri Visual Studio IDE'ye yapıştırırken veya ifadeyi yazarak tamamlarken, ;editör garip `` karakteri normal bir alana değiştirme eğilimindedir, ancak bu "otomatik düzeltme" yi geri alırsanız aynı davranışa sahip olursunuz . Bu karakter, tire veya eksi (normal yazı tiplerinde) gibi görünse bile boşlukla aynı anlambilime sahiptir.
Jeppe Stig Nielsen

4
Bunun tersi de olabilir. Tanımlayıcılarda unicode'u destekleyen bazı diller beyaz boşluk gibi görünen unicode karakterleri kabul eder (başka bir deyişle, onları göremezsiniz); tamamen görünmez tanımlayıcılara sahip olmak bile mümkün olabilir.
gnasher729

58
(OT) Çünkü 42 her şeye
ivan_pozdeev

4
Beklenmedik sonucun bu Unicode karakterinden kaynaklanmış olması gerçeği zaten belliydi.
GOTO 0

Yanıtlar:


470

Bu karakter bir uzay karakteri olan "OGHAM UZAY MARKU" dur . Yani kod eşdeğerdir alert(2+ 40).

Ayrıca böyle davranan daha fazla karakter olup olmadığını bilmek istiyorum.

Zs sınıfındaki herhangi bir Unicode karakteri, JavaScript'te bir boşluk karakteridir , ancak bu kadar çok görünmüyor .

Bununla birlikte, JavaScript aynı zamanda tanımlayıcılarda Unicode karakterlere izin verir , bu da gibi ilginç değişken adları kullanmanıza izin verir ಠ_ಠ.


3
Onaltılık kodlu kutu alt çizgi altıgen kodlu kutu. Hangi karakter olmalı?
user253751

12
@immibis Bu yanıtın son kısmı disapprovallook.com
Mark S.

3
ZsJavaScript'te yalnızca karakterlerin beyaz boşluk olarak kabul edilmediğini unutmayın . Daha fazlası da var: github.com/mathiasbynens/regexpu/blob/…
Mathias Bynens

20
Tepkim ಠ_ಠJS bir tanımlayıcı olarak kullanılabilir: ಠ_ಠ
Chris Cirefice

2
@ChrisCirefice harf olarak ele alınan alt çizgi, C tarzı dillerinde uzun süredir devam etmektedir. mektup olarak muamele görmek sadece sağduyu, çünkü bir mektup. ಠ_ಠTanımlayıcı olarak kullanılamazsa açık bir hata olur .
Jon Hanna

81

Diğer cevapları okuduktan sonra, beyaz boşluklar gibi davranan U + 0000 – U + FFFF aralığındaki tüm Unicode karakterleri bulmak için basit bir komut dosyası yazdım. Görünüşe göre, tarayıcıya bağlı olarak 26 veya 27 tane var, U + 0085 ve U + FFFE ile ilgili anlaşmazlıklar var.

Bu karakterlerin çoğunun normal bir beyaz boşluğa benzediğini unutmayın.


17
U + 0085 "NEL", Unicode tarafından boşluk olarak tanımlanır, ancak yanlış kullanımın uzun bir geçmişi vardır. U + FFFE, NChar dışında ad ve özellik içermeyen bir karakter değildir ve makul bir şey tarafından boşluk olarak düşünülmemelidir. Bununla birlikte, tarayıcım her iki noktada da benimle aynı fikirde değil :)
ocaklar

4
@hobbs U + FFFE de a \p{Default Ignorable Code Point}değil, sadece a \p{Noncharacter Code Pount}. U + 0085 her zaman bir \p{Whitespace}kod noktası olmuştur. Kötülük, “son zamanlarda” \p{Whitespace}mülkünü kaybeden U + 180E Moğolca Sesli Ayırıcıdır . Not \p{Pattern Whitespace}çok daha küçük bir set olduğu ve değişmez bir özellik. Ama \p{Whitespace}değil.
tchrist

2
FEFFMalzeme Listesidir ve metinler içinde "sıfır genişlik aralıksız boşluk" olarak ele alınabilir. FFFEendian takas eşdeğeri. Belki de bazı tarayıcıların tedavi etmesinin nedeni boşluktur.
CodesInChaos

ecma-international.org/ecma-262/6.0/#sec-white-space (Felix King'in cevabına bağlı olarak) özellikle U + FEFF'yi JS kaynak kodunda boşluk olarak kabul eder. U + FFFE listede yok, ancak bu bir ihmal hatası olarak bana çarpıyor.
zwol

1
@zwol, bu bir ihmal hatası değildir, çünkü U + FFFE karakteri yoktur. Boşluk gibi davranmak bir hatadır. Gerçekten de, ona geçerli bir karakter olarak davranmak çoğu durumda bir hatadır. U + 0085, JS spektrumuna göre beyaz boşluk değildir, ancak spesifikasyonun yeni bir hat olmamak için U + 0085'in özel muhafazasını gerektirmesi tuhaftır ve spesifikasyonda bir hatadır.
Jon Hanna

56

Kullandığınız karakterin gerçek eksi işaretinden (tire) daha uzun olduğu anlaşılıyor.


-

Üst kısım kullandığınız şey, alt kısım eksi işaretinin olması gerektiği. Bunu zaten biliyor gibisiniz, şimdi Javascript'in bunu neden yaptığını görelim.

Kullandığınız karakter aslında bir boşluk karakteri olan ogham boşluk işaretidir , bu nedenle temelde boşlukla aynı şey olarak yorumlanır, yani ifadeniz alert(2+ 40)Javascript'e benziyor .

Javascript'te bunun gibi başka karakterler var. Vikipedi'de tam bir liste görebilirsiniz .


Bu karakter hakkında fark ettiğim ilginç bir şey, Google Chrome'un (ve diğer olası tarayıcıların) bunu sayfanın üst çubuğunda yorumlama şeklidir.

resim açıklamasını buraya girin

İçinde bir bloktur 1680. Aslında ogham uzay işaretinin unicode numarası. Sadece bunu yapan benim makinem gibi görünüyor, ama garip bir şey.


Ne olduğunu görmek için bunu diğer dillerde denemeye karar verdim ve elde ettiğim sonuçlar bunlar.


Çalışmadığı diller:

Python 2 ve 3

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

Yakut

>> 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 ( mainyöntemin içinde )

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

Git

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

Çalıştığı diller:

düzen

>> (+ 240)
=> 42

C # ( Main()yöntemin içinde )

Console.WriteLine(2+ 40);

Output: 42

Perl 6

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

34
Sorun Ubuntu değil. Kullandığınız pencere başlığı yazı tipi.
PSkocik

2
Firefox (iceweasel) ve debian'da google chrome unicode char'ı gayet iyi gösteriyor gibi görünse de, sistemimde unicode uyumluluğu sağlamak için uzunluklara gitmiştim. (aslında, yaptığım en yararlı şey en sudo apt-get install unicode
basitiydi

@PSkocik İlginç, daha önce burada yazı tipi sorunları yaşadım, bu muhtemelen
michaelpri

51
@PSkocik “Sorun Ubuntu değil. Kullandığınız pencere başlığı yazı tipi. ” … “ Ubuntu ”.
user4642212

1
@PSkocik Sonunda düzelttim :) Sadece sistem başlık çubuğu yazı tipini değiştirmek gerekiyordu.
michaelpri

43

Sanırım garip bir nedenden dolayı boşluk olarak sınıflandırdığı bir şey yapmak zorunda:

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

Bu terminalinizden bir kopyala yapıştır ise, komutu nerede bulduğunuzu bilmek istiyorum unicode.
BenjiWiebe

16
unicodeRadovan Garabík tarafından adlandırılan (bekleyin ...) adlı Ubuntu paketinden . İlgili repo, github.com/garabik/unicode adresindedir .
PSkocik

Tamam, github bağlantısı için teşekkürler. AFAICT, Fedora depolarında değil.
BenjiWiebe

Konsolda ' '.codePointAt(0)@PSkocik 5760 getirecek. Şimdi google 5760 unicode.
Royi Namir

6

Ayrıca böyle davranan daha fazla karakter olup olmadığını bilmek istiyorum.

Birisinin kodunda Yunan soru işareti olan U + 037E ile yarı-sütunların (U + 003B) yaramaz bir şekilde değiştirilmesi hakkında bir süre okuduğumu hatırlıyorum.

Her ikisi de aynı görünüyor (Yunanlıların U + 003B kullandıklarına inanıyorum) ama bu makale diğerinin işe yaramayacağını belirtti.

Wikipedia'dan bu konuda daha fazla bilgi burada: https://en.wikipedia.org/wiki/Question_mark#Greek_question_mark

Ve bunu SO'nun şakası olarak kullanma konusunda kapalı bir soru. Aslında başlangıçta AFAIR okumak değil: JavaScript Prank / Joke

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.