Apakah JavaScript memiliki evaluasi "sirkuit pendek"?

101

Saya ingin tahu apakah JavaScript memiliki evaluasi "sirkuit pendek" seperti && Operator di C #. Jika tidak, saya ingin tahu apakah ada solusi yang masuk akal untuk diterapkan.

GibboK
sumber
2
Sama-sama. Saya telah menambahkan https://www.google.com/search?q=site:stackoverflow.com+%ssebagai pintasan pencarian (Chrome / Firefox) untuk mempercepat pencarian.
Rob W
Juga di sini jawaban untuk pertanyaan saya developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
GibboK
Sumber daya berguna lainnya: || pertanyaan evaluasi Pertanyaan evaluasi &&
Samuel Hulla

Jawaban:

118

Ya, JavaScript memiliki evaluasi "sirkuit pendek".

if (true == true || foo.foo){
    // Passes, no errors because foo isn't defined.
}

DEMO langsung

if (false && foo.foo){
    // Passes, no errors because foo isn't defined.
}

DEMO langsung

gdoron mendukung Monica
sumber
8
Jadi korsleting itu adalah standar di JS?
GibboK
1
Terima kasih gdoron, tolong bantu saya untuk memahami ... di C # Saya juga memiliki operator biner seperti & jadi kedua operan harus benar untuk lulus, alih-alih dengan && di C
GibboK
1
@Tokopedia Maka, jelas, tidak mungkin ada Short-circuitdengan operator logika itu. Coba saja sendiri. Gunakan demo saya.
gdoron mendukung Monica
2
@ GibboK: Lihat referensi operator ini . Dan ya, ada operator AND biner di JS juga.
Bergi
5
@Tokopedia YA dalam standar! Tapi komentar yang bagus, seperti pada saat JIT-compiling-magic dalam implementasi javascript, seseorang benar-benar ingin tahu apakah ada sesuatu yang "standar", atau berpotensi tunduk pada implementasi. Cara pernyataan kondisi dengan Binary Operator Logical dievaluasi dan (short-curcuit) adalah perilaku standar ecma-international.org/ecma-262/5.1/#sec-11.11
humanityANDpeace
24

Jawaban ini sangat rinci tentang caranya berfungsi dalam JavaScript, dengan semua gotcha dan juga tema yang relevan seperti prioritas operator, jika Anda mencari definisi cepat dan sudah memahami cara kerja korsleting, saya sarankan untuk memeriksa jawaban lain.


Apa yang kami (pikir kami) ketahui sejauh ini:

Pertama mari kita periksa perilaku yang kita semua kenal, di dalam if()blok, tempat kita gunakan &&untuk memeriksa apakah dua hal itu true:

if (true && true) {
   console.log('bar');
} 

Sekarang, naluri pertama Anda mungkin mengatakan: 'Ah ya, cukup sederhana, kode menjalankan pernyataan jika keduanya expr1dan expr2dievaluasi sebagai true'

Ya dan tidak. Anda secara teknis benar, itu adalah perilaku yang Anda jelaskan, tetapi itu bukanlah cara yang tepat untuk mengevaluasi kode dan kami perlu mempelajari lebih dalam untuk memahami sepenuhnya.


Bagaimana tepatnya &&dan ||ditafsirkan ?:

Saatnya untuk melihat "di bawah tenda mesin ". Mari pertimbangkan contoh praktis ini:

function sanitise(x) {
  if (isNaN(x)) {
    return NaN;
  }
  return x;
}

let userinput = 0xFF; // as an example
const res = sanitise(userinput) && userinput + 5

console.log(res);

Nah hasilnya 260.. tapi kenapa? Untuk mendapatkan jawabannya, kita perlu memahami cara kerja evaluasi hubung singkat.

Menurut Definisi MDN , &&operator expr1 && expr2dijalankan sebagai berikut:

Jika expr1dapat diubah menjadi true, kembali expr2; lain, kembali expr1.

Jadi ini berarti, dalam contoh praktis kita, const resdievaluasi dengan cara berikut:

  1. Memanggil expr1-sanitise(0xFF)
  2. 0xFF adalah bilangan heksadesimal yang valid untuk 250, jika tidak, saya akan kembali NaN
  3. The expr1kembali sebuah "truthy" nilai, waktu untuk mengeksekusi expr2 (jika tidak saya akan berhenti sebagai NaNadalah falsy)
  4. Sejak userinputadalah truthy (nomor), saya dapat menambahkan +5untuk itu
  • "Truthy" berarti ekspresi tersebut dapat dievaluasi sebagai benar. Berikut adalah daftar truthy dan falsy ekspresi.

Jadi di sini, kami dapat menghindari ifpemblokiran tambahan dan isNaNpemeriksaan lebih lanjut dengan penggunaan &&operator yang sederhana.


Bagaimana cara kerjanya:

Sekarang, setidaknya kita harus memiliki gambaran bagaimana operator bekerja. Aturan universal berjalan:

  • (some falsy expression) && expr akan dievaluasi menjadi ekspresi yang salah
  • (some truthy expression) || expr akan mengevaluasi ekspresi kebenaran

Berikut beberapa contoh lebih lanjut untuk pemahaman yang lebih baik:

function a() { console.log('a'); return false; }
function b() { console.log('b'); return true; }

if ( a() && b() ){
     console.log('foobar'); 
}

//Evaluates a() as false, stops execution.

function a() { console.log('a'); return false; }
function b() { console.log('b'); return true; }

if ( a() || b() ){
     console.log('foobar'); 
}

/* 1. Evaluates a() as false
   2. So it should execute expr2, which is `b()`
   3. b() returned as true, executing statement `console.log('foobar');`
*/


Satu hal terakhir yang mengganggu, tetapi sangat penting [Operator Precedence]:

Bagus, semoga Anda menguasainya! Hal terakhir yang perlu kita ketahui adalah aturan tentang prioritas operator, yaitu:

  • The &&operator selalu dilaksanakan sebelum ||operator.

Perhatikan contoh berikut:

function a() { console.log('a'); return true;}
function b() { console.log('b'); return false;}
function c() { console.log('c'); return false;}

console.log(a() || b() && c());

// returns a() and stops execution

Ini akan kembali sebagai, mungkin membingungkan bagi beberapa orang sebagai a(). Alasannya cukup sederhana, hanya penglihatan kita yang menipu kita, karena kita terbiasa membaca kiri-ke-kanan. Mari kita ambil console.log()dan apa yang tidak keluar dan fokus murni pada evaluasi

true || false && false

Sekarang untuk membungkus kepala Anda di sekitar ini:

  1. Kami mengatakan &&operator itu diutamakan, jadi dievaluasi sebagai yang pertama. Untuk membantu kami membayangkan evaluasi dengan lebih baik, pikirkan definisinya

    expr1 && expr2

    Dimana:

    • expr2 adalah false
    • expr1 adalah true || false
  2. Jadi itu bagian yang sulit, sekarang true || falsedievaluasi ( expr1- sisi kiri &&).

    • Mengingat ||Operator berhenti eksekusi jika expr1 || expr2di expr1mengevaluasi sebagai truthy, yang expr1dijalankan dan eksekusi kode berhenti.
  3. Nilai yang dikembalikan adalah true

Yah .. itu cukup rumit, semua karena sedikit aturan dan semantik yang aneh. Tapi ingat, Anda selalu dapat menghindari prioritas operator dengan ()- seperti dalam matematika

function a() { console.log('a'); return true;}
function b() { console.log('b'); return false;}
function c() { console.log('c'); return false;}

console.log((a() || b()) && c());

/* 1. The () escape && operator precedence
   2. a() is evaluated as false, so expr2 (c()) to be executed
   3. c()  
*/

Samuel Hulla
sumber
Saya tidak akan 1) menggunakan kata "compiler". "mesin" lebih akurat. 2) Tidak membicarakan expr1dan expr2 atau condition1atau apapun, itu hanya membingungkan. Tentukan salah satunya, Anda juga bisa memasukkan variabel lokal, misalnya. const expr1 = true; if(expr1 && ...)
Jonas Wilms
@JonasWilms thanks atas masukannya, dirubah jawabannya sesuai.
Samuel Hulla
1
Ini masih tidak langsung menjawab pertanyaan yang diajukan.
Kevin B
7
Ini adalah "jawaban hebat yang tidak secara eksplisit menjawab pertanyaan" terbaik yang pernah saya lihat ...
Gerardo Furtado
1
Ini adalah jawaban yang benar dengan penjelasan yang mendalam, harus ditandai sebagai diterima dan diberi suara lebih tinggi daripada saat ini!
Alexander Kim