JavaScript atau (||) penjelasan tugas variabel


351

Dengan cuplikan JavaScript ini ...

var a;
var b = null;
var c = undefined;
var d = 4;
var e = 'five';

var f = a || b || c || d || e;

alert(f); // 4

Dapatkah seseorang tolong jelaskan kepada saya apa yang disebut teknik ini (tebakan terbaik saya ada pada judul pertanyaan ini!)? Dan bagaimana / mengapa itu bekerja dengan tepat?

Pemahaman saya adalah bahwa variabel fakan diberi nilai terdekat (dari kiri ke kanan) dari variabel pertama yang memiliki nilai yang tidak nol atau tidak terdefinisi, tetapi saya belum berhasil menemukan banyak bahan referensi tentang teknik ini dan memiliki melihatnya digunakan banyak.

Juga, apakah teknik ini khusus untuk JavaScript? Saya tahu melakukan sesuatu yang serupa di PHP akan menghasilkan fmemiliki nilai boolean yang benar, bukan nilai ditu sendiri.


4
Pertanyaan lama, tapi mengenai PHP, ada konstruksi yang dapat Anda gunakan: $f=$a or $f=$b or $f=$c; // etc. PHP memiliki ||operator dan oroperator, yang melakukan pekerjaan yang sama; Namun ordievaluasi setelah penugasan sementara ||dievaluasi sebelumnya. Ini juga memberi Anda gaya bahasa Inggris$a=getSomething() or die('oops');
Manngo

1
Dalam PHP 5.3 Anda dapat meninggalkan bagian tengah dari operator ternary sehingga mendasarkan dari itu ... Anda juga dapat memotong sedikit lebih pendek menjadi sesuatu seperti ini: $f = $a ?: $b ?: $c;
Rei

1
Pada PHP 7 Anda dapat menggunakan ??ini. $a = $b ?? 'default'
Spencer Ruskin

@SpencerRuskin $aakan diberi nilai $bjika $bbenar, yang lain 'default'?
oldboy

Betul. Lihatlah bagian operator penggabungan nol pada halaman ini: php.net/manual/en/migration70.new-features.php
Spencer Ruskin

Jawaban:


212

Lihat evaluasi hubung singkat untuk penjelasannya. Ini adalah cara umum untuk menerapkan operator ini; itu tidak unik untuk JavaScript.


57
Pikirkan saja 'gotcha' yang mana yang terakhir akan selalu ditugaskan walaupun semuanya tidak terdefinisi, nol atau salah. Mengatur sesuatu yang Anda tahu tidak salah, null, atau tidak terdefinisi pada akhir rantai adalah cara yang baik untuk memberi sinyal tidak ada yang ditemukan.
Erik Reppen

Saya telah melihat teknik ini selama bertahun-tahun, tetapi yang mengejutkan saya saat itu ketika saya ingin menggunakannya adalah bahwa hasil dari ekspresi tidak dilemparkan ke boolean. Anda nanti tidak bisa melakukannya if( true == f ). Jika bilangan bulat disimpan dalam f, maka tes ini akan selalu mengembalikan false.

9
Sebenarnya, Anda bisa melakukannya if(true == f), yang sama dengan if(f): tes akan berlalu. Jika Anda ingin juga menguji jenis dari f, menggunakan perbandingan yang ketat: if(true === f), yang akan gagal memang.
Alsciende

5
Ya, evaluasi hubung singkat adalah hal biasa. Namun perbedaan di sini terletak pada cara JavaScript mengembalikan nilai terakhir yang menghentikan eksekusi. Jawaban @ Anurag lebih baik menjelaskan hal ini.
Ben.12

tidak yakin apakah itu penjelasan terbaik untuk pemula. Saya akan merekomendasikan: javascript.info/logical-operators
csguy

198

Ini dibuat untuk menetapkan nilai default , dalam hal ini nilai y, jika xvariabel falsy .

Operator boolean dalam JavaScript dapat mengembalikan operan, dan tidak selalu menghasilkan boolean seperti dalam bahasa lain.

Operator Logical OR ( ||) mengembalikan nilai operan kedua, jika yang pertama palsu, jika tidak nilai operan pertama dikembalikan.

Sebagai contoh:

"foo" || "bar"; // returns "foo"
false || "bar"; // returns "bar"

Falsy nilai-nilai adalah mereka yang memaksa untuk falseketika digunakan dalam konteks boolean, dan mereka 0, null, undefined, string kosong, NaNdan tentu saja false.


1
+1 Apakah ada operator lain seperti itu? Atau ||eksklusif.
OscarRyz

9
@Support (@ Oscar): The Logical &&operator memiliki perilaku yang sama, ia mengembalikan nilai dari operan pertama jika itu dengan sendirinya falsy dan mengembalikan nilai dari operan kedua, hanya jika yang pertama adalah truthy , misalnya ("foo" && "bar") == "bar", dan(0 && "bar") == 0
CMS

12
Falsy sebenarnya adalah istilah teknis.
ChaosPandion

8
Jadi kami belajar tentang ||, &&, "Falsy" dan "Truly" di pos ini. Jawaban terbaik dengan hadiah "tersembunyi".
Alex

4
@Alex NB: "Truthy" (! "Truly")
Bumpy

183

Javacript menggunakan evaluasi hubung singkat untuk operator logis ||dan &&. Namun, ini berbeda dengan bahasa lain karena mengembalikan hasil dari nilai terakhir yang menghentikan eksekusi, bukan nilai true, atau false.

Nilai-nilai berikut ini dianggap salah dalam JavaScript.

  • Salah
  • batal
  • "" (string kosong)
  • 0
  • Nan
  • tidak terdefinisi

Mengabaikan aturan prioritas operator , dan menjaga hal-hal sederhana, contoh-contoh berikut menunjukkan nilai mana yang menghentikan evaluasi, dan dikembalikan sebagai hasilnya.

false || null || "" || 0 || NaN || "Hello" || undefined // "Hello"

5 nilai pertama hingga NaNpalsu sehingga mereka semua dievaluasi dari kiri ke kanan, sampai memenuhi nilai kebenaran pertama - "Hello"yang membuat seluruh ekspresi benar, jadi apa pun yang lebih jauh ke atas tidak akan dievaluasi, dan "Hello"akan dikembalikan sebagai hasil dari ekspresi . Demikian pula, dalam hal ini:

1 && [] && {} && true && "World" && null && 2010 // null

5 nilai pertama semuanya benar dan dievaluasi sampai memenuhi nilai falsy pertama ( null) yang membuat ekspresi salah, jadi 2010tidak dievaluasi lagi, dan nulldikembalikan sebagai hasil dari ekspresi.

Contoh yang Anda berikan adalah memanfaatkan properti JavaScript ini untuk melakukan tugas. Ini dapat digunakan di mana saja di mana Anda perlu mendapatkan nilai true atau falsy pertama di antara seperangkat nilai. Kode ini di bawah ini akan menetapkan nilai "Hello"untuk bkarena membuat lebih mudah untuk menetapkan nilai default, bukannya melakukan jika-lain cek.

var a = false;
var b = a || "Hello";

Anda dapat menyebut contoh di bawah ini sebagai eksploitasi fitur ini, dan saya percaya ini membuat kode lebih sulit dibaca.

var messages = 0;
var newMessagesText = "You have " + messages + " messages.";
var noNewMessagesText = "Sorry, you have no new messages.";
alert((messages && newMessagesText) || noNewMessagesText);

Di dalam lansiran, kami memeriksa apakah messagesada kesalahan, dan jika ya, maka evaluasi dan kembali noNewMessagesText, jika tidak, evaluasi dan kembali newMessagesText. Karena itu salah dalam contoh ini, kami berhenti di noNewMessagesText dan memberitahukan "Sorry, you have no new messages.".


36
Ini adalah jawaban terbaik menurut pendapat saya karena penjelasan berikut:However, it's different to other languages in that it returns the result of the last value that halted the execution, instead of a true, or false value.
mastazi

1
@ Majazi Yap, harus dengan huruf tebal IMHO.
noober

6
Seharusnya jawabannya, itu menunjukkan nilai yang dipilih daripada kasus uji.
Dadan

Setuju, ini adalah jawaban favorit saya karena secara khusus membahas masalah penugasan variabel JavaScript. Selain itu, jika Anda memilih untuk menggunakan terner sebagai salah satu variabel berikutnya untuk menguji penugasan (setelah operator), Anda harus membungkus terner dalam tanda kurung agar evaluasi penugasan dapat berfungsi dengan baik.
Joey T

ini seharusnya jawaban yang diterima
Alan

49

Variabel Javascript tidak diketik, sehingga f dapat diberi nilai integer meskipun telah ditetapkan melalui operator boolean.

f diberi nilai terdekat yang tidak setara dengan false . Jadi 0, false, null, undefined, semuanya dilewati:

alert(null || undefined || false || '' || 0 || 4 || 'bar'); // alerts '4'

13
Jangan lupa ''juga sama salah dalam hal ini.
Brigand

Suara positif untuk menunjukkan hal f is assigned the NEAREST valueyang cukup penting di sini.
steviejay

3
"Terdekat" tidak sepenuhnya benar, meskipun memang memiliki penampilan seperti itu. ||Operator boolean , menjadi operator boolean memiliki dua operan: sisi kiri dan sisi kanan. Jika sisi kiri ||adalah truthy , yang resolve operasi ke sisi kiri dan sisi kanan diabaikan. Jika sisi kiri adalah kepalsuan , ia memutuskan ke sisi kanan. Jadi null || undefined || 4 || 0benar-benar memutuskan undefined || 4 || 0yang memutuskan untuk 4 || 0yang memutuskan untuk 4.
devios1

29

Tidak ada keajaiban untuk itu. Ekspresi Boolean suka a || b || c || ddievaluasi dengan malas. Interpeter mencari nilai a, itu tidak terdefinisi sehingga salah sehingga bergerak, kemudian melihat byang nol, yang masih memberikan hasil palsu sehingga bergerak, lalu melihat c- cerita yang sama. Akhirnya ia melihat ddan berkata 'huh, ini bukan nol, jadi saya mendapatkan hasil saya' dan menetapkannya ke variabel akhir.

Trik ini akan bekerja dalam semua bahasa dinamis yang melakukan evaluasi hubung singkat ekspresi boolean. Dalam bahasa statis itu tidak akan dikompilasi (ketik kesalahan). Dalam bahasa yang ingin mengevaluasi ekspresi boolean, itu akan mengembalikan nilai logis (yaitu benar dalam kasus ini)


6
Dalam bahasa yang cukup statis C # satu dapat menggunakan ?? operator á la: objek f = a ?? b ?? c ?? d ?? e;
herzmeister

2
herzmeister - terima kasih! Saya tidak tahu itu ?? operator dapat dirantai dalam C # dan digunakan dalam teknik evaluasi malas
Marek

3
Seperti disebutkan di tempat lain, yang terakhir dakan ditetapkan apakah itu null / tidak terdefinisi atau tidak.
BlackVegetable

Satu koreksi kecil: ||operator selalu memutuskan untuk seluruh operan sisi kanan ketika sisi kiri falsy. Menjadi operator boolean hanya melihat dua input: sisi kiri dan sisi kanan. Pengurai tidak melihat mereka sebagai serangkaian istilah, jadi itu tidak benar-benar berhenti ketika menemukan nilai kebenaran pertama kecuali jika nilai itu juga merupakan operan tangan kiri dari yang lain ||.
devios1

8

Pertanyaan ini sudah menerima beberapa jawaban bagus.

Singkatnya, teknik ini memanfaatkan fitur bagaimana bahasa dikompilasi. Artinya, JavaScript "sirkuit pendek" evaluasi operator Boolean dan akan mengembalikan nilai yang terkait dengan nilai variabel non-false pertama atau apa pun yang berisi variabel terakhir. Lihat penjelasan Anurag tentang nilai-nilai yang akan dinilai salah.

Menggunakan teknik ini bukan praktik yang baik karena beberapa alasan; namun.

  1. Keterbacaan Kode: Ini menggunakan operator Boolean, dan jika perilaku bagaimana kompilasi ini tidak dipahami, maka hasil yang diharapkan akan menjadi nilai Boolean.
  2. Stabilitas: Ini menggunakan fitur bagaimana bahasa dikompilasi yang tidak konsisten di berbagai bahasa, dan karena ini adalah sesuatu yang berpotensi ditargetkan untuk perubahan di masa depan.
  3. Fitur yang Didokumentasikan: Ada alternatif yang ada yang memenuhi kebutuhan ini dan konsisten di lebih banyak bahasa. Ini akan menjadi operator ternary:

    ()? nilai 1: Nilai 2.

Menggunakan operator ternary memang membutuhkan pengetikan yang lebih sedikit, tetapi ia dengan jelas membedakan antara ekspresi Boolean yang dievaluasi dan nilai yang diberikan. Selain itu dapat dirantai, sehingga jenis tugas default yang dilakukan di atas dapat dibuat kembali.

var a;
var b = null;
var c = undefined;
var d = 4;
var e = 'five';

var f =  ( a ) ? a : 
                ( b ) ? b :
                       ( c ) ? c :
                              ( d ) ? d :
                                      e;

alert(f); // 4

potentially be targeted for change in the future.ya, tapi saya tidak menggunakannya untuk javascript.
Dadan

Datang ke sini dan melihat semua jawaban di atas dan berpikir pada diri sendiri bahwa ada sesuatu yang mengabaikan tugas itu. Saya baru saja membaca Kode Bersih oleh Robert C Martin dan jenis penugasan ini jelas melanggar aturan "Tidak Memiliki Efek Samping" ... sementara penulis sendiri menyatakan bahwa bukunya hanya satu dari banyak teknik untuk menghasilkan kode yang baik, saya masih terkejut bahwa tidak ada orang lain yang keberatan dengan penugasan semacam ini. +1
Albert Rothman

Terima kasih atas tanggapannya. Saya pikir lebih banyak orang perlu mempertimbangkan efek samping ketika menulis kode, tetapi sampai seseorang menghabiskan banyak waktu mempertahankan kode orang lain. Mereka sering tidak mempertimbangkannya.
WSimpson

1
Anda benar-benar berpikir bahwa monstrositas lebih jelas daripada a || b || c || d || e?
devios1

1
@AlbertRothman Saya tidak melihat efek samping. Tidak ada yang dimutasi. Ini hanyalah singkatan untuk penggabungan nol, yang merupakan fitur yang cukup umum dalam banyak bahasa.
devios1

7

Kembalikan nilai asli pertama .

Jika semuanya false, kembalikan nilai false terakhir.

Contoh:-

  null || undefined || false || 0 || 'apple'  // Return apple

4

Ini mengatur variabel baru ( z) ke nilai xapakah itu "benar" (bukan nol, objek / array / fungsi yang valid / apa pun itu) atau ysebaliknya. Ini adalah cara yang relatif umum untuk memberikan nilai default jika xtidak ada.

Misalnya, jika Anda memiliki fungsi yang mengambil parameter panggilan balik opsional, Anda bisa memberikan panggilan balik default yang tidak melakukan apa-apa:

function doSomething(data, callback) {
    callback = callback || function() {};
    // do stuff with data
    callback(); // callback will always exist
}

1

Ini berarti bahwa jika xdiatur, nilai untuk zakan x, jika ytidak diatur maka nilainya akan ditetapkan sebagai znilai.

itu sama dengan

if(x)
  z = x;
else
  z = y;

Itu mungkin karena operator logis dalam JavaScript tidak mengembalikan nilai boolean tetapi nilai elemen terakhir yang diperlukan untuk menyelesaikan operasi (dalam kalimat ATAU itu akan menjadi nilai non-salah pertama, dalam kalimat DAN itu akan menjadi yang terakhir ). Jika operasi gagal, maka falsedikembalikan.


5
ini salah! jika (x) {z = x; } else {z = y;} jika nilai pertama salah, nilai kedua selalu diberikan tidak tergantung pada apa nilai sebenarnya.
evilpie

Kecuali saya pikir itu hanya menetapkan y ke z jika x salah . Itulah cara kerjanya bagi saya di FF, tentu saja, itu mungkin tergantung pada implementasi juga.
tvanfosson

7
Bagian terakhir tentang mengembalikan false tidak benar (tidak ada permainan kata pun yang dimaksudkan). Jika nilai pertama adalah falsey, ||operator hanya mengembalikan nilai kedua, terlepas dari apakah itu benar atau tidak.
Matthew Crumley

-1. Potongan kode setara Anda adalah akurat, tetapi yang penting adalah bahwa zakan diatur ke nilai xjika nilai yang truthy . Kalau tidak akan diatur ke nilai y. Ini berarti bahwa jika xdiatur ke, misalnya 0,, atau string kosong "", ini tidak melakukan apa yang Anda katakan, karena nilai-nilai itu palsu .
Daniel Cassidy

1

Ini disebut operator hubung singkat.

Evaluasi hubung singkat mengatakan, argumen kedua dieksekusi atau dievaluasi hanya jika argumen pertama tidak cukup untuk menentukan nilai ekspresi. ketika argumen pertama dari fungsi OR (||) mengevaluasi ke true, nilai keseluruhan harus benar.

Ini juga dapat digunakan untuk menetapkan nilai default untuk argumen fungsi.`

function theSameOldFoo(name){ 
  name = name || 'Bar' ;
  console.log("My best friend's name is " + name);
}
theSameOldFoo();  // My best friend's name is Bar
theSameOldFoo('Bhaskar');  // My best friend's name is Bhaskar`

0

Ini akan mengevaluasi X dan, jika X bukan nol, string kosong, atau 0 (false false), maka akan menetapkannya ke z. Jika X adalah null, string kosong, atau 0 (false false), maka itu akan menetapkan y ke z.

var x = '';
var y = 'bob';
var z = x || y;
alert(z);

Akan menampilkan 'bob';


Anda harus mengklarifikasi apa yang Anda maksud dengan 'kosong'. String kosong memaksa false, tetapi array kosong atau objek memaksa true.
Daniel Cassidy

@Daniel "null, kosong, atau 0" - null akan berlaku sehubungan dengan array dan objek. Poin yang diambil.
tvanfosson

0

Menurut posting Blog Bill Higgins ' ; idiom logis Javascript ATAU penugasan (Februari 2007), perilaku ini berlaku pada v1.2 (setidaknya)

Dia juga menyarankan penggunaan lain untuk itu (dikutip): " normalisasi ringan perbedaan lintas-browser "

// determine upon which element a Javascript event (e) occurred
var target = /*w3c*/ e.target || /*IE*/ e.srcElement;
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.