Apakah yang !! (tidak tidak) operator di JavaScript?

3108

Saya melihat beberapa kode yang tampaknya menggunakan operator saya tidak mengenali, dalam bentuk dua tanda seru, seperti: !!. Bisakah seseorang tolong beri tahu saya apa yang dilakukan operator ini?

Konteks di mana saya melihat ini adalah,

this.vertical = vertical !== undefined ? !!vertical : this.vertical;
Teori Hexagon
sumber
946
Ingat itu dengan "bang, bang kau boolean"
Gus
75
Sebagai catatan, jangan lakukan apa yang dikutip di sana. Do if(vertical !== undefined) this.vertical = Boolean(vertical);- jauh lebih bersih dan lebih jelas apa yang sedang terjadi, tidak memerlukan tugas yang tidak perlu, sepenuhnya standar, dan secepat (pada FF dan Chrome saat ini) jsperf.com/boolean-conversion-speed .
Phil H
73
!! bukan operator. Itu hanya! operator dua kali.
Vivek
11
Hanya sebagai catatan, Boolean(5/0)tidak sama dengan!!5/0
schabluk
63
@ schabluk, sebagai catatan, urutan operasi adalah alasan !!5/0menghasilkan Infinitydaripada true, seperti yang diproduksi oleh Boolean(5/0). !!5/0setara dengan (!!5)/0- alias true/0- karena !operator memiliki prioritas lebih tinggi daripada /operator. Jika Anda ingin Booleanize 5/0menggunakan double-bang, Anda harus menggunakannya !!(5/0).
matty

Jawaban:

2748

Konversi Objectke boolean. Jika itu falsey (misalnya 0, null, undefined, dll), itu akan menjadi false, jika tidak, true.

!oObject  // inverted boolean
!!oObject // non inverted boolean so true boolean representation

Jadi !!bukan operator, itu hanya !operator dua kali.

Contoh Dunia Nyata "Uji versi IE":

const isIE8 = !! navigator.userAgent.match(/MSIE 8.0/);  
console.log(isIE8); // returns true or false 

Jika Anda ⇒

console.log(navigator.userAgent.match(/MSIE 8.0/));  
// returns either an Array or null  

Tetapi jika Anda ⇒

console.log(!!navigator.userAgent.match(/MSIE 8.0/));  
// returns either true or false
stevehipwell
sumber
123
Ini mengkonversi nonboolean menjadi boolean terbalik (misalnya,! 5 akan salah, karena 5 adalah nilai non-salah dalam JS), lalu boolean-membalikkan itu sehingga Anda mendapatkan nilai asli sebagai boolean (jadi !! 5 akan benar).
Chuck
111
Cara mudah untuk menggambarkannya adalah: Boolean (5) === !! 5; Casting yang sama, lebih sedikit karakter.
Micah Snyder
39
Ini digunakan untuk mengubah nilai kebenaran menjadi boolean true, dan nilai falsy terlalu boolean false.
thetoolman
13
@Micah Snyder berhati-hatilah bahwa dalam JavaScript lebih baik menggunakan boolean primitif daripada membuat objek yang membuat boolean kotak dengan Boolean baru (). Berikut ini contoh untuk melihat perbedaannya: jsfiddle.net/eekbu
victorvartan
4
Sejauh yang saya tahu, pola bang-bang ini tidak berguna di dalam pernyataan if (... _; hanya dalam pernyataan pengembalian fungsi yang seharusnya mengembalikan boolean.
rds
854

Ini adalah cara yang sangat tidak jelas untuk melakukan konversi tipe.

!adalah TIDAK . Begitu !truejuga false, dan !falsesekarang true. !0adalah true, dan !1sekarang false.

Jadi, Anda mengonversi nilai menjadi boolean, lalu membalikkannya, lalu membalikkannya lagi.

// Maximum Obscurity:
val.enabled = !!userId;

// Partial Obscurity:
val.enabled = (userId != 0) ? true : false;

// And finally, much easier to understand:
val.enabled = (userId != 0);
Tom Ritter
sumber
74
!! false = false. !! true = true
cllpse
89
Apakah varian "jauh lebih mudah dipahami" benar-benar lebih mudah dipahami di sini? Pemeriksaan terhadap 0 bukanlah pemeriksaan aktual terhadap 0, tetapi pemeriksaan terhadap daftar nilai Javascript yang agak aneh dianggap sama dengan 0. userId ? true : false membuat lebih jelas bahwa ada konversi yang terjadi dan menangani kasus di mana nilai userId mungkin telah secara eksplisit diatur keundefined
Ben Regenspan
54
Otak saya tidak memiliki masalah menguraikan !!varke dalam Boolean(var).. dan !!lebih cepat (lebih sedikit instruksi untuk diproses) dan lebih pendek dari alternatif.
adamJLev
7
@ RickyClarkson terutama untuk keterbacaan karena secara sintaksis tidak diperlukan. Beberapa menggunakan konvensi untuk selalu membungkus sebuah tanda kurung dalam kurung untuk membedakannya dari sisa ekspresi.
Dave Rager
8
Saya tidak setuju dengan ini. userId != 0benar untuk null, NaNdan undefined, tetapi salah untuk false. Jika Anda menginginkan perilaku itu, Anda mungkin harus menjelaskannya. Tetapi bahkan jika itu bekerja persis sama dengan !!userId, tidak jelas apakah Anda ingin nilai-nilai tersebut menjadi salah di sini, atau apakah Anda hanya gagal mempertimbangkan aturan konversi tipe Javascript.
philh
449

!!exprmengembalikan nilai Boolean ( trueatau false) tergantung pada kebenaran ekspresi. Lebih masuk akal bila digunakan pada jenis non-boolean. Pertimbangkan contoh-contoh ini, terutama contoh ke-3 dan selanjutnya:

          !!false === false
           !!true === true

              !!0 === false
!!parseInt("foo") === false // NaN is falsy
              !!1 === true
             !!-1 === true  // -1 is truthy

             !!"" === false // empty string is falsy
          !!"foo" === true  // non-empty string is truthy
        !!"false" === true  // ...even if it contains a falsy value

     !!window.foo === false // undefined is falsy
           !!null === false // null is falsy

             !!{} === true  // an (empty) object is truthy
             !![] === true  // an (empty) array is truthy; PHP programmers beware!
Salman A
sumber
63
Layak dicatat:!!new Boolean(false) // true
Camilo Martin
43
... Tetapi juga!!Boolean(false) // false
Camilo Martin
97
new Boolean(false)adalah sebuah objek dan sebuah objek adalah benar bahkan jika itu mengandung nilai palsu!
Salman A
3
Ya aku tahu, tapi mempertimbangkan fakta bahwa sebagian besar konstruktor asli ( String, Number, Date, dll) yang dimaksudkan untuk menjadi callable sebagai fungsi juga, namun dalam hal ini hasilnya berbeda!
Camilo Martin
4
@ CamiloMartin: baru menyadari bahwa new Boolean(false)mengembalikan suatu objectsaat Boolean(false)mengembalikan primitif false . Semoga ini masuk akal.
Salman A
155

Seduh teh:

!!bukan operator. Ini adalah penggunaan ganda !- yang merupakan operator "bukan" yang logis.


Dalam teori:

! menentukan "kebenaran" dari nilai yang bukan:

  • Yang benar adalah falsetidak true(itu sebabnya !falsehasil true)

  • Yang benar adalah truetidak false(itu sebabnya !truehasil false)


!!menentukan "kebenaran" tentang apa nilai yang tidak tidak:

  • Yang benar adalah itu truebukan tidak true (itu sebabnya !!truehasil true)

  • Yang benar adalah itu falsebukan tidak false (itu sebabnya !!falsehasil false)


Apa yang ingin kita tentukan dalam perbandingan adalah "kebenaran" tentang nilai referensi, bukan nilai referensi itu sendiri. Ada kasus penggunaan di mana kita mungkin ingin mengetahui kebenaran tentang suatu nilai, bahkan jika kita mengharapkan nilainya false(atau falsey), atau jika kita mengharapkan nilainya tidak menjadi tipe boolean.


Dalam praktek:

Pertimbangkan fungsi ringkas yang mendeteksi fungsionalitas fitur (dan dalam hal ini, kompatibilitas platform) dengan cara mengetik dinamis (alias "mengetik bebek"). Kami ingin menulis fungsi yang kembali truejika browser pengguna mendukung <audio>elemen HTML5 , tetapi kami tidak ingin fungsi tersebut memunculkan kesalahan jika <audio>tidak terdefinisi; dan kami tidak ingin menggunakan try ... catchuntuk menangani kemungkinan kesalahan (karena itu kotor); dan juga kami tidak ingin menggunakan pemeriksaan di dalam fungsi yang tidak akan secara konsisten mengungkapkan kebenaran tentang fitur (misalnya, document.createElement('audio')masih akan membuat elemen yang disebut <audio>bahkan jika HTML5 <audio>tidak didukung).


Inilah tiga pendekatan:

// this won't tell us anything about HTML5 `<audio>` as a feature
var foo = function(tag, atr) { return document.createElement(tag)[atr]; }

// this won't return true if the feature is detected (although it works just fine)
var bar = function(tag, atr) { return !document.createElement(tag)[atr]; }

// this is the concise, feature-detecting solution we want
var baz = function(tag, atr) { return !!document.createElement(tag)[atr]; }

foo('audio', 'preload'); // returns "auto"
bar('audio', 'preload'); // returns false
baz('audio', 'preload'); // returns true

Setiap fungsi menerima argumen untuk a <tag>dan attributemencari, tetapi masing-masing mengembalikan nilai yang berbeda berdasarkan apa yang ditentukan perbandingan.

Tapi tunggu, masih ada lagi!

Beberapa dari Anda mungkin memperhatikan bahwa dalam contoh khusus ini, seseorang dapat dengan mudah memeriksa properti menggunakan cara yang sedikit lebih berkinerja memeriksa apakah objek tersebut memiliki properti. Ada dua cara untuk melakukan ini:

// the native `hasOwnProperty` method
var qux = function(tag, atr) { return document.createElement(tag).hasOwnProperty(atr); }

// the `in` operator
var quux = function(tag, atr) { return atr in document.createElement(tag); }

qux('audio', 'preload');  // returns true
quux('audio', 'preload'); // returns true

Kami ngelantur ...

Betapapun jarangnya situasi ini, mungkin ada beberapa skenario di mana cara yang paling ringkas, paling berkinerja, dan dengan demikian paling disukai untuk mendapatkan truedari non-boolean, mungkin nilai yang tidak ditentukan memang dengan menggunakan !!. Semoga ini dengan konyol membersihkannya.

Benny
sumber
1
jawaban yang benar-benar luar biasa, tetapi saya gagal melihat utilitas !! membangun. Karena if()pernyataan sudah melemparkan ekspresi ke boolean, secara eksplisit casting nilai kembali dari fungsi pengujian ke boolean adalah mubazir - karena "kebenaran" === benar sejauh if()pernyataan berjalan. Atau apakah saya melewatkan skenario di mana Anda MEMBUTUHKAN ekspresi yang benar-benar menjadi boolean true?
Tom Auger
1
if()Pernyataan @TomAuger melakukan cast boolean terhadap nilai falsey, tetapi katakan Anda ingin benar-benar mengatur flag boolean pada objek - itu tidak akan melemparkannya seperti if()pernyataan. Misalnya object.hasTheThing = !!castTheReturnValToBoolNoMatterWhat()akan menetapkan salah satu trueatau falsebukan nilai pengembalian nyata. Contoh lain adalah mungkin semua admin iddari 0dan non-admin id 1atau lebih tinggi. Untuk mendapatkan truejika seseorang bukan admin, Anda bisa melakukannya person.isNotAdmin = !!admin.id. Beberapa kasus penggunaan, tapi ringkas ketika ada.
Benny
103

!!mengkonversi nilai di sebelah kanan ke nilai boolean yang setara. (Pikirkan cara orang miskin "mengetik"). Its niat biasanya untuk menyampaikan kepada pembaca bahwa kode tidak peduli apa nilai dalam variabel, tapi apa itu "kebenaran" nilai adalah.

Crescent Fresh
sumber
4
Atau dalam hal nilai boolean di sebelah kanan, tidak ada artinya.
Daniel A. White
3
@Aniel: !masih membalik nilai ke kanan. Dalam kasus boolean yang paling kanan !meniadakan nilai, sedangkan yang paling kiri !meniadakan sekali lagi. Efek bersihnya adalah tidak ada perubahan, tetapi sebagian besar mesin akan menghasilkan kode op untuk negasi ganda.
Crescent Fresh
Tapi apa gunanya? Jika saya melakukan if(0){...Javascript sudah tahu ini salah. Mengapa lebih baik dikatakan if(!!0){...?
CodyBugstein
intinya adalah untuk variabel yang Anda mungkin tidak tahu isinya; jika bisa berupa integer atau string, objek atau null, tidak terdefinisi, dll. Ini adalah cara mudah untuk menguji keberadaan.
mix3d
71

!!fooberlaku unary not operator dua kali dan digunakan untuk cast ke tipe boolean mirip dengan unary plus +foountuk cast ke number dan menyatukan string kosong ''+foountuk cast ke string.

Alih-alih peretasan ini, Anda juga dapat menggunakan fungsi konstruktor yang terkait dengan tipe primitif ( tanpa menggunakan new) untuk secara eksplisit memberikan nilai, yaitu

Boolean(foo) === !!foo
Number(foo)  === +foo
String(foo)  === ''+foo
Christoph
sumber
Tapi kemudian Anda bisa mengalami masalah dengan instanceof. new Boolean (1) instanceof Object -> true !! 1 instanceof Object -> false
Seamus
13
tidak, Anda tidak bisa: perhatikan bahwa fungsi konstruktor dipanggil tanpa new- sebagaimana disebutkan secara eksplisit dalam jawaban saya
Christoph
2
fantastis! Ini berguna untuk retasan kecil ketika Anda perlu mengevaluasi string dengan "0" sebagai false, bukan true. (Yaitu ketika membaca nilai dari seleksi, karena mereka dibaca sebagai String). Jadi, jika Anda ingin menganggap "0" sebagai negatif (Boolean false), anggap x="0"saja melakukan: x=!!+x; //falseyang sama dengan Boolean(Number(x))Angka (atau + x) mengonversi string "0" menjadi 0, yang TIDAK bernilai false, dan kemudian Boolean (!! x) melemparkannya ke boolean secara langsung. Peasy mudah!
DiegoDD
2
@DiegoDD mengapa Anda memilih !!+xvs x !== "0"?
placeybordeaux
@placeybordeaux karena misalnya Anda mungkin ingin mengkonversi nilai dan menetapkannya ke variabel lain, terlepas dari apakah Anda akan membandingkannya dengan sesuatu yang lain atau tidak.
DiegoDD
67

Begitu banyak jawaban melakukan setengah pekerjaan. Ya, !!Xbisa dibaca sebagai "kebenaran X [diwakili sebagai boolean]". Tetapi !!secara praktis, tidak penting untuk menentukan apakah suatu variabel tunggal (atau bahkan jika banyak variabel) benar atau salah. !!myVar === truesama dengan adil myVar. Membandingkan !!Xdengan boolean "nyata" tidak terlalu berguna.

Apa yang Anda peroleh !!adalah kemampuan untuk memeriksa kebenaran beberapa variabel terhadap satu sama lain dengan cara yang berulang, standar (dan ramah JSLint).

Cukup casting :(

Itu adalah...

  • 0 === falseadalah false.
  • !!0 === falseadalah true.

Di atas tidak begitu berguna. if (!0)memberi Anda hasil yang sama dengan if (!!0 === false). Saya tidak bisa memikirkan kasus yang baik untuk casting variabel ke boolean dan kemudian membandingkan dengan boolean "benar".

Lihat "== dan! =" Dari arah JSLint (catatan: Crockford memindahkan situsnya sedikit; tautan itu mungkin akan mati pada beberapa titik) untuk sedikit alasan:

Operator == dan! = Melakukan paksaan sebelum membandingkan. Ini buruk karena menyebabkan '\ t \ r \ n' == 0 menjadi benar. Ini bisa menutupi kesalahan tipe. JSLint tidak dapat secara andal menentukan apakah == digunakan dengan benar, jadi yang terbaik adalah tidak menggunakan == dan! = Sama sekali dan selalu menggunakan operator === dan! == yang lebih andal.

Jika Anda hanya peduli bahwa suatu nilai itu benar atau salah, maka gunakan formulir singkat. Dari pada
(foo != 0)

hanya mengatakan
(foo)

dan bukannya
(foo == 0)

mengatakan
(!foo)

Perhatikan bahwa ada beberapa kasus tidak intuitif di mana boolean akan dilemparkan ke nomor ( truedilemparkan ke 1dan falseke 0) ketika membandingkan boolean dengan nomor. Dalam hal ini, !!mungkin bermanfaat secara mental. Meskipun, sekali lagi, ini adalah kasus di mana Anda membandingkan boolean non-boolean dengan hard-typed, yang merupakan, imo, kesalahan serius. if (-1)masih cara untuk pergi ke sini.

╔═══════════════════════════════════════╦═══════════════════╦═══════════╗
               Original                    Equivalent       Result   
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
 if (-1 == true) console.log("spam")    if (-1 == 1)       undefined 
 if (-1 == false) console.log("spam")   if (-1 == 0)       undefined 
   Order doesn't matter...                                           
 if (true == -1) console.log("spam")    if (1 == -1)       undefined 
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
 if (!!-1 == true) console.log("spam")  if (true == true)  spam       better
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
 if (-1) console.log("spam")            if (truthy)        spam       still best
╚═══════════════════════════════════════╩═══════════════════╩═══════════╝

Dan hal-hal menjadi lebih gila tergantung pada mesin Anda. WScript, misalnya, memenangkan hadiah.

function test()
{
    return (1 === 1);
}
WScript.echo(test());

Karena beberapa sejarah Windows jive , itu akan menampilkan -1 di kotak pesan! Cobalah di prompt cmd.exe dan lihat! Tapi WScript.echo(-1 == test())tetap memberi Anda 0, atau WScript false. Mengalihkan pandangan. Itu mengerikan.

Membandingkan kebenaran :)

Tetapi bagaimana jika saya memiliki dua nilai, saya perlu memeriksa kebenaran yang sama?

Berpura-puralah kita memiliki myVar1 = 0;dan myVar2 = undefined;.

  • myVar1 === myVar2adalah 0 === undefineddan jelas salah.
  • !!myVar1 === !!myVar2benar !!0 === !!undefineddan benar! Kebenaran yang sama! (Dalam hal ini, keduanya "memiliki kebenaran palsu".)

Jadi satu-satunya tempat Anda benar-benar perlu menggunakan "variabel boolean-cast" adalah jika Anda memiliki situasi di mana Anda memeriksa apakah kedua variabel memiliki kebenaran yang sama , bukan? Yaitu, gunakan !!jika Anda perlu melihat apakah dua vars keduanya benar atau keduanya palsu (atau tidak), yaitu, dengan kebenaran yang sama (atau tidak) .

Saya tidak bisa memikirkan kasus penggunaan yang hebat, tidak dibuat-buat untuk itu begitu saja. Mungkin Anda memiliki "tautan" bidang dalam formulir?

if (!!customerInput.spouseName !== !!customerInput.spouseAge ) {
    errorObjects.spouse = "Please either enter a valid name AND age " 
        + "for your spouse or leave all spouse fields blank.";
}

Jadi sekarang jika Anda memiliki kebenaran untuk keduanya atau kepalsuan untuk nama dan usia pasangan, Anda dapat melanjutkan. Kalau tidak, Anda hanya punya satu bidang dengan nilai (atau pernikahan yang diatur sangat awal) dan perlu membuat kesalahan tambahan pada errorObjectskoleksi Anda .


EDIT 24 Okt 2017, 6 Feb 19:

Perpustakaan pihak ketiga yang mengharapkan nilai Boolean eksplisit

Inilah kasus yang menarik ... !!mungkin berguna ketika lib pihak ke-3 mengharapkan nilai Boolean eksplisit.

Misalnya, False in JSX (React) memiliki arti khusus yang tidak dipicu oleh kepalsuan sederhana. Jika Anda mencoba mengembalikan sesuatu seperti yang berikut di BEJ Anda, mengharapkan int di messageCount...

{messageCount && <div>You have messages!</div>}

... Anda mungkin terkejut melihat React render a 0saat Anda memiliki nol pesan. Anda harus secara eksplisit mengembalikan false agar JSX tidak di-render. Pernyataan di atas kembali 0, yang dibuat oleh BEJ dengan senang hati, sebagaimana mestinya. Itu tidak bisa mengatakan Anda tidak punya Count: {messageCount && <div>Get your count to zero!</div>}(atau sesuatu yang kurang dibuat-buat).

  • Salah satu perbaikan melibatkan bangbang, yang memaksa 0ke dalam !!0, yang false:
    {!!messageCount && <div>You have messages!</div>}

  • Dokumen BEJ menyarankan Anda untuk lebih eksplisit, menulis kode komentar sendiri, dan menggunakan perbandingan untuk memaksa ke Boolean.
    {messageCount > 0 && <div>You have messages!</div>}

  • Saya lebih nyaman menangani sendiri kepalsuan dengan ternary -
    {messageCount ? <div>You have messages!</div> : false}

Kesepakatan yang sama dalam naskah: Jika Anda memiliki fungsi yang mengembalikan boolean (atau Anda memberikan nilai ke variabel boolean), Anda [biasanya] tidak dapat mengembalikan / menetapkan nilai boolean-y; itu haruslah boolean yang sangat diketik. Ini berarti, jika iff myObjectsangat diketik , return !myObject;berfungsi untuk fungsi mengembalikan boolean, tetapi return myObject;tidak. Anda harus return !!myObjectmencocokkan ekspektasi Typcript.

Pengecualian untuk naskah? Jika myObjectadalah any, Anda kembali ke Wild West JavaScript dan dapat mengembalikannya tanpa !!, bahkan jika jenis pengembalian Anda adalah boolean.

Perlu diingat bahwa ini adalah konvensi JSX & Typcript , bukan yang melekat pada JavaScript .

Tetapi jika Anda melihat aneh 0di JSX Anda, pikirkan manajemen yang salah.

ruffin
sumber
Penjelasan yang bagus. Jadi, apakah Anda akan mengatakan !! tidak sepenuhnya diperlukan dalam contoh deteksi fitur Pekerja ini ? if (!!window.Worker)
jk7
2
Tidak, kamu tidak akan membutuhkannya. Kebenaran dan true"eksternal" beroperasi persis sama dalam if. Saya terus berusaha, tetapi saya tidak bisa memikirkan alasan untuk lebih memilih menuangkan kebenaran ke nilai boolean di luar jenis kasus "bandingkan kebenaran" yang berbelit-belit di atas, kecuali untuk keterbacaan jika Anda menggunakan kembali nilainya nanti, seperti dalam qcontoh perpustakaan . Tetapi meskipun begitu, ini adalah jalan pintas yang hilang informasi, dan saya berpendapat Anda lebih baik mengevaluasi kebenaran setiap saat.
ruffin
Bereaksi adalah alasan utama kami mulai menggunakan !! pola, tetapi itu terjadi menjadi hal yang sangat nyaman dan berulang. Saya hanya perlu khawatir tentang kebenaran atau kepalsuan sesuatu, bukan tipe yang mendasarinya.
Downvotes tanpa komentar membuatnya sulit untuk mengatasi masalah Anda! Beri tahu saya apa yang terlihat buruk, dan saya akan senang mengatasinya.
ruffin
55

Ini hanya operator TIDAK logis, dua kali - digunakan untuk mengubah sesuatu menjadi boolean, misalnya:

true === !!10

false === !!0
Greg
sumber
3
Mengapa kamu mau melakukan itu? Menggunakan ! operator untuk mengkonversi ke boolean kemudian gunakan === untuk membandingkan tipe? Terima saja, Anda tidak memiliki tipe keselamatan dan lakukan val> 0 atau sesuatu.
Darren Clark
43
@ Darren: Dia tidak membandingkan tipe; dia memberi tahu Anda apa hasilnya, dengan menuliskan pernyataan dalam jawabannya.
Lightness Races in Orbit
32

Itu mengkonversi akhiran ke nilai Boolean.

Paul McMillan
sumber
26

Ini notoperasi ganda . Yang pertama !mengkonversi nilai menjadi boolean dan membalikkan nilai logisnya. Yang kedua !membalikkan nilai logis kembali.

Bill the Lizard
sumber
26

Tampaknya !!hasil operator dalam negasi ganda.

var foo = "Hello World!";

!foo // Result: false
!!foo // Result: true
Steve Harrison
sumber
23

Ini mensimulasikan perilaku Boolean()fungsi casting. Yang pertama NOTmengembalikan nilai Boolean tidak peduli apa operan yang diberikan. Yang kedua NOTmeniadakan Booleannilai itu dan memberikan nilai trueBoolean dari suatu variabel. Hasil akhirnya sama dengan menggunakan Boolean()fungsi pada suatu nilai.

Prakash
sumber
20

! adalah "boolean not", yang pada dasarnya typecasts nilai "enable" ke boolean kebalikannya. Kedua ! membalik nilai ini. Jadi, !!enableberarti "tidak tidak memungkinkan," memberi Anda nilai enablesebagai boolean.

Annika Backstrom
sumber
18

Saya pikir layak disebutkan adalah, bahwa suatu kondisi yang dikombinasikan dengan logika DAN / ATAU tidak akan mengembalikan nilai boolean tetapi keberhasilan terakhir atau kegagalan pertama dalam kasus && dan keberhasilan pertama atau kegagalan terakhir dalam kasus || rantai kondisi.

res = (1 && 2); // res is 2
res = (true && alert) // res is function alert()
res = ('foo' || alert) // res is 'foo'

Untuk melemparkan kondisi ke literal boolean sejati kita dapat menggunakan negasi ganda:

res = !!(1 && 2); // res is true
res = !!(true && alert) // res is true
res = !!('foo' || alert) // res is true
GreQ
sumber
17

!!menggunakan NOToperasi dua kali bersama-sama, !mengonversi nilai menjadi booleandan membalikkannya, berikut adalah contoh sederhana untuk melihat cara !!kerjanya:

Pada awalnya, tempat yang Anda miliki:

var zero = 0;

Kemudian Anda lakukan !0, itu akan dikonversi ke boolean dan dievaluasi ke true, karena 0 adalah falsy, sehingga Anda mendapatkan nilai yang dibalik dan dikonversi ke boolean, sehingga akan dievaluasi true.

!zero; //true

tetapi kami tidak ingin versi boolean yang terbalik dari nilai, jadi kami dapat membalikkannya lagi untuk mendapatkan hasil kami! Itu sebabnya kami menggunakan yang lain! .

Pada dasarnya, !!pastikan kami, nilai yang kami dapatkan adalah boolean, bukan falsy, truthy atau string dll ...

Jadi itu seperti menggunakan Booleanfungsi dalam javascript, tetapi cara mudah dan lebih pendek untuk mengkonversi nilai menjadi boolean:

var zero = 0;
!!zero; //false
Alireza
sumber
15

Itu !! membangun adalah cara sederhana untuk mengubah setiap ekspresi JavaScript ke setara Boolean nya.

Misalnya: !!"he shot me down" === truedan !!0 === false.

Navin Rauniyar
sumber
2
Sangat dekat dengan perbedaan penting. Kuncinya adalah itu 0 === falsesalah dan !!0 === falsebenar.
ruffin
14

Itu bukan operator tunggal, itu dua. Ini setara dengan yang berikut dan merupakan cara cepat untuk memberikan nilai ke boolean.

val.enabled = !(!enable);
Justin Johnson
sumber
10

Saya menduga ini adalah sisa dari C ++ di mana orang menimpa! operator tetapi bukan operator bool.

Jadi untuk mendapatkan jawaban negatif (atau positif) dalam hal ini Anda harus terlebih dahulu menggunakan! operator untuk mendapatkan boolean, tetapi jika Anda ingin memeriksa kasus positif akan digunakan !!.

Darren Clark
sumber
10

The ifdan whilepernyataan dan ?Operator nilai-nilai penggunaan kebenaran untuk menentukan cabang kode untuk dijalankan. Misalnya, angka nol dan NaN dan string kosong salah, tetapi angka dan string lainnya benar. Objek benar, tetapi nilai yang tidak ditentukan dan nullkeduanya salah.

Operator negasi ganda !!menghitung nilai kebenaran suatu nilai. Ini sebenarnya dua operator, di mana !!xberarti !(!x), dan berperilaku sebagai berikut:

  • Jika xadalah nilai palsu, !xadalah true, dan !!xmerupakanfalse .
  • Jika xadalah nilai sejati, !xadalah false, dan !!xsedang true.

Ketika digunakan pada tingkat atas konteks Boolean ( if, while, atau ?), yang !!operator adalah perilaku no-op. Misalnya, if (x)dan if (!!x)berarti hal yang sama.

Penggunaan praktis

Namun memiliki beberapa kegunaan praktis.

Salah satu penggunaannya adalah dengan kompres objek ke nilai kebenarannya hilang, sehingga kode Anda tidak memegang referensi ke objek besar dan menjaganya tetap hidup. Menetapkan !!some_big_objectke variabel sebagai ganti some_big_objectmelepaskannya untuk pengumpul sampah. Ini berguna untuk kasus yang menghasilkan objek atau nilai salah seperti nullatau nilai yang tidak ditentukan, seperti deteksi fitur browser.

Penggunaan lain, yang saya sebutkan dalam jawaban tentang !!operator yang sesuai C , adalah dengan alat "lint" yang mencari kesalahan ketik umum dan diagnosa cetak. Misalnya, dalam C dan JavaScript, beberapa kesalahan ketik umum untuk operasi Boolean menghasilkan perilaku lain yang outputnya tidak sebesar Boolean:

  • if (a = b)apakah penugasan diikuti dengan penggunaan nilai kebenaran b; if (a == b)adalah perbandingan kesetaraan.
  • if (a & b)adalah bitwise AND; if (a && b)adalah AND logis. 2 & 5adalah 0(nilai salah); 2 && 5adalah benar.

The !!Operator meyakinkan alat serat bahwa apa yang Anda tulis adalah apa yang Anda maksud: jangan operasi ini, kemudian mengambil nilai kebenaran hasilnya.

Penggunaan ketiga adalah untuk menghasilkan XOR logis dan XNOR logis. Baik dalam C dan JavaScript, a && bmelakukan AND logis (benar jika kedua belah pihak benar), dan a & bmelakukan AND AND. a || bmelakukan OR logis (benar jika setidaknya ada yang benar), dan a | bmelakukan bitwise OR. Ada XOR bitwise (eksklusif ATAU) sebagai a ^ b, tetapi tidak ada operator built-in untuk XOR logis (benar jika tepat satu sisi benar). Anda mungkin, misalnya, ingin mengizinkan pengguna untuk memasukkan teks di salah satu dari dua bidang. Apa yang dapat Anda lakukan adalah mengkonversi masing-masing untuk nilai kebenaran dan membandingkan mereka: !!x !== !!y.

Damian Yerrick
sumber
8

Negasi boolean ganda. Sering digunakan untuk memeriksa apakah nilai tidak ditentukan.

Sergey Ilinsky
sumber
8

Banyak jawaban bagus di sini, tetapi jika Anda sudah membaca sampai sejauh ini, ini membantu saya untuk 'mendapatkannya'. Buka konsol di Chrome (dll), dan mulai mengetik:

!(!(1))
!(!(0))
!(!('truthy')) 
!(!(null))
!(!(''))
!(!(undefined))
!(!(new Object())
!(!({}))
woo = 'hoo'
!(!(woo))
...etc, etc, until the light goes on ;)

Tentu saja, semua ini sama dengan hanya mengetik !! someThing, tetapi tanda kurung tambahan mungkin membantu membuatnya lebih dimengerti.

Warren Davis
sumber
8

!!x adalah singkatan Boolean(x)

Ledakan pertama memaksa mesin js untuk berjalan Boolean(x)tetapi juga memiliki efek samping pembalik nilai. Jadi ledakan kedua membatalkan efek samping.

Greg Gum
sumber
8

Ini memaksa semua hal menjadi boolean.

Sebagai contoh:

console.log(undefined); // -> undefined
console.log(!undefined); // -> true
console.log(!!undefined); // -> false

console.log('abc'); // -> abc
console.log(!'abc'); // -> false
console.log(!!'abc'); // -> true

console.log(0 === false); // -> undefined
console.log(!0 === false); // -> false
console.log(!!0 === false); // -> true
Khuong
sumber
7

Pertanyaan ini telah dijawab dengan cukup teliti, tetapi saya ingin menambahkan jawaban yang saya harap sesederhana mungkin, menjadikan artinya !! sesederhana untuk dipahami.

Karena javascript memiliki apa yang disebut nilai "benar" dan "falsey", ada ungkapan bahwa ketika dievaluasi dalam ekspresi lain akan menghasilkan kondisi benar atau salah, meskipun nilai atau ekspresi yang diperiksa tidak benar true- benar atau false.

Contohnya:

if (document.getElementById('myElement')) {
    // code block
}

Jika elemen itu benar-benar ada, ekspresi akan dievaluasi sebagai benar, dan blok kode akan dieksekusi.

Namun:

if (document.getElementById('myElement') == true) {
    // code block
}

... TIDAK akan menghasilkan kondisi yang benar, dan blok kode tidak akan dieksekusi, bahkan jika elemen itu ada.

Mengapa? Karena document.getElementById()merupakan ungkapan "benar" yang akan dievaluasi sebagai benar dalam if()pernyataan ini , tetapi itu bukan nilai boolean aktual dari true.

Ganda "tidak" dalam hal ini cukup sederhana. Ini hanya dua nots kembali ke belakang.

Yang pertama hanya "membalikkan" nilai truey atau falsey, menghasilkan tipe boolean yang sebenarnya, dan kemudian yang kedua "membalikkan" kembali ke keadaan semula, tetapi sekarang dalam nilai boolean yang sebenarnya. Dengan begitu Anda memiliki konsistensi:

if (!!document.getElementById('myElement')) {}

dan

if (!!document.getElementById('myElement') == true) {}

akan KEDUA mengembalikan true, seperti yang diharapkan.

Kirby L. Wallace
sumber
7

Saya hanya ingin menambahkan itu

if(variableThing){
  // do something
}

sama dengan

if(!!variableThing){
  // do something
}

Tapi ini bisa menjadi masalah ketika sesuatu tidak terdefinisi.

// a === undefined, b is an empty object (eg. b.asdf === undefined)
var a, b = {};

// Both of these give error a.foo is not defined etc.
// you'd see the same behavior for !!a.foo and !!b.foo.bar

a.foo 
b.foo.bar

// This works -- these return undefined

a && a.foo
b.foo && b.foo.bar
b && b.foo && b.foo.bar

Kuncinya di sini adalah rantai &&s akan mengembalikan nilai falsey pertama yang ditemukannya - dan ini dapat diumpankan ke pernyataan if, dll. Jadi, jika b.foo tidak terdefinisi, ia akan kembali tidak terdefinisi dan melewati b.foo.barpernyataan, dan kami tidak mendapatkan kesalahan.

Return di atas tidak terdefinisi tetapi jika Anda memiliki string kosong, false, null, 0, undefined nilai-nilai itu akan kembali dan segera setelah kami menjumpai mereka dalam rantai - []dan {}keduanya "benar" dan kami akan melanjutkan apa yang disebut " && rantai "ke nilai berikutnya di sebelah kanan.

PS Cara lain untuk melakukan hal yang sama adalah (b || {}).foo, karena jika b tidak didefinisikan maka b || {}akan menjadi {}, dan Anda akan mengakses nilai dalam objek kosong (tidak ada kesalahan) alih-alih mencoba mengakses nilai dalam "undefined" (menyebabkan kesalahan ). Jadi, (b || {}).foosama dengan b && b.foodan ((b || {}).foo || {}).barsama dengan b && b.foo && b.foo.bar.

Ryan Taylor
sumber
poin bagus - mengubah jawaban saya. Itu hanya terjadi pada objek ketika bersarang tiga level, karena seperti yang Anda katakan ({}).anythingakan memberiundefined
Ryan Taylor
5

Setelah melihat semua jawaban hebat ini, saya ingin menambahkan alasan lain untuk menggunakan !!. Saat ini saya sedang bekerja dalam Angular 2-4 (TypeScript) dan saya ingin mengembalikan boolean seperti falseketika pengguna saya tidak diautentikasi. Jika dia tidak diautentikasi, token-string akan menjadi nullatau "". Saya bisa melakukan ini dengan menggunakan blok kode berikut:

public isAuthenticated(): boolean {
   return !!this.getToken();
}
Wouter Vanherck
sumber
4

di sini adalah sepotong kode dari js sudut

var requestAnimationFrame = $window.requestAnimationFrame ||
                                $window.webkitRequestAnimationFrame ||
                                $window.mozRequestAnimationFrame;

 var rafSupported = !!requestAnimationFrame;

niat mereka adalah untuk mengatur rafDidukung ke true atau false berdasarkan ketersediaan fungsi dalam requestAnimationFrame

itu dapat dicapai dengan memeriksa secara umum sebagai berikut:

if(typeof  requestAnimationFrame === 'function')
rafSupported =true;
else
rafSupported =false;

cara singkat bisa menggunakan !!

rafSupported = !!requestAnimationFrame ;

jadi jika requestAnimationFrame diberi fungsi maka! requestAnimationFrame akan salah dan satu lagi! itu akan benar

jika requestAnimationFrame dianggap tidak terdefinisi maka! requestAnimationFrame akan benar dan satu lagi! itu akan salah

JeevanReddy Avanaganti
sumber
3

Beberapa operator dalam JavaScript melakukan konversi tipe implisit, dan terkadang digunakan untuk konversi tipe.

!Operator unary mengubah operan menjadi boolean dan meniadakannya.

Fakta ini mengarah pada idiom berikut yang dapat Anda lihat di kode sumber Anda:

!!x // Same as Boolean(x). Note double exclamation mark
GibboK
sumber
3

Gunakan logika bukan operator dua kali
artinya! True = false
dan !! true = true

Abhay Dixit
sumber
3

Mengembalikan nilai boolean suatu variabel.

Sebaliknya, Booleankelas bisa digunakan.

(baca deskripsi kode)

var X = "test"; // X value is "test" as a String value
var booleanX = !!X // booleanX is `true` as a Boolean value beacuse non-empty strings evaluates as `true` in boolean
var whatIsXValueInBoolean = Boolean(X) // whatIsXValueInBoolean is `true` again
console.log(Boolean(X) === !!X) // writes `true`

Yaitu, Boolean(X) = !!Xsedang digunakan.

Silakan periksa cuplikan kode di bawah ini

let a = 0
console.log("a: ", a) // writes a value in its kind
console.log("!a: ", !a) // writes '0 is NOT true in boolean' value as boolean - So that's true.In boolean 0 means false and 1 means true.
console.log("!!a: ", !!a) // writes 0 value in boolean. 0 means false.
console.log("Boolean(a): ", Boolean(a)) // equals to `!!a`
console.log("\n") // newline

a = 1
console.log("a: ", a)
console.log("!a: ", !a)
console.log("!!a: ", !!a) // writes 1 value in boolean
console.log("\n") // newline

a = ""
console.log("a: ", a)
console.log("!a: ", !a) // writes '"" is NOT true in boolean' value as boolean - So that's true.In boolean empty strings, null and undefined values mean false and if there is a string it means true.
console.log("!!a: ", !!a) // writes "" value in boolean
console.log("\n") // newline

a = "test"
console.log("a: ", a) // writes a value in its kind
console.log("!a: ", !a)
console.log("!!a: ", !!a) // writes "test" value in boolean

console.log("Boolean(a) === !!a: ", Boolean(a) === !!a) // writes true

efkan
sumber