Pertanyaan Apakah yang !! (bukan bukan) operator di JavaScript?


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

Konteks di mana saya melihat ini,

this.vertical = vertical !== undefined ? !!vertical : this.vertical;

2316
2018-04-24 08:13


asal


Jawaban:


Coerces oObject ke boolean. Jika itu falsey (mis. 0, null, undefined, dll.), itu akan terjadi false, jika tidak, true.

!oObject  //Inverted boolean
!!oObject //Non inverted boolean so true boolean representation

Begitu !! bukan operator, hanya saja ! operator dua kali.

Contoh Dunia Nyata "Uji versi IE":

let isIE8 = false;  
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 null  

tetapi jika Anda ⇒

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

2068
2018-04-24 08:18



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

! aku s TIDAK. Begitu !true aku s false, dan !false aku s true. !0 aku s true, dan !1 aku s false.

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

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

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

// And finally, much easier to understand:
val.enabled = (userId != 0);

729
2017-09-10 17:28



!!expr mengembalikan nilai Boolean (true atau false) tergantung pada kebenaran dari ekspresi itu. Lebih masuk akal bila digunakan pada jenis non-boolean. Pertimbangkan contoh-contoh ini, terutama contoh ke-3 dan seterusnya:

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

372
2018-05-15 09:06



Seduh teh:

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


Dalam teori:

! menentukan "kebenaran" dari nilai apa yang tidak:

  • Yang benar adalah itu false tidak true (itulah sebabnya !false hasil di true)

  • Yang benar adalah itu true tidak false (itulah sebabnya !true hasil di false)


!! menentukan "kebenaran" dari nilai apa itu tidak tidak:

  • Yang benar adalah itu true tidak tidak  true (itulah sebabnya !!true hasil dalam true)

  • Yang benar adalah itu false tidak tidak  false (itulah sebabnya !!false hasil dalam false)


Apa yang kami ingin tentukan dalam perbandingan adalah "kebenaran" tentang nilai referensi, bukan Nilai dari 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 tipikal boolean.


Dalam praktek:

Pertimbangkan fungsi ringkas yang mendeteksi fungsi fitur (dan dalam hal ini, kompatibilitas platform) dengan cara pengetikan dinamis (alias "bebek mengetik"). Kami ingin menulis fungsi yang mengembalikan true jika browser pengguna mendukung HTML5 <audio> elemen, tetapi kami tidak ingin fungsi untuk membuang kesalahan jika <audio> tidak terdefinisi; dan kami tidak ingin menggunakannya try ... catch untuk menangani segala kemungkinan kesalahan (karena mereka kotor); dan juga kami tidak ingin menggunakan pemeriksaan di dalam fungsi yang tidak akan secara konsisten mengungkapkan kebenaran tentang fitur tersebut (misalnya, document.createElement('audio') akan tetap membuat elemen bernama <audio> bahkan jika HTML5 <audio> tidak didukung).


Berikut adalah 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 sebuah attribute untuk mencari, tetapi mereka masing-masing mengembalikan nilai yang berbeda berdasarkan apa yang ditentukan oleh perbandingan.

Tapi tunggu, masih ada lagi!

Beberapa dari Anda mungkin memperhatikan bahwa dalam contoh spesifik ini, seseorang dapat dengan mudah memeriksa properti menggunakan sedikit lebih berkinerja berarti memeriksa apakah objek tersebut punya sebuah 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 yang paling disukai untuk mendapatkan true dari nilai non-boolean, mungkin tidak terdefinisi memang dengan menggunakan !!. Semoga ini sangat tidak jelas.


128
2018-02-22 23:45



!! mengkonversi nilai ke kanan ke nilai boolean yang setara. (Pikirkan cara orang miskin "casting-jenis"). Nya maksud biasanya untuk menyampaikan kepada pembaca bahwa kode tidak peduli apa nilai dalam variabel, tetapi apa itu nilai "kebenaran" aku s.


87
2017-09-10 17:26



!!foo menerapkan unary bukan operator dua kali dan digunakan untuk mentransmisikan ke tipe boolean yang serupa dengan penggunaan unary plus +foo untuk mentransmisikan ke nomor dan menggabungkan string kosong ''+foo untuk mentransmisikan ke string.

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

Boolean(foo) === !!foo
Number(foo)  === +foo
String(foo)  === ''+foo

59
2017-09-10 21:15



Begitu banyak jawaban yang melakukan separuh pekerjaan. Iya nih, !!X bisa dibaca sebagai "kebenaran X [direpresentasikan sebagai boolean]". Tapi !! tidak, secara praktis, sangat penting untuk mencari tahu apakah satu variabel (atau bahkan jika banyak variabel) benar atau salah. !!myVar === true sama saja myVar. Perbandingan !!X ke boolean "nyata" tidak benar-benar berguna.

Apa yang Anda dapatkan dengan !! adalah kemampuan untuk memeriksa kebenaran dari beberapa variabel melawan satu sama lain dengan cara yang dapat diulang, standar (dan JSLint ramah).

Cukup casting :(

Itu adalah...

  • 0 === false aku s false.
  • !!0 === false aku s true.

Hal di atas tidak begitu bermanfaat. if (!0) memberi Anda hasil yang sama dengan if (!!0 === false). Saya tidak bisa memikirkan kasus yang bagus untuk mentransmisikan variabel ke boolean dan kemudian membandingkannya dengan boolean "benar".

Lihat "== dan! =" Dari Petunjuk JSLint (Catatan: Crockford sedang memindahkan situsnya sedikit; tautan itu mungkin mati pada titik tertentu) untuk sedikit alasan mengapa:

Operator == dan! = Melakukan pemaksaan jenis sebelum membandingkan. Ini buruk karena menyebabkan '\ t \ r \ n' == 0 untuk menjadi kenyataan. Ini dapat menutupi kesalahan jenis. JSLint tidak dapat diandalkan menentukan apakah == sedang digunakan dengan benar, jadi yang terbaik adalah tidak menggunakan == dan! = Sama sekali dan untuk selalu menggunakan operator === dan! == yang lebih dapat diandalkan.

Jika Anda hanya peduli bahwa 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 yang tidak intuitif di mana boolean akan dilemparkan ke angka (true dilemparkan ke 1 dan false untuk 0) saat membandingkan boolean ke angka. Pada kasus ini, !! mungkin bermanfaat secara mental. Padahal, sekali lagi, ini adalah kasus di mana Anda membandingkan non-boolean ke boolean yang sulit diketik, yang, imo, kesalahan serius.  if (-1) masih cara untuk pergi di 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 lebih gila lagi tergantung pada mesin Anda. WScript, misalnya, memenangkan hadiah.

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

Karena beberapa jeli Windows historis, itu akan menghasilkan -1 dalam kotak pesan! Cobalah di prompt cmd.exe dan lihat! Tapi WScript.echo(-1 == test()) masih memberi Anda 0, atau WScript false. Mengalihkan pandangan. Itu mengerikan.

Membandingkan kejujuran :)

Tetapi bagaimana jika saya memiliki dua nilai yang saya perlukan untuk memeriksa truthi / falsi-ness yang sama?

Berpura-pura kita punya myVar1 = 0; dan myVar2 = undefined;.

  • myVar1 === myVar2 aku s 0 === undefined dan jelas salah.
  • !!myVar1 === !!myVar2 aku s !!0 === !!undefined dan itu benar! Kebenaran yang sama! (Dalam hal ini, keduanya "memiliki kebenaran tentang kepalsuan".)

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 sama kebenaran, bukan? Itu adalah, menggunakan !! jika Anda perlu melihat apakah dua vars berada keduanya benar atau keduanya falsy (atau tidak), artinya, sama (atau tidak) kebenaran.

Saya tidak bisa memikirkan kasus penggunaan besar yang tidak dibikin untuk itu begitu saja. Mungkin Anda memiliki kolom "tertaut" 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 yang salah untuk nama dan usia pasangan, Anda dapat melanjutkan. Jika tidak, Anda hanya memiliki satu bidang dengan nilai (atau pernikahan yang diatur sangat dini) dan perlu membuat kesalahan ekstra pada Anda errorObjects koleksi.


EDIT 24 Okt 2017: 

Perpustakaan pihak ke-3 yang mengharapkan nilai Boolean eksplisit

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

Contohnya, Salah dalam JSX (React) memiliki arti khusus itu tidak dipicu pada kepalsuan sederhana. Jika Anda mencoba mengembalikan sesuatu seperti berikut di JSX Anda, mengharapkan int di messageCount...

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

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

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

  • Dokumen JSX menyarankan Anda untuk lebih eksplisit, tulis kode komentar otomatis, dan gunakan perbandingan untuk memaksa ke Boolean.
    {messageCount > 0 && <div>You have messages!</div>}

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

Ingat itu ini adalah konvensi BEJ, tidak ada yang melekat pada JavaScript.

Tetapi jika Anda melihat aneh 0s dalam JSX yang Anda berikan, pikirkan manajemen palsu yang palsu.


45
2018-04-29 18:14



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

true === !!10

false === !!0

44
2018-04-24 08:18



Ini mengubah akhiran menjadi nilai Boolean.


28
2017-09-10 17:27



Ini ganda not operasi. Pertama ! mengkonversi nilai ke boolean dan membalikkan nilai logisnya. Kedua ! membalikkan nilai logis kembali.


21
2017-09-10 17:28



Ini mensimulasikan perilaku Boolean() fungsi pengecoran. Pertama NOT mengembalikan nilai Boolean tidak peduli operan apa yang diberikan. Kedua NOT meniadakan itu Boolean nilai dan memberi trueNilai Boolean suatu variabel. Hasil akhirnya sama dengan menggunakan Boolean() berfungsi pada suatu nilai.


21
2018-03-23 11:53