Apa yang dikerjakan oleh konstruk x = x || maksudmu?

250

Saya men-debug beberapa JavaScript, dan tidak bisa menjelaskan apa ||fungsinya?

function (title, msg) {
  var title = title || 'Error';
  var msg   = msg || 'Error on Request';
}

Bisakah seseorang memberi saya petunjuk, mengapa orang ini menggunakan var title = title || 'ERROR'? Terkadang saya melihatnya tanpa vardeklarasi juga.

opHASnoNAME
sumber
44
Orang-orang sudah menjawab ini ... tetapi sangat menyadari fakta bahwa nilai kedua dipilih jika nilai pertama adalah falsy, bukan HANYA undefined. Jumlah yang saya lihat doWeDoIt = doWeDoIt || true, sudah cukup untuk membuat saya menangis. (yaitu doWeDoItsekarang tidak akan pernah false)
Matt
4
Bagi mereka yang berpengalaman dengan C #, operator pipa ganda setara dengan operator null-coalesce ??. Javascript mengevaluasi objek non-null seperti true (atau lebih baik evalualtes objek null ke false)
usr-local-ΕΨΗΕΛΩΝ
3
Jangan merasa buruk - JS adalah satu-satunya bahasa konyol yang memungkinkan pengkodean yang mengerikan ini .... itu dan mengajarkan bahwa layak untuk menyarang setiap fungsi ke dalam baris kode dan membuangnya sehingga membuatnya dapat dibuang dan tidak dapat digunakan lagi untuk kedua kalinya. :) Saya 30 tahun ke dalam pengkodean dan menunda menyentuh JS sampai beberapa waktu yang lalu saya dan saya merasakan sakit Anda yang bisa saya katakan adalah, pertahankan "tidak masuk akal, ini hanya dalam JS" berguna cheetsheet berguna itu satu-satunya cara saya sudah lewat! :)
Collin Chaffin
1
Harap pertimbangkan untuk mengubah jawaban yang diterima ke jawaban saya .
Michał Perłakowski

Jawaban:

210

Ini berarti titleargumennya opsional. Jadi jika Anda memanggil metode tanpa argumen itu akan menggunakan nilai default "Error".

Ini singkatan untuk menulis:

if (!title) {
  title = "Error";
}

Trik semacam steno dengan ekspresi boolean juga umum di Perl. Dengan ekspresi:

a OR b

mengevaluasi trueapakah salah satu aatau btidak true. Jadi, jika abenar, Anda tidak perlu memeriksa bsama sekali. Ini disebut evaluasi boolean hubung singkat sehingga:

var title = title || "Error";

pada dasarnya memeriksa apakah titledievaluasi false. Jika ya, "kembali" "Error", jika tidak kembali title.

cletus
sumber
3
Maaf untuk pilih-pilih, tapi argumennya tidak opsional, argumennya diperiksa
themightybun
4
Ini BUKAN jawabannya dan saya setuju dengan komentar terakhir itu bahkan bukan opsional. Tidak ada bagian dari jawaban ini yang benar bahkan referensi Perl karena pernyataan Perl benar-benar membuat SENSE dan dievaluasi dengan cara yang sama sekali berbeda. JS adalah eval dalam metode logika boolean jauh lebih "dikonversi" yang saya juga menemukan jauh lebih membingungkan untuk membaca / menulis. Jawaban di bawah ini berjudul "Apa itu operator pipa ganda" sebenarnya adalah jawaban yang benar.
Collin Chaffin
198

Apa itu operator pipa ganda ( ||)?

Operator pipa ganda ( ||) adalah operator logisOR . Dalam sebagian besar bahasa ini bekerja dengan cara berikut:

  • Jika nilai pertama adalah false, itu memeriksa nilai kedua. Jika itu true, ia kembali truedan jika itu false, ia kembali false.
  • Jika nilai pertama true, selalu kembali true, tidak peduli apa nilai kedua.

Jadi pada dasarnya ini berfungsi seperti fungsi ini:

function or(x, y) {
  if (x) {
    return true;
  } else if (y) {
    return true;
  } else {
    return false;
  }
}

Jika Anda masih tidak mengerti, lihat tabel ini:

      | true   false  
------+---------------
true  | true   true   
false | true   false  

Dengan kata lain, itu hanya salah ketika kedua nilai tersebut salah.

Apa bedanya dengan JavaScript?

JavaScript sedikit berbeda, karena ini adalah bahasa yang diketik secara longgar . Dalam hal ini berarti Anda dapat menggunakan ||operator dengan nilai yang bukan boolean. Meskipun tidak masuk akal, Anda dapat menggunakan operator ini dengan misalnya fungsi dan objek:

(function(){}) || {}

Apa yang terjadi disana?

Jika nilainya bukan boolean, JavaScript membuat konversi implisit ke boolean . Ini berarti bahwa jika nilai falsey (misalnya 0, "", null, undefined(lihat juga Semua nilai falsey di JavaScript )), ia akan diperlakukan sebagai false; kalau tidak diperlakukan sebagai true.

Jadi contoh di atas harus memberi true, karena fungsi kosong itu benar. Ya tidak. Ini mengembalikan fungsi kosong. Itu karena ||operator JavaScript tidak berfungsi seperti yang saya tulis di awal. Cara kerjanya sebagai berikut:

  • Jika nilai pertama adalah falsey , itu mengembalikan nilai kedua .
  • Jika nilai pertama adalah truthy , ia mengembalikan nilai pertama .

Terkejut? Sebenarnya, ini "kompatibel" dengan ||operator tradisional . Dapat ditulis sebagai fungsi berikut:

function or(x, y) {
  if (x) {
    return x;
  } else {
    return y;
  }
}

Jika Anda melewatkan nilai kebenaran sebagai x, itu mengembalikan x, yaitu nilai kebenaran. Jadi jika Anda menggunakannya nanti dalam ifklausa:

(function(x, y) {
  var eitherXorY = x || y;
  if (eitherXorY) {
    console.log("Either x or y is truthy.");
  } else {
    console.log("Neither x nor y is truthy");
  }
}(true/*, undefined*/));

kamu dapatkan "Either x or y is truthy.".

Jika xitu palsu, eitherXorYakan menjadi y. Dalam hal ini Anda akan mendapatkan "Either x or y is truthy."jika yitu benar; kalau tidak Anda akan mendapatkan "Neither x nor y is truthy".

Pertanyaan sebenarnya

Sekarang, ketika Anda tahu cara ||kerja operator, Anda mungkin dapat mengetahui sendiri apa x = x || yartinya. Jika xbenar, xditugaskan x, maka sebenarnya tidak ada yang terjadi; jika ytidak ditugaskan x. Ini biasanya digunakan untuk mendefinisikan parameter default dalam fungsi. Namun, ini sering dianggap praktik pemrograman yang buruk , karena mencegah Anda melewatkan nilai falsey (yang tidak harus undefinedatau null) sebagai parameter. Pertimbangkan contoh berikut:

function badFunction(/* boolean */flagA) {
  flagA = flagA || true;
  console.log("flagA is set to " + (flagA ? "true" : "false"));
}

Terlihat valid pada pandangan pertama. Namun, apa yang akan terjadi jika Anda meneruskan falsesebagai flagAparameter (karena itu boolean, yaitu bisa trueatau false)? Itu akan menjadi true. Dalam contoh ini, tidak ada cara untuk mengatur flagAke false.

Ini akan menjadi ide yang baik untuk secara eksplisit memeriksa apakah flagAini undefined, seperti itu:

function goodFunction(/* boolean */flagA) {
  flagA = typeof flagA !== "undefined" ? flagA : true;
  console.log("flagA is set to " + (flagA ? "true" : "false"));
}

Meskipun lebih panjang, selalu bekerja dan lebih mudah untuk dipahami.


Anda juga dapat menggunakan sintaks ES6 untuk parameter fungsi default , tetapi perhatikan bahwa itu tidak berfungsi di browser lama (seperti IE). Jika Anda ingin mendukung browser ini, Anda harus mengubah kode Anda dengan Babel .

Lihat juga Operator Logis di MDN .

Michał Perłakowski
sumber
13
+1 - sejauh ini jawaban yang paling benar dan lengkap. Dan, bagi mereka yang memiliki pertanyaan ini (sebagian dari kita, coders veteran yang baru mengenal JS) pastinya harus memfokuskan sebagian besar dari seluruh jawaban ini pada baris ini: "Meskipun tidak masuk akal" karena "jenis loosley ini" tidak akan pernah masuk akal untuk kita yang tumbuh tanpa itu. Bagi kami, operator boolean hanya itu dan HANYA itu ...... dan siapa pun yang pernah berpikir itu akan menjadi ide yang baik untuk harus berhenti dan memikirkan beberapa konversi aneh nilai-nilai non-boolean ke boolean saat membaca / menulis kode , lupa minum obat-obatan mereka hari itu! :)
Collin Chaffin
2
+1, singkatnya: title = title || 'Error'berartiif (title) { title = title; } else { title = 'Error'; }
Andre Elrico
Saya sebenarnya tidak setuju dengan garis "meskipun tidak masuk akal". Saya mengerti baris tidak akan dikompilasi dalam C, misalnya, tetapi dipahami dengan baik jika Anda berasal dari Ruby misalnya, atau bahkan Groovy. Di Ruby, Anda dapat mengekspresikannya lebih pendek, seperti title ||= 'Error'.
Elliot Nelson
28

Jika judul tidak disetel, gunakan 'KESALAHAN' sebagai nilai default.

Lebih umum:

var foobar = foo || default;

Dibaca: Set foobar ke fooatau default. Anda bahkan dapat membuat rantai ini berkali-kali:

var foobar = foo || bar || something || 42;
ericteubert
sumber
1
Saya menemukan itu membingungkan karena variabel memiliki nama yang sama. Jauh lebih mudah jika tidak.
Norbert Norbertson
14

Menjelaskan ini sedikit lagi ...

The ||Operator adalah logis- oroperator. Hasilnya benar jika bagian pertama benar dan benar jika bagian kedua benar dan benar jika kedua bagian itu benar. Untuk kejelasan, ini dia dalam tabel:

 X | Y | X || Y 
---+---+--------
 F | F |   F    
---+---+--------
 F | T |   T    
---+---+--------
 T | F |   T    
---+---+--------
 T | T |   T    
---+---+--------

Sekarang perhatikan sesuatu di sini? Jika Xbenar, hasilnya selalu benar. Jadi jika kita tahu itu Xbenar, kita tidak perlu memeriksa Ysama sekali. Banyak bahasa dengan demikian menerapkan evaluator "korsleting" untuk logis- or(dan logis- anddatang dari arah lain). Mereka memeriksa elemen pertama dan jika itu benar mereka tidak repot-repot memeriksa yang kedua sama sekali. Hasilnya (dalam hal logis) adalah sama, tetapi dalam hal eksekusi ada potensi perbedaan besar jika elemen kedua mahal untuk dihitung.

Jadi apa hubungannya ini dengan contoh Anda?

var title   = title || 'Error';

Mari kita lihat itu. The titleelemen dilewatkan ke fungsi Anda. Dalam JavaScript jika Anda tidak mengirimkan parameter, defaultnya adalah nilai nol. Juga dalam JavaScript jika variabel Anda adalah nilai nol, itu dianggap salah oleh operator logis. Jadi jika fungsi ini disebut dengan judul yang diberikan, itu adalah nilai yang tidak salah dan dengan demikian ditugaskan ke variabel lokal. Namun, jika tidak diberi nilai, itu adalah nilai nol dan dengan demikian salah. orOperator logis kemudian mengevaluasi ekspresi kedua dan mengembalikan 'Kesalahan' sebagai gantinya. Jadi sekarang variabel lokal diberi nilai 'Kesalahan'.

Ini berfungsi karena penerapan ekspresi logis dalam JavaScript. Itu tidak mengembalikan nilai boolean yang tepat ( trueatau false) tetapi sebaliknya mengembalikan nilai itu diberikan di bawah beberapa aturan untuk apa yang dianggap setara dengan truedan apa yang dianggap setara dengan false. Cari referensi JavaScript Anda untuk mempelajari apa yang dianggap benar atau salah oleh JavaScript dalam konteks boolean.

HANYA PENDAPAT SAYA yang benar
sumber
8

Pipa ganda singkatan dari "OR" logis. Ini tidak benar-benar terjadi ketika "parameter tidak disetel", karena secara ketat di javascript jika Anda memiliki kode seperti ini:

function foo(par) {
}

Lalu telepon

foo()
foo("")
foo(null)
foo(undefined)
foo(0)

tidak setara.

Pipa ganda (||) akan melemparkan argumen pertama ke boolean dan jika boolean yang dihasilkan benar - lakukan penugasan jika tidak maka akan menetapkan bagian yang tepat.

Ini penting jika Anda memeriksa parameter yang tidak disetel.

Katakanlah, kita memiliki fungsi setSalary yang memiliki satu parameter opsional. Jika pengguna tidak menyediakan parameter maka nilai default 10 harus digunakan.

jika Anda melakukan pemeriksaan seperti ini:

function setSalary(dollars) {
    salary = dollars || 10
}

Ini akan memberikan hasil yang tidak terduga seperti panggilan

setSalary(0) 

Ini masih akan mengatur 10 mengikuti aliran yang dijelaskan di atas.

Juriy
sumber
8

Pada dasarnya memeriksa apakah nilai sebelum || bernilai true, jika ya, dibutuhkan nilai ini, jika tidak, dibutuhkan nilai setelah ||.

Nilai yang akan diambil nilainya setelah || (Sejauh yang saya ingat):

  • tidak terdefinisi
  • Salah
  • 0
  • '' (Null atau Null string)
Morfildur
sumber
1
false || null || undefined || 0 || '' || 'Anda lupa nol'
Dziamid
7

Sementara jawaban Cletus benar, saya merasa lebih detail harus ditambahkan sehubungan dengan "evaluate to false" dalam JavaScript.

var title = title || 'Error';
var msg   = msg || 'Error on Request';

Tidak hanya memeriksa jika judul / msg telah disediakan, tetapi juga jika salah satu dari mereka adalah falsy . yaitu salah satu dari yang berikut:

  • Salah.
  • 0 (nol)
  • "" (string kosong)
  • batal.
  • tidak terdefinisi.
  • NaN (nilai Angka khusus yang berarti Bukan Angka!)

Begitu juga

var title = title || 'Error';

Jika judul itu benar (yaitu, bukan falsy, maka title = "titleMessage" dll.) Maka operator Boolean OR (||) telah menemukan satu nilai 'benar', yang berarti ia mengevaluasi nilai true, sehingga membuat sirkuit pendek dan mengembalikan nilai sebenarnya (judul).

Jika judul salah (yaitu salah satu dari daftar di atas), maka operator Boolean OR (||) telah menemukan nilai 'salah', dan sekarang perlu mengevaluasi bagian lain dari operator, 'Kesalahan', yang dievaluasi menjadi true , dan karenanya dikembalikan.

Tampaknya juga (setelah beberapa percobaan konsol pembakar cepat) jika kedua sisi operator mengevaluasi ke false, ia mengembalikan operator 'palsu' kedua.

yaitu

return ("" || undefined)

kembali tidak terdefinisi, ini mungkin memungkinkan Anda untuk menggunakan perilaku yang ditanyakan dalam pertanyaan ini ketika mencoba judul / pesan default ke "". yaitu setelah berjalan

var foo = undefined
foo = foo || ""

foo akan diatur ke ""

Azrantha
sumber
5

operator pipa ganda

Apakah contoh ini bermanfaat?

var section = document.getElementById('special');
if(!section){
     section = document.getElementById('main');
}

bisa juga

var section = document.getElementById('special') || document.getElementById('main');
choise
sumber
4

Untuk menambahkan beberapa penjelasan kepada semua yang dikatakan sebelum saya, saya harus memberi Anda beberapa contoh untuk memahami konsep logis.

var name = false || "Mohsen"; # name equals to Mohsen
var family = true || "Alizadeh" # family equals to true

Ini berarti jika sisi kiri dievaluasi sebagai pernyataan yang benar itu akan selesai dan sisi kiri akan dikembalikan dan ditugaskan ke variabel. dalam kasus lain sisi kanan akan dikembalikan dan ditugaskan.

Dan operator memiliki struktur yang berlawanan seperti di bawah ini.

var name = false && "Mohsen" # name equals to false
var family = true && "Alizadeh" # family equals to Alizadeh
Mohsen Alizadeh
sumber
3

|| adalah operator boolean OR. Seperti dalam javascript, undefined, null, 0, false dianggap sebagai nilai falsy .

Itu hanya berarti

true || true = true
false || true = true
true || false = true
false || false = false

undefined || "value" = "value"
"value" || undefined = "value"
null || "value" = "value"
"value" || null = "value"
0 || "value" = "value"
"value" || 0 = "value"
false || "value" = "value"
"value" || false = "value"
Shivang Gupta
sumber
2

Kutipan: "Apa arti konstruk x = x || y?"

Menetapkan nilai default.

Ini berarti memberikan nilai default y ke x , dalam kasus x masih menunggu nilainya tetapi belum menerimanya atau sengaja dihilangkan untuk kembali ke default.

Bekim Bacaj
sumber
Itulah makna yang tepat dari konstruk dan satu-satunya makna darinya. Dan itu sangat sebagai subrutin dalam fungsi penulisan yang dapat diambil sebagai prototipe, fungsi mandiri, dan juga sebagai metode pinjaman untuk diterapkan pada elemen lain. Di mana tugas utamanya dan satu-satunya adalah mengubah referensi target. Contoh: function getKeys(x) { x = x || this ; .... }yang dapat digunakan tanpa modifikasi sebagai fungsi mandiri, sebagai metode properti dalam prototipe dan sebagai metode elemen yang bisa mendapatkan elemen lain sebagai argumennya sebagai `[elemen] .getKeys (anotherElement);`
Bekim Bacaj
-5

Dan saya harus menambahkan satu hal lagi: Tulisan singkat ini adalah kekejian. Ini menyalahgunakan optimasi juru bahasa yang tidak disengaja (tidak mengganggu operasi kedua jika yang pertama adalah benar) untuk mengontrol tugas. Penggunaan itu tidak ada hubungannya dengan tujuan operator. Saya tidak percaya itu harus digunakan.

Saya lebih suka operator ternary untuk inisialisasi, misalnya,

var title = title?title:'Error';

Ini menggunakan operasi bersyarat satu baris untuk tujuan yang benar. Ini masih memainkan game yang tidak sedap dipandang dengan kebenaran tetapi, itu Javascript untuk Anda.

tqwhite
sumber