JavaScript VEYA (||) değişken atama açıklaması


351

Bu JavaScript snippet'i göz önüne alındığında ...

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

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

alert(f); // 4

Birisi bana bu tekniğin ne olduğunu açıklayabilir mi (benim en iyi tahminim bu sorunun başlığında!)? Ve nasıl / neden tam olarak çalışıyor?

Anladığım kadarıyla, değişkene f, null veya undefined olmayan bir değere sahip ilk değişkenin en yakın değerine (soldan sağa) atanacak, ancak bu teknik hakkında çok fazla referans materyali bulmayı başaramadım ve çok kullandığını gördüm.

Ayrıca, bu teknik JavaScript'e özgü mü? PHP benzer bir şey yapmanın kendisi fyerine gerçek bir boolean değeri ile sonuçlanır biliyorum d.


4
Eski bir soru, ama PHP ile ilgili, kullanabileceğiniz bir yapı vardır: $f=$a or $f=$b or $f=$c; // etc. PHP aynı işi yapan hem ||operatöre hem de operatöre sahiptir or; Ancak ordeğerlendirilir sonra atama yaparken ||önce değerlendirilir. Bu aynı zamanda size Perish tarzı vermek$a=getSomething() or die('oops');
Manngo

1
PHP 5.3'te üçlü operatörün orta kısmını dışarıda bırakabilirsiniz, bu yüzden ... Bunu da böyle bir şeye biraz daha kısa kesebilirsiniz: $f = $a ?: $b ?: $c;
Rei

1
PHP 7'den itibaren ??bunun için kullanabilirsiniz . $a = $b ?? 'default'
Spencer Ruskin

Böylece @SpencerRuskin $adeğerini atanacak $beğer $bdiğer doğrudur 'default'?
oldboy

Doğru. Bu sayfadaki boş birleştirme operatörü bölümüne bakın: php.net/manual/tr/migration70.new-features.php
Spencer Ruskin

Yanıtlar:


212

Açıklama için kısa devre değerlendirmesine bakın . Bu operatörleri uygulamanın yaygın bir yoludur; JavaScript'e özgü değildir.


57
Sadece 'gotcha'ya dikkat edin, ki hepsi tanımlanmamış, boş veya yanlış olsalar bile sonuncusu her zaman atanacaktır. Zincirin sonunda yanlış, null veya tanımsız olduğunu bildiğiniz bir şeyi ayarlamak, hiçbir şey bulunamadığını belirtmek için iyi bir yoldur.
Erik Reppen

Yıllardır bu tekniği gördüm, ama o zaman kullanmak istediğimde bana çarpıcı gelen şey, ifadenin sonucunun boole'ye dökülmemesidir. Daha sonra yapamazsın if( true == f ). F'de bir tamsayı kaydedilmişse, bu test her zaman false değerini döndürür.

9
Aslında, bunu yapabilirsiniz if(true == f), aynı if(f): test geçecek. Ayrıca test etmek isterseniz türünü ait f: katı bir karşılaştırma kullanmak if(true === f), gerçekten de başarısız olur.
Alsciende

5
Evet, kısa devre değerlendirmesi yaygındır. Ancak buradaki ayrım, JavaScript'in yürütmeyi durduran son değeri döndürme biçiminde yatmaktadır. @ Anurag'ın cevabı bunu açıklamaktan çok daha iyi bir iş çıkarıyor.
Ben.12

yeni başlayanlar için en iyi açıklama olup olmadığından emin değilim. Tavsiye ederim: javascript.info/logical-operators
csguy

198

Bu atama yapılır varsayılan değeri bu durumda, değerini yise, xdeğişkendir falsy .

JavaScript'teki boole işleçleri, diğer dillerde olduğu gibi her zaman bir boole sonucu değil, bir işlenen döndürebilir.

Mantıksal VEYA operatörü ( ||) ikinci işleneninin değerini döndürür, eğer ilki falsiyse, aksi takdirde ilk işlenenin değeri döndürülür.

Örneğin:

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

Falsy değerler için bu kim zorlamak için olan falseboolean bağlamında kullanıldığında, ve bunlar 0, null, undefined, boş bir dize, NaNve tabii ki false.


1
+1 Böyle bir operatör var mı? Veya ||özeldir.
OscarRyz

9
@Support (@Oscar): Mantıksal &&işleç benzer bir davranışa sahiptir, eğer tek başınaysa , ilk işlenenin değerini döndürür ve ikinci işlenenin değerini, yalnızca ilkinin doğruysa döndürür , örn. ("foo" && "bar") == "bar"Ve(0 && "bar") == 0
CMS

12
Falsy aslında teknik terimdir.
ChaosPandion

8
Biz de bu yayında ||, &&, "Falsy" ve "Truly" hakkında bilgi edindik. "Gizli" hediyeler ile en iyi cevap.
Alex

4
@Alex NB: "Truthy" ( "Gerçekten"!)
Tümsekli

183

Javacript, mantıksal operatörler ve için kısa devre değerlendirmesini kullanır . Ancak, a veya değer yerine yürütmeyi durduran son değerin sonucunu döndürmesi diğer dillerden farklıdır .||&&truefalse

Aşağıdaki değerler JavaScript'te yanlış olarak kabul edilir.

  • yanlış
  • boş
  • "" (boş dize)
  • 0
  • Nan
  • Tanımsız

Operatör öncelik kurallarını göz ardı ederek ve işleri basit tutarak, aşağıdaki örnekler değerlendirmeyi hangi değerin durdurduğunu ve sonuç olarak geri döndüğünü gösterir.

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

İlk 5 değer NaNfalsidir, bu nedenle ilk doğruluk değerini karşılayana kadar hepsi soldan sağa değerlendirilir - "Hello"bu da tüm ifadeyi doğru yapar, böylece daha sonraki her şey değerlendirilmez ve "Hello"ifadenin sonucu olarak geri döner . Benzer şekilde, bu durumda:

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

İlk 5 değerin tümü doğrudur ve nullifadeyi yanlış yapan ilk yanlış değeri ( ) karşılayana kadar değerlendirilir , bu yüzden 2010artık değerlendirilmez nullve ifadenin sonucu olarak döndürülür.

Verdiğiniz örnek, bir ödev gerçekleştirmek için bu JavaScript özelliğinden faydalanmaktır. Bir değer kümesi arasında ilk doğruluk veya falsi değerini elde etmeniz gereken her yerde kullanılabilir. Bu kod aşağıda değer atar "Hello"etmek byerine if-else kontrolleri yapmanın, daha kolay bir varsayılan değer atamak için yapar gibi.

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

Aşağıdaki örnek bu özellik sömürü diyebiliriz ve ben inanıyorum kod okumayı zorlaştırır.

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

Uyarının içinde messages, sahte olup olmadığını kontrol ederiz ve eğer evetse, değerlendirin ve geri gönderin noNewMessagesText, aksi takdirde değerlendirin ve geri dönün newMessagesText. Bu örnekte sahte olduğu için noNewMessagesText ve alert'te durduk "Sorry, you have no new messages.".


36
Bu, aşağıdaki açıklama nedeniyle bence en iyi cevap: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
@mastazi Evet, kalın yazı tipinde IMHO yazmalı.
noober

6
Cevap olmalı, test senaryoları üzerinden seçilen değerleri gösterir.
Dadan

Kabul ediyorum, bu özellikle JavaScript değişken ataması endişelerini ele aldığı için en sevdiğim cevap. Ayrıca, atamayı test etmek için bir sonraki üç değişkenten biri olarak bir üçlü kullanmayı tercih ederseniz (işleçten sonra) atama değerlendirmesinin düzgün çalışması için üçgeni parantez içine almanız gerekir.
Joey T

49

Javascript değişkenleri yazılmaz, bu nedenle boole işleçleri tarafından atanmış olsa bile f'ye bir tamsayı değeri atanabilir.

f, false değerine eşit olmayan en yakın değere atanır . Yani 0, false, null, undefined, hepsi aktarılır:

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

13
''Bu durumda eşit yanlış da unutma .
Brigand

f is assigned the NEAREST valueBurada oldukça önemli bir noktaya işaret etmek için oy verin .
steviejay

3
"En yakın" tam olarak doğru olmasa da bu görünüme sahip. Bir boolean ||operatörü olan boolean operatörünün iki operandı vardır: sol taraf ve sağ taraf. Sol tarafı ise ||olduğu truthy , sol tarafta ve sağ tarafına operasyon giderir göz ardı edilir. Sol taraf falsiyse , sağ tarafa doğru çözülür. Yani null || undefined || 4 || 0aslında undefined || 4 || 0hangisinin çözüleceğine 4 || 0karar verir 4.
devios1

29

Bunda sihir yok. Boole ifadeleri a || b || c || dtembel olarak değerlendirilir. Interpeter değerini arar a, tanımsızdır, bu yüzden yanlıştır, böylece devam eder, sonra bnull olduğunu görür , bu hala yanlış sonuç verir, böylece devam eder, sonra görür c- aynı hikaye. Sonunda d'ha, boş değil, bu yüzden sonucum var' diyor ve son değişkene atar.

Bu hile, boole ifadelerinin tembel kısa devre değerlendirmesini yapan tüm dinamik dillerde çalışacaktır. Statik dillerde derlenmez (tip hatası). Boole ifadelerini değerlendirmeye istekli dillerde mantıksal değer döndürür (yani bu durumda doğrudur).


6
Oldukça statik dilde C # bir ?? kullanabilirsiniz operatör la: nesne f = a ?? b ?? c ?? d ?? e;
herzmeister

2
herzmeister - teşekkürler! Bunu bilmiyordum ?? operatörü C # olarak zincirlenebilir ve tembel değerlendirme tekniklerinde kullanılabilir
Marek

3
Başka bir yerde belirtildiği gibi, bu sonuncusu dboş / tanımsız olsun veya olmasın atanacaktır.
BlackVegetable

Hafif bir düzeltme: ||sol taraf sahteleyken operatör her zaman sağ taraftaki işlenene gider. Bir boole operatörü olarak yalnızca iki girdi görür: sol taraf ve sağ taraf. Ayrıştırıcı onları bir dizi terim olarak görmez, bu nedenle bu değer aynı zamanda bir başkasının sol el işleneni olmadıkça , ilk doğruluk değerini bulduğunda aslında durmaz ||.
devios1

8

Bu soru zaten birkaç iyi yanıt aldı.

Özetle, bu teknik, dilin nasıl derlendiği özelliğinden yararlanmaktadır. Yani, JavaScript Boole işleçlerinin değerlendirmesini "kısa devre yapar" ve ilk yanlış olmayan değişken değerle veya son değişkenin içerdiği değerle ilişkili değeri döndürür. Anurag'ın yanlış olarak değerlendirilecek değerleri açıklamasına bakın.

Bu tekniği kullanmak çeşitli nedenlerle iyi bir uygulama değildir; ancak.

  1. Kod Okunabilirliği: Bu, Boolean işleçlerini kullanır ve bunun nasıl derlendiğinin davranışı anlaşılmazsa, beklenen sonuç bir Boolean değeri olur.
  2. Kararlılık: Bu, dilin birden çok dilde tutarlı olmayan bir şekilde nasıl derlendiğini kullanır ve bu nedenle gelecekte değişiklik için potansiyel olarak hedeflenebilecek bir şeydir.
  3. Belgelenmiş Özellikler: Bu ihtiyacı karşılayan ve daha fazla dilde tutarlı olan mevcut bir alternatif vardır. Bu üçlü operatör olacaktır:

    ()? değer 1: Değer 2.

Üçlü operatörün kullanılması biraz daha fazla yazmayı gerektirir, ancak değerlendirilmekte olan Boole ifadesi ile atanan değer arasında açıkça ayrım yapar. Ek olarak zincirlenebilir, böylece yukarıda gerçekleştirilen varsayılan atama türleri yeniden oluşturulabilir.

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.evet, ama javascript için geçerli değil.
Dadan

Buraya geldi ve yukarıdaki tüm cevapları gördüm ve kendime ödev hakkında bir şeyler baktığını düşünüyordum. Robert C Martin tarafından Temiz Kod okudum ve bu tür bir görev kesinlikle "Yan Etkisi Yok" kuralını ihlal ediyor ... yazarın kendisi kitabının iyi kod üretmek için birçok teknikten sadece biri olduğunu belirtiyor, bu tür bir göreve kimsenin itiraz etmediğine hala şaşırmıştı. +1
Albert Rothman

Cevap için teşekkürler. Kod yazarken daha fazla insanın yan etkileri düşünmesi gerektiğini düşünüyorum, ancak birileri diğer insanların kodlarını korumak için çok zaman harcayana kadar. Genellikle bunu düşünmezler.
WSimpson

1
Gerçekten canavarlığın daha net olduğunu a || b || c || d || emu düşünüyorsun ?
devios1

1
@AlbertRothman Hiçbir yan etki görmüyorum. Hiçbir şey mutasyona uğramaz. Birçok dilde oldukça yaygın bir özellik olan null birleştirme kısayolu.
devios1

7

Çıktı ilk doğru değerini döndürür .

Hepsi yanlışsa son yanlış değeri döndürür.

Misal:-

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

4

Yeni değişkeni ( z) x"doğruluk" (sıfırdan farklı, geçerli bir nesne / dizi / işlev / her neyse) değerine veya başka bir değere ayarlar y. xMevcut değilse, varsayılan bir değer sağlamanın nispeten yaygın bir yoludur .

Örneğin, isteğe bağlı geri çağrı parametresi alan bir işleviniz varsa, hiçbir şey yapmayan varsayılan bir geri çağrı sağlayabilirsiniz:

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

1

Bu ise anlamına gelir xayarlanır değeri zolacaktır x, aksi takdirde, ydaha sonra değeri olarak ayarlanır ayarlanır z'in değeri.

aynı

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

JavaScript'teki mantıksal işleçler boole değerlerini döndürmediğinden, ancak işlemi tamamlamak için gereken son öğenin değeri (VEYA cümlesinde ilk yanlış olmayan değer olur, VE cümlesinde sonuncusu olur) ). İşlem başarısız olursa falseiade edilir.


5
Bu yanlış! eğer (x) {z = x; } else {z = y;} ilk değer yanlışsa, değerin gerçekte ne olduğuna bağlı olarak her zaman ikinci değer atanır.
evilpie

Bunun dışında, x yanlışsa sadece y'den z'ye atadığını düşünüyorum . Tabii ki, FF'de benim için bu şekilde çalışıyor, bu da uygulamaya bağlı olabilir.
tvanfosson

7
Yanlış döndürme ile ilgili son bölüm doğru değildir (cinas amaçlanmamıştır). İlk değer falsey ise, ||operatör doğru olup olmamasına bakılmaksızın ikinci değeri döndürür.
Matthew Crumley

-1. Eşdeğer kod snippet'iniz doğrudur, ancak önemli olan nokta, bu zdeğerin doğru xolup olmadığı değerine ayarlanmasıdır . Aksi takdirde değerine ayarlanır y. Bu x, örneğin, 0veya boş dizeye ayarlanırsa, ""söylediğiniz şeyi yapmaz, çünkü bu değerler yanlıştır .
Daniel Cassidy

1

Kısa devre operatörü denir.

Kısa devre değerlendirmesi, ikinci argümanın yalnızca ilk argüman ifadenin değerini belirlemek için yeterli olmadığında yürütüldüğünü veya değerlendirildiğini söylüyor. OR (||) işlevinin ilk bağımsız değişkeni true olarak değerlendirildiğinde, genel değer true olmalıdır.

İşlev argümanı için varsayılan bir değer ayarlamak için de kullanılabilir.

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

X'i değerlendirecek ve X boş değilse, boş dize veya 0 (mantıksal yanlış), o zaman z'ye atayacaktır. X null, boş dize veya 0 (mantıksal yanlış) ise, y'ye z değerini atayacaktır.

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

'Bob' çıktısı verir;


Ne demek istediğinizi 'boş' olarak netleştirmelisiniz. Boş dizeler zorlanır false, ancak boş diziler veya nesneler zorlanır true.
Daniel Cassidy

@Daniel "boş, boş veya 0" - boş, diziler ve nesneler için geçerli olur. Ancak alınan nokta.
tvanfosson

0

Göre Bill Higgins'ın blog yazı; Javascript mantıksal VEYA atama deyimi (Şubat 2007), bu davranış v1.2'den itibaren geçerlidir (en azından)

Ayrıca bunun için başka bir kullanım önermektedir (alıntılanmıştır): " tarayıcılar arası farklılıkların hafif normalleştirilmesi "

// determine upon which element a Javascript event (e) occurred
var target = /*w3c*/ e.target || /*IE*/ e.srcElement;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.