Yapı x = x || yani?


250

Bazı JavaScript hata ayıklama ve bunun ne olduğunu açıklayamıyorum ||?

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

Birisi bana bir ipucu verebilir var title = title || 'ERROR'mi , bu adam neden kullanıyor ? Bazen bir varaçıklama yapmadan da görüyorum .


44
İnsanlar bunu zaten yanıtladı ... ama falsysadece SADECE değil , ilk değer ise ikinci değerin seçildiğinin farkında olun undefined. Gördüğüm kadar miktar, doWeDoIt = doWeDoIt || truebeni ağlatmak için yeterli. (yani doWeDoItartık asla olmayacak false)
Matt


4
C # tecrübesi olanlar için, çift borulu operatör boş birleştirme operatörüne eşdeğerdir ??. JavaScript boş olmayan nesneleri değerlendirir gibi true (ya da daha iyi evalualtes YANLıŞ nesneleri boş)
usr-yerel-ΕΨΗΕΛΩΝ

3
Kötü hissetme - JS, bu korkunç kodlamaya izin veren tek aptal dildir .... ki ve her işlevi kod satırlarına yerleştirmenin ve onları atıp atılabilir ve 2. kez kullanılamaz hale getirmenin uygun olduğunu öğretir. :) Ben kodlama 30 yıl olduğum ve çok uzun zaman önce JS dokunmadan kapalı tutulur ve ben senin acı tüm hissediyorum söyleyebilirim, "mantıklı değil, sadece JS" cheetsheet kullanışlı tek yolu ben ' ve aldım! :)
Collin Chaffin

1
İçin kabul edilen cevabını değiştirmeyi düşünün lütfen Cevabıma .
Michał Perłakowski

Yanıtlar:


211

Bu, titleargümanın isteğe bağlı olduğu anlamına gelir . Eğer yöntemi argüman olmadan çağırırsanız, varsayılan değeri kullanır "Error".

Yazmak için kısayol:

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

Boole ifadeleriyle bu tür stenografi numaraları Perl'de de yaygındır. İfadesiyle:

a OR b

trueya ada böyle olup olmadığını değerlendirir true. Yani adoğruysa hiç kontrol etmenize gerek yok b. Buna kısa devre boole değerlendirmesi denir:

var title = title || "Error";

temel olarak titledeğerlendirip değerlendirmediğini kontrol eder false. Varsa "geri döner" "Error", aksi takdirde geri döner title.


3
Seçici olduğum için üzgünüm, ancak argüman isteğe bağlı değil, argüman kontrol edildi
themightybun

4
Bu cevap DEĞİLDİR ve son yorumu kabul ediyorum bile isteğe bağlı değil. Perl ifadesi aslında SENSE yapar ve tamamen farklı bir şekilde değerlendirildiğinden, bu cevabın hiçbir kısmı Perl referansında bile doğru değildir. JS okuma / yazma için çok daha kafa karıştırıcı bulduğum çok daha "dönüştürülmüş" boole mantık yönteminde eval olduğunu. Aşağıdaki "Çift boru operatörü nedir" başlıklı cevap aslında doğru bir cevaptır.
Collin Chaffin

198

Çift boru operatörü ( ||) nedir?

Çift boru operatörü ( ||) mantıksal ORoperatördür . Gelen birçok dilde aşağıdaki şekilde çalışır:

  • İlk değer ise false, ikinci değeri kontrol eder. Eğer öyleyse true, geri döner trueve eğer öyleyse false, geri döner false.
  • İlk değer ise true, trueikinci değer ne olursa olsun her zaman geri döner .

Temel olarak bu işlev gibi çalışır:

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

Hala anlamadıysanız, şu tabloya bakın:

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

Diğer bir deyişle, yalnızca her iki değer de yanlış olduğunda yanlıştır.

JavaScript'te farkı nedir?

JavaScript biraz farklıdır, çünkü gevşek yazılan bir dildir . Bu durumda ||, boolean olmayan değerlerle operatörü kullanabileceğiniz anlamına gelir . Bir anlam ifade etmese de, bu operatörü örneğin bir işlev ve bir nesne ile kullanabilirsiniz:

(function(){}) || {}

Orada ne olur?

Değerler boole değilse, JavaScript örtük boole dönüştürür . Bu değer Falsey ise (örneğin, anlamına gelir 0, "", null, undefined(bakınız ayrıca JavaScript Tüm Falsey değerleri , bu olarak kabul edilecektir)) false; Aksi takdirde true.

Dolayısıyla yukarıdaki örnek vermelidir true, çünkü boş işlev doğrudur. Pekala, öyle değil. Boş işlevi döndürür. Çünkü JavaScript'in ||operatörü başlangıçta yazdığım gibi çalışmıyor. Aşağıdaki şekilde çalışır:

  • İlk değer falsey ise , ikinci değeri döndürür .
  • İlk değer doğruysa , ilk değeri döndürür .

Sürpriz? Aslında, geleneksel ||operatör ile "uyumlu" . Aşağıdaki fonksiyon olarak yazılabilir:

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

Eğer bir doğruluk değerini şu şekilde iletirseniz x, geri döner x, yani doğruluk değeri. Yani daha sonra ifyan tümcede kullanırsanız:

(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*/));

olsun "Either x or y is truthy.".

Eğer xfalsey eitherXorYolsaydı , olurdu y. Bu durumda "Either x or y is truthy."eğer if ydoğruydu; aksi halde alırsınız "Neither x nor y is truthy".

Asıl soru

Şimdi, ||operatörün nasıl çalıştığını bildiğinizde, muhtemelen ne anlama x = x || ygeldiğini kendiniz belirleyebilirsiniz . Eğer xtruthy olduğunu xatanan xböylece aslında hiçbir şey olmuyor; Aksi yatanır x. Genellikle işlevlerdeki varsayılan parametreleri tanımlamak için kullanılır. Bununla birlikte, genellikle kötü bir programlama uygulaması olarak kabul edilir , çünkü parametre olarak bir falsey değerini (zorunlu olarak undefinedveya zorunlu değildir null) geçirmenizi önler . Aşağıdaki örneği düşünün:

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

İlk bakışta geçerli görünüyor. Bununla birlikte, parametre falseolarak geçerseniz ne olur flagA(çünkü boole, yani trueveya olabilir false)? Olurdu true. Bu örnekte, ayarlamak için bir yolu yoktur flagAiçin false.

Açıkça olmadığını kontrol etmek daha iyi bir fikir olacağını flagAise undefinedböyle:

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

Daha uzun olmasına rağmen, her zaman çalışır ve anlaşılması daha kolaydır.


ES6 sözdizimini varsayılan işlev parametreleri için de kullanabilirsiniz , ancak eski tarayıcılarda (IE gibi) çalışmadığına dikkat edin. Bu tarayıcıları desteklemek istiyorsanız, kodunuzu Babel ile aktarmanız gerekir .

Ayrıca bkz . MDN'de Mantıksal İşleçler .


13
+1 - açık ara en doğru ve eksiksiz cevap. Ve bu soruya sahip olanlar için (bazılarımız JS dahil yeni emektar kodlayıcılar) kesinlikle bu satırdaki tüm cevaptan en iyi şekilde odaklanmalı: "Anlamsız olsa da" çünkü bu "yazılan loosley" asla mantıklı olmayacak onsuz büyüyen bizlere. Bizim için, bir boolean operatörü tam da budur ve SADECE ...... ve kod yazarken boolean olmayan değerlerin boolean'a tuhaf bir şekilde dönüştürülmesinin durup düşünmesinin iyi bir fikir olacağını kim düşünürse ... , ilaçlarını almayı unuttum o gün! :)
Collin Chaffin

2
Kısacası +1: title = title || 'Error'anlamıif (title) { title = title; } else { title = 'Error'; }
Andre Elrico

Aslında "anlamsız olsa da" çizgisine katılmıyorum. Örneğin, çizginin C'de derlenmeyeceğini anlıyorum, örneğin Ruby'den, hatta Groovy'dan geldiyseniz iyi anlaşılmıştır. Ruby'de bunu daha da kısa olarak ifade edebilirsiniz title ||= 'Error'.
Elliot Nelson

28

Başlık ayarlanmamışsa, varsayılan değer olarak 'ERROR' seçeneğini kullanın.

Daha genel:

var foobar = foo || default;

Okur: Foobar'ı fooveya olarak ayarlayın default. Bunu birçok kez bile zincirleyebilirsiniz:

var foobar = foo || bar || something || 42;

1
Kafa karıştırıcı buldum çünkü değişkenler aynı ada sahip. Yapmadıkları zaman çok daha kolay.
Norbert Norbertson

14

Bunu biraz daha açıklamak gerekirse ...

||Operatör mantıksal-olan oroperatör. İlk kısım doğruysa sonuç doğrudur ve ikinci kısım doğruysa doğrudur ve her iki parça da doğruysa doğrudur. Açıklık için, burada bir tabloda:

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

Şimdi burada bir şey fark ettiniz mi? Eğer Xdoğruysa, sonuç her zaman doğrudur. Yani Xbunun doğru olduğunu bilersek, hiç kontrol etmek zorunda değiliz Y. Böylece birçok dil mantıksal or(ve anddiğer yönden gelen) için "kısa devre" değerlendiricileri uygular . İlk elementi kontrol ederler ve eğer doğruysa ikinciyi kontrol etmekten rahatsız olmazlar. Sonuç (mantıksal terimlerle) aynıdır, ancak ikinci elementin hesaplanması pahalıysa, yürütme açısından potansiyel olarak büyük bir fark vardır.

Peki bunun örneğinizle ne ilgisi var?

var title   = title || 'Error';

Şuna bakalım. titleÖğesi işlevine de geçirilir. JavaScript'te bir parametreyi iletmezseniz, varsayılan olarak null değerine ayarlanır. Ayrıca JavaScript'te değişkeniniz null değerse, mantıksal işleçler tarafından yanlış kabul edilir. Dolayısıyla, bu işlev verilen bir başlık ile çağrılırsa, yanlış olmayan bir değerdir ve bu nedenle yerel değişkene atanır. Bununla birlikte, bir değer verilmezse, null değerdir ve bu nedenle yanlıştır. Mantıksal orişleç daha sonra ikinci ifadeyi değerlendirir ve bunun yerine 'Hata' değerini döndürür. Şimdi yerel değişkene 'Error' değeri verilir.

Bu, JavaScript'te mantıksal ifadelerin uygulanması nedeniyle çalışır. Uygun bir boolean değeri ( trueveya false) döndürmez, bunun yerine bazı kurallar altında neyin eşdeğeri olarak trueneyin eşdeğeri olarak kabul edildiğine ilişkin değeri döndürür false. JavaScript'in boolean bağlamlarında neyin doğru veya yanlış olduğunu düşündüğünü öğrenmek için JavaScript referansınıza bakın.


8

Çift boru mantıksal "VEYA" anlamına gelir. "Parametre ayarlanmadı" durumunda durum böyle değildir, çünkü böyle bir kodunuz varsa kesinlikle javascript'te:

function foo(par) {
}

Sonra arar

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

eşdeğer değildir.

Çift boru (||) ilk argümanı boole olarak verir ve sonuçta boolean doğruysa - ödevi yapın aksi takdirde doğru kısmı atar.

Bu, unset parametresini kontrol ederseniz önemlidir.

Diyelim ki, isteğe bağlı bir parametreye sahip setSalary işlevimiz var. Kullanıcı parametreyi sağlamazsa, varsayılan 10 değeri kullanılmalıdır.

Çeki şu şekilde yaparsanız:

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

Bu, çağrı gibi beklenmedik bir sonuç verecektir.

setSalary(0) 

Yine de yukarıda açıklanan akışı izleyerek 10'u ayarlayacaktır.


8

Temelde || true olarak değerlendirilir, evet ise bu değeri alır, değilse değeri || 'dan sonra alır.

|| değerinden sonra alacağı değerler (hatırladığım kadarıyla):

  • Tanımsız
  • yanlış
  • 0
  • '' (Boş veya Boş dize)

1
yanlış || boş || undefined || 0 || '' || 'null unuttun'
Dziamid

7

Cletus'un cevabı doğru olsa da , JavaScript'te "yanlış olarak değerlendirilir" konusunda daha fazla ayrıntı eklenmesini hissediyorum.

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

Sadece başlık / msg sağlanmış olup olmadığını kontrol etmekle kalmaz , aynı zamanda bunlardan herhangi birinin yanlış olup olmadığını kontrol eder . yani aşağıdakilerden biri:

  • yanlış.
  • 0 (sıfır)
  • "" (boş dize)
  • boş.
  • Tanımsız.
  • NaN (Sayı Değil anlamına gelen özel bir Sayı değeri!)

Yani çizgide

var title = title || 'Error';

Başlık doğruysa (yani, falsy değilse, title = "titleMessage" vb.), Boolean OR (||) operatörü bir 'true' değeri bulur, yani true olarak değerlendirilir, bu nedenle kısa devre yapar ve döner gerçek değer (başlık).

Başlık yanlışsa (örn. Yukarıdaki listeden biri), Boolean OR (||) operatörü bir 'false' değeri bulur ve şimdi operatörün 'true' değerini doğrulayan diğer kısmını değerlendirmesi gerekir ve dolayısıyla geri döndürülür.

Operatörün her iki tarafı da false olarak değerlendirilirse (bazı hızlı firebug konsolu denemelerinden sonra) ikinci 'falsy' operatörünü döndürür.

yani

return ("" || undefined)

undefined değerini döndürürse, büyük olasılıkla bu başlıkta "" varsayılan başlığını / iletisini kullanmaya çalışırken bu soruda sorulan davranışı kullanmanıza olanak tanır. yani koştuktan sonra

var foo = undefined
foo = foo || ""

foo "" olarak ayarlanır


5

çift ​​borulu operatör

bu örnek faydalı mı?

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

Ayrıca olabilir

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

4

Benden önce söylenen herkese bir açıklama eklemek için, size mantıksal kavramları anlamanız için bazı örnekler vermeliyim.

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

Bu, sol taraf gerçek bir ifade olarak değerlendirilirse, tamamlanacağı ve sol tarafın döndürüleceği ve değişkene atanacağı anlamına gelir. diğer durumlarda sağ taraf iade edilir ve atanır.

Ve operatör aşağıdaki gibi zıt bir yapıya sahiptir.

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

3

|| boole OR operatörüdür. JavaScript olduğu gibi, sahte, 0, null tanımsız olarak kabul edilir falsy değerleri.

Bu basitçe

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"

2

Alıntı: "x = x || y yapısı ne anlama geliyor?"

Varsayılan bir değer atama.

Bu , x'in hala değerini beklemesi, ancak henüz almamış olması veya bir varsayılana geri dönmek için kasıtlı olarak atlanması durumunda, y'den x'e varsayılan bir değer sağlamak anlamına gelir .


Yapının kesin anlamı ve tek anlamı budur. Prototipler, bağımsız işlevler ve ayrıca başka bir öğeye uygulanacak ödünç alınmış yöntemler olarak yazı yazma işlevlerinde büyük bir altyordamdı. Ana ve tek görevi, hedefin referansını değiştirmekti. Örnek: function getKeys(x) { x = x || this ; .... }bağımsız bir işlev olarak, prototiplerde bir özellik yöntemi olarak ve başka bir öğeyi `[element] .getKeys (anotherElement) olarak argümanı olarak alabilen bir öğenin yöntemi olarak değiştirilmeden kullanılabilen örnek ;`
Bekim Bacaj

-5

Ve bir şey daha eklemek zorundayım: Bu steno stresi biraz iğrenç. Bir ödevi kontrol etmek için yanlışlıkla yorumlayıcı optimizasyonunu (birincisi doğruysa ikinci işlemle uğraşmamak) kötüye kullanır. Bu kullanımın operatörün amacı ile ilgisi yoktur. Hiç kullanılması gerektiğine inanmıyorum.

Üçlü operatörü başlatma için tercih ederim, örneğin,

var title = title?title:'Error';

Bu, doğru amacı için tek satırlık bir koşullu işlem kullanır. Hala doğrulukla çirkin oyunlar oynuyor, ancak bu sizin için Javascript.

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.