Apakah pernyataan if javascript dengan beberapa kondisi menguji semuanya?

100

Dalam javascript, ketika menggunakan pernyataan if dengan beberapa kondisi untuk diuji, apakah javascript menguji semuanya, atau apakah jaminan sebelum menguji semuanya jika sudah salah?

Sebagai contoh:

 a = 1
 b = 2
 c = 1

 if (a==1 && b==1 && c==1)

Akankah javascript menguji semua 3 kondisi tersebut atau, setelah melihat bahwa b tidak sama dengan 1, dan oleh karena itu salah, akankah itu keluar dari pernyataan?

Saya bertanya dari sudut pandang kinerja. Jika, misalnya, saya menguji 3 selektor jQuery kompleks, saya lebih suka jQuery tidak melintasi DOM 3 kali jika sudah jelas melalui yang pertama bahwa itu akan mengembalikan FALSE. (Dalam hal ini akan lebih masuk akal untuk menyarangkan 3 pernyataan if).

TAMBAHAN: Lebih ke penasaran, istilah apa yang tepat untuk ini? Saya perhatikan bahwa banyak dari Anda menggunakan istilah 'korsleting'. Juga, apakah beberapa bahasa melakukan ini dan yang lainnya tidak?

DA.
sumber
@ Josh: Saya sangat menghargai gagasan bahwa ini adalah pengoptimalan mikro. Yang bagus untuk diketahui. Yang mengatakan jika satu opsi lebih dioptimalkan daripada yang lain, saya berasumsi ada baiknya untuk mengetahui dan membiasakan diri menggunakan metode tersebut. (Plus, yah, aku juga sangat penasaran dengan jawabannya)
DA.
21
Sebenarnya, ini bukan pengoptimalan yang prematur. Dalam bahasa dengan logika hubung singkat, penting untuk mengetahui dalam kondisi apa beberapa metode tidak akan dijalankan; jika Anda mengandalkan efek sampingnya, misalnya.
Rob
5
Berikut pertanyaan lain tentang "evaluasi hubung singkat": stackoverflow.com/questions/1232603/…
David
@Tokopedia Terima kasih! Bacaan yang menarik.
DA.

Jawaban:

151

The &&operator "sirkuit pendek" - yaitu, jika kondisi kiri adalah palsu, itu tidak mengganggu mengevaluasi yang tepat.

Begitu pula dengan ||operator korsleting jika kondisi kiri benar.

EDIT: Padahal, Anda tidak perlu khawatir tentang kinerja sampai Anda mengukur dan menentukan bahwa itu masalah. Mikro-optimasi prematur adalah kutukan dari pemeliharaan.

Segera.
sumber
1
Jawaban yang sangat baik (baik bagian teknis maupun masalah manajemen). Terima kasih!
DA.
5
Jika Anda DO ingin mengeksekusi semua bagian statmen boolean, Anda dapat menggunakan & dan | untuk dan atau mewakili
Zoidberg
25
Kondisi ini tidak selalu tentang kinerja. Kadang-kadang Anda mungkin melakukan pemeriksaan nol dan mengatakan jika pemeriksaan nol Anda adalah kondisi a dan kemudian Anda mencoba melakukan (b == nilai + 1) untuk pemeriksaan kedua Anda, Anda akan mendapatkan kesalahan jika ketiga kondisi jika kondisi diperiksa.
infocyde
4
Memang, hubungan arus pendek bukanlah tentang kinerja. Pertanyaan aslinya, bagaimanapun, adalah menanyakan dari sudut pandang kinerja.
Anon.
1
Baik sekali. Melakukan pengoptimalan mikro semacam ini (antara lain) dapat berdampak besar di dalam loop peristiwa gulir, katakanlah untuk perhitungan paralaks beberapa elemen misalnya atau bahkan bilah lengket. ambil contoh ini: if (!barSticky && bar.parent().offset().top <= document.documentElement.scrollTop)kondisi kedua adalah perhitungan yang lebih mahal, yang pertama hanya boolean. :)
antoni
13

Dari sudut pandang kinerja, ini bukan pengoptimalan mikro.

Jika kita memiliki 3 variabel Boolean, a, b, c itu adalah mikro-optimasi.

Jika kita memanggil 3 fungsi yang mengembalikan variabel Boolean, setiap fungsi mungkin membutuhkan waktu lama, dan tidak hanya penting untuk mengetahui hubung singkat ini, tetapi juga dalam urutannya. Sebagai contoh:

if (takesSeconds() && takesMinutes())

jauh lebih baik daripada

if (takesMinutes() && takesSeconds())

jika keduanya sama-sama cenderung mengembalikan false.

Brad
sumber
12

Itu sebabnya Anda bisa melakukannya dalam kode javascript seperti

var x = x || 2;

Yang berarti jika x tidak ditentukan atau sebaliknya 'salah' maka nilai defaultnya adalah 2.

azazul
sumber
3
Ini dapat bekerja bahkan jika JS tidak mendukung evaluasi sirkuit pendek.
pswg
1
Apakah ini setara dengan terner?
Mark Carpenter Jr
10

Jika seseorang bertanya-tanya apakah ada cara untuk memaksa evaluasi semua kondisi, dalam beberapa kasus operator bitwise &dan |dapat digunakan

var testOr = true | alert(""); //alert pops up
var testAnd = false & alert(""); //alert pops up

Ini harus digunakan dengan sangat hati-hati karena operator bitwise adalah operator aritmatika yang bekerja pada bit tunggal operan mereka dan tidak dapat selalu berfungsi sebagai versi "non-short-circuit" dari &&dan||

Contoh:

-2147483648 && 1 = 1 

tapi

-2147483648 & 1 = 0

Semoga dapat membantu seseorang yang tiba di sini mencari informasi seperti ini (seperti saya) dan terima kasih kepada @Max atas koreksi dan contoh tandingannya.

ivcandela.dll
sumber
1
Jawaban ini salah. & dan | adalah operator bitwise, mereka BUKAN 'versi non-short-circuit dari && dan ||'. Operator bitwise adalah operator aritmatika yang bekerja pada bit tunggal operannya. Contoh: -2147483648 && 1 = 1 tetapi -2147483648 & 1 = 0. Info lebih lanjut di sini: en.wikipedia.org/wiki/Bitwise_operation
Maks.
1
@Max sebenarnya saya tidak tahu ini, saya telah menggunakan ini (yang sekarang saya sebut "trik") sejak saya belajar C. Untungnya masukan seperti itu yang akan memecahkan kode saya tidak pernah muncul. Saya mengoreksi jawaban saya, saya berhutang budi
ivcandela
@DJDaveMark maaf saya tidak bisa mendapatkan false && (alert(""))solusi Anda untuk bekerja: /
ivcandela
@ivcandela Begitu pula saya. Jika saya tidak menggunakan ponsel, saya akan mengujinya terlebih dahulu; o) Sayang sekali Anda tidak dapat mengedit komentar. Saya baru saja menghapusnya dan menambahkan yang lain di bawah
DJDaveMark
Cara yang lebih sederhana dan lebih baik untuk memaksa evaluasi adalah dengan menyimpan hasil dalam variabel kemudian menguji variabel yaitu:var a=false; var b=check(); alert(a && b);
DJDaveMark
7

Ini hanya akan menguji semua kondisi jika yang pertama benar, ujilah sendiri:

javascript: alert (false && alert("A") && false);
albertein.dll
sumber
3

Ini korsleting - hanya a dan b yang akan dibandingkan dalam contoh Anda.

David M
sumber
3

Alasan lain mengapa menghentikan evaluasi dengan 1 atau lebih parameter di sebelah kiri.

if (response.authResponse && (response.authResponse.accessToken! = user.accessToken)) {...}

evaluasi kedua bergantung pada yang pertama benar dan tidak akan memunculkan kesalahan kompilasi jika response.authResponse adalah null atau tidak terdefinisi dll karena kondisi pertama gagal.

Bahasa lain memiliki masalah ini di masa-masa awal dan menurut saya ini adalah pendekatan standar dalam membangun kompiler sekarang.

PazoozaTest Pazman
sumber
2

Itu keluar setelah melihat bahwa b tidak sama dengan satu.

Annie
sumber
2

Bagi siapa pun yang memiliki pertanyaan ini bingung karena mereka tidak melihat perilaku hubung singkat saat menggunakan ||dalam hubungannya dengan ?operator seperti:

x = 1 || true ? 2 : 3 // value of x will be 2, rather than 1 as expected

sepertinya aturan korsleting tidak berfungsi. Mengapa mengevaluasi suku kedua dari ||(benar? 2: 3) ketika yang pertama benar? Ternyata ini adalah masalah urutan operasi karena persamaan di atas adalah

x = (1 || true) ? 2 : 3

dengan ||evaluasi pertama dan ?evaluasi kedua. Apa yang mungkin Anda inginkan adalah:

x = 1 || (true ? 2 : 3)

BrightEyed
sumber