Bir tilde bir ifadeden önce geldiğinde ne yapar?


Yanıtlar:


268

~Bir olan bit düzeyinde operatör kendi işlenen tüm bitlerini çevirir.

Örneğin, numaranız IEEE 754 şamandıra (JavaScript'in sayıları nasıl ele 1aldığı) ikili temsili olurdu ...

0011 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

Yani ~işlenenini 32 bit tam sayıya dönüştürür (JavaScript'teki bitsel operatörler bunu yapar) ...

0000 0000 0000 0000 0000 0000 0000 0001

Negatif bir sayı olsaydı, 2'nin tamamlayıcısı içinde saklanırdı: tüm bitleri tersine çevir ve 1'i ekle.

... ve sonra tüm parçalarını çevirir ...

1111 1111 1111 1111 1111 1111 1111 1110

Peki bunun faydası ne? Ne zaman kullanılabilir?

Birkaç kullanım alanı vardır. Düşük seviyeli şeyler yazıyorsanız, kullanışlı. Uygulamanızı profillendirdiyseniz ve bir darboğaz bulduysanız, bitsel hileler ( daha büyük bir çantada olası bir araç olarak) kullanılarak daha performans gösterilebilir .

Ayrıca (genellikle) belirsiz hile açmak için indexOf()s' bulundu içine dönüş değeri truthy (yapmada ise bulunamadı olarak falsy ) ve insanlar genellikle Katlama tarafından 32 bite numaralarını kesiliyor (ve ondalık yeri bırakarak onun yan etkisi için kullanmak, Math.floor()pozitif sayılarla aynı şekilde etkili ).

Diyorum belirsiz bunun için kullanılıyor hemen belli gibi değil çünkü. Genel olarak, kodunuzun okuyan diğer kullanıcılarla net bir şekilde iletişim kurmasını istersiniz. Kullanırken ~olabilir serin bakmak , genellikle kendi iyiliği için çok zeki. :)

O JavaScript sahip olduğunu da artık daha az alakalı Array.prototype.includes()ve String.prototype.includes(). Bunlar bir boolean değeri döndürür. Hedef platformlarınız destekliyorsa, bunu bir dizede veya dizide bir değerin olup olmadığını test etmek için tercih etmelisiniz.


2
Kötü doğru kelime mi? Eğer işe yararsa, sadece bir dil deyimi diyecektim. Birçok deyim var. Onları öğrendikten sonra belirsiz değiller. Bunları bilmiyorsanız ve daha ayrıntılı döngülerle gerçekleştirilebiliyorsa, Python'da liste anlaşmaları net değildir, ancak asla bir Python programcısından bunları kullanmamasını istemezsiniz. Benzer şekilde value = value || defaultJavaScript'te de, ne zaman kullanabileceğinizi ve kullanamayacağınızı bildiğiniz sürece yaygın ve geçerli bir deyimdir.
gman

3
@gman Sanırım birisinin kullanması önemli değil. Liste kavrayışlarını (dil özelliği) bununla karşılaştırmak gerçekten aynı şey değil ( bazı ekstra karakterler yazmaktan kaçınmanın akıllı yolu). Kötü bir terimin çok sert olduğunu düşünüyorsanız , lütfen cevabımı düzenlemek için çekinmeyin.
alex

2
Belki daha yaygın bir örnek v = t ? a : b;. Ben var v; if (t} { v = a; } else { v = b; }genellikle 5+ satır kırık daha net ve aynı zamanda var v = b; if (t) { v = a; }genellikle 4 + satır daha net buluyorum . Ama ? :ikinci veya üçüncü yolu tercih edecek operatörlere aşina olmayan birçok insan tanıyorum . İlkinin daha okunabilir olduğunu düşünüyorum. Genel prensibe katılıyorum, kodu netleştirin, kesmek kullanmayın. Sanırım ~v.indexOf('...')öğrendikten sonra çok net görüyorum .
gman

9
Birçok geliştiriciyle büyük bir şirkette çalışırken, kodun açıkça yazılmasını (İNGİLİZCE) ve iyi belgelenmesini istiyorsunuz. Çöp toplama özelliğine sahip bir dilde üst düzey kodlamanın amacı, ikili işlemler hakkında düşünmekten kaçınmaktır ve birçok ön uç geliştiricinin kemerleri altında montaj dili deneyimi bile yoktur.
user2867288

3
i demezdim ~deyimsel. teknik olarak dil spesifikasyonunun bir parçasıdır , ancak genel kullanımda dilin bir parçası değildir .
worc

110

Bir indexOf()ifadeden önce kullanmak, doğrudan döndürülen sayısal dizin yerine doğru / yanlış bir sonuç verir.

Dönüş değeri ise -1, o zaman ~-1olduğu 0çünkü -1her 1 bit bir dizedir. Sıfıra eşit veya sıfırdan büyük herhangi bir değer sıfırdan farklı bir sonuç verecektir. Böylece,

if (~someString.indexOf(something)) {
}

if"someString" içinde "bir şey" olduğunda kodun çalışmasına neden olur . .indexOf()Doğrudan bir boolean olarak kullanmaya çalışırsanız , bu işe yaramaz çünkü bazen sıfır döndürür ("bir şey" dizenin başında olduğunda).

Tabii ki, bu da işe yarıyor:

if (someString.indexOf(something) >= 0) {
}

ve çok daha az gizemli.

Bazen bunu da görürsünüz:

var i = ~~something;

~İşleci bu şekilde iki kez kullanmak, bir dizeyi 32 bit tam sayıya dönüştürmenin hızlı bir yoludur. Birincisi ~dönüşümü yapar ve ikincisi ~bitleri geri çevirir. Elbette, operatör bir sayıya dönüştürülemeyen bir şeye uygulanırsa, NaNsonuç olarak elde edersiniz . ( düzenle - aslında ~ilk uygulanan ikinci, ama fikri anladınız.)


2
~Tamsayılarla yapıldığında yavaş yavaş olumsuzlamak istemeyenler için eşittir -(x + 1).
Fabrício Matté

Görünüşe göre, NEGATİF sayısal değerler ilk başta negatif boole değerlerini de döndürmelidir. Ama JS'nin sadece bir diğeri başarısız, sanırım?
wwaawaw

7
@adlwalrus, 0varlık falseve sıfır olmayan varlık geleneği trueen azından 70'lerde C'ye ve muhtemelen diğer çağdaş sistem programlama dillerine kadar uzanır. Muhtemelen donanımın çalışma şeklinden kaynaklanmaktadır; birçok CPU bir işlemden sonra sıfır biti ayarlar ve test etmek için karşılık gelen bir dal talimatına sahiptir.
Sivri

4
32 bit int'e dönüştürmenin daha hızlı bir yolu | 0, bu durumda tek bir işlem olacaktır.
alex

@alex gerçekten de basit bir uygulamayı ~~aynı şekilde yorumlamamak için çalışma zamanına güvenemeyiz .
Sivri

30

~Olduğu Bit DEĞİL Operatör , ~xkabaca aynıdır -(x+1). Bunu anlamak daha kolay. Yani:

~2;    // -(2+1) ==> -3

Düşünün -(x+1). -1üretmek için bu işlemi yapabilir 0.

Başka bir deyişle, ~bir dizi sayı değeriyle birlikte kullanıldığında, yalnızca girdi değeri için bir yanlış (zorlama-den- falsearası 0) -1değeri oluşur, aksi takdirde başka bir doğruluk değeri üretir.

Bildiğimiz gibi -1, genellikle sentinel değeri denir . Başarı ve başarısızlık için >= 0değer döndüren birçok işlev için kullanılır-1 C dilinde. indexOf()JavaScript ile aynı dönüş değeri kuralı .

Bu şekilde başka bir dizede bir alt dizenin varlığını / yokluğunu kontrol etmek yaygındır

var a = "Hello Baby";

if (a.indexOf("Ba") >= 0) {
    // found it
}
if (a.indexOf("Ba") != -1) { 
    // found it
}

if (a.indexOf("aB") < 0) { 
    // not found
}
if (a.indexOf( "aB" ) == -1) { 
    // not found
}

Ancak, ~aşağıdaki gibi yapmak daha kolay olurdu

var a = "Hello Baby";

~a.indexOf("Ba");         // -7   -> truthy
if (~a.indexOf("Ba")) {   // true
    // found it
}

~a.indexOf("aB");         // 0    -> falsy
!~a.indexOf("aB");        // true
if (!~a.indexOf( "aB" )) {  // true
    // not found
}

Bilmiyorsun JS: Türler ve Gramer Kyle Simpson


1
Bu var kesinlikle bir kişinin çalışması yapan bir arka plan anlamıyor bile, yüz değerinde anlamak daha kolay. -(x+1)Bir if ifadesinde görüp görmediğime ikinci kez bakarım . Tilde bana Javascript'in 0 tabanlı doğasını telafi etmek için ne yaptığını söylüyor. Ayrıca, daha az parantez okumak için daha iyi
Düzenli Joe

İlk kontrol kodu bloğunuzda if (a.indexOf("Ba") > -1) {// found} //true, tilde örneklerinden biraz daha uzun olmasına rağmen, verdiğiniz iki örnekten ve yeni programcılar için var opinion = !~-1 ? 'more' : 'less'anlaşılabilir olandan daha az olan kullanarak daha az yazabilirsiniz .
HalfMens

25

~indexOf(item) oldukça sık ortaya çıkıyor ve buradaki cevaplar harika, ama belki de bazı insanlar bunu nasıl kullanacağını bilmeli ve teoriyi "atlamalı":

   if (~list.indexOf(item)) {
     // item in list
   } else {
     // item *not* in list
   }

1
Hemfikirim. Airbnb JavaScript Stil Rehberi izin vermiyor ++ve --"aşırı hileyi teşvik ediyorlar" ve yine de bir şekilde ~hayatta kaldılar (gölgelerde gizleniyorlar) github.com/airbnb/javascript/issues/540
Shanimal

@Shanimal Alternatif list.indexOf(item) >= 0veya ... > -1javascript sıfır temelli olduğundan ve bu sorunu en baştan ele almayı seçmedi. Dahası, sadece görüş (Airbnb'lerle aynı), javascriptte anlamlı bir şey yapan herkes bilir ++ve --daha az yaygın olsa da, anlam çıkarılabilir.
Düzenli Joe

@RegularJoe Buna katılıyorum. Kişisel olarak ihtiyaç duymadım ++ve --bir süre mapsonra forEachvb ~. Bir şeyi yasaklamak için CIS101 hiçbir anlam ifade etmiyor.
Shanimal

12

Bir sonuçtan doğruluk değeri oluşturmak için yaklaşık işareti kullanmayı düşünenlerindexOf için, daha açıktır ve bunun yerine includesyöntemiString kullanmak için daha az sihir vardır .

'hello world'.includes('hello') //=> true
'hello world'.includes('kittens') //=> false

Bunun ES 2015'ten itibaren yeni bir standart yöntem olduğunu ve eski tarayıcılarda çalışmadığını unutmayın. Bunun önemli olduğu durumlarda, String.prototype.incfind çoklu dolguyu kullanmayı düşünün .

Bu özellik aynı sözdizimini kullanan diziler için de kullanılabilir :

['apples', 'oranges', 'cherries'].includes('apples') //=> true
['apples', 'oranges', 'cherries'].includes('unicorns') //=> false

Daha eski tarayıcı desteğine ihtiyacınız varsa Array.prototype.incfits çoklu dolgusunu burada bulabilirsiniz .


2
İnclude () kullanmaktan kaçının. Yazma
sırasında IE'nin

8
Ya da sadece bir derleyici kullanın, böylece dili en kötü ortak payda JS yorumlayıcısına göre yazmak yerine daha net bir kod yazabilirsiniz ...
Kyle Baker

2
@Ben haklı, Netscape 4.72'de de çalışmıyor.
mikemaccana
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.