JavaScript'te “boş birleştirme” operatörü var mı?


1381

Javascript'te boş bir birleştirme operatörü var mı?

Örneğin, C #, bunu yapabilirim:

String someString = null;
var whatIWant = someString ?? "Cookies!";

Javascript için anlayabileceğim en iyi yaklaşım koşullu operatörü kullanmaktır:

var someString = null;
var whatIWant = someString ? someString : 'Cookies!';

Hangi sorta icky IMHO. Daha iyisini yapabilir miyim?


31
2018'den not: x ?? ysözdizimi şimdi 1. aşama teklif durumunda - nullish birleştirme
Aprillion

2
Şimdi bu tam sözdizimini içeren bir Babel eklentisi var.
Jonathan Sudiaman

10
2019'dan not: şimdi 3. aşama statüsü!
Daniel Schaffer

3
Ocak 2020'den not: Nullish birleştirme operatörü yerel olarak Firefox 72'de mevcut, ancak isteğe bağlı zincirleme operatörü hala mevcut değil.
Kir Kanos

4
Nullish birleştirme operatörü ( x ?? y) ve isteğe bağlı zincirleme operatörü ( user.address?.street) artık 4. Aşamadır . İşte bunun anlamı hakkında iyi bir açıklama: 4'tür . 2ality.com/2015/11/tc39-process.html#stage-4%3A-finished .
Mass Dot Net

Yanıtlar:


2134

Güncelleme

JavaScript artık nullish birleştirme operatörünü (??) desteklemektedir . Onun sağ tarafı işlenen zaman onun sol tarafı döner işlenen olduğu nullveya undefined, aksi takdirde onun sol taraftaki işlem gören döndürür.

Lütfen kullanmadan önce uyumluluğu kontrol edin.


C # null birleştirme operatörünün ( ??) JavaScript eşdeğeri mantıksal bir OR ( ||) kullanıyor:

var whatIWant = someString || "Cookies!";

Davranışın C # ile eşleşmediği durumlar (aşağıda açıklanmıştır), ancak bu, JavaScript'te varsayılan / alternatif değerler atamanın genel, kısa yoludur.


açıklama

İlk işlenenin türünden bağımsız olarak, bir Boole'ye dönüştürülürse falseatama ikinci işleneni kullanır. Aşağıdaki tüm durumlara dikkat edin:

alert(Boolean(null)); // false
alert(Boolean(undefined)); // false
alert(Boolean(0)); // false
alert(Boolean("")); // false
alert(Boolean("false")); // true -- gotcha! :)

Bunun anlamı:

var whatIWant = null || new ShinyObject(); // is a new shiny object
var whatIWant = undefined || "well defined"; // is "well defined"
var whatIWant = 0 || 42; // is 42
var whatIWant = "" || "a million bucks"; // is "a million bucks"
var whatIWant = "false" || "no way"; // is "false"

48
"False", "undefined", "null", "0", "empty", "deleted" gibi dizelerin tümü, boş olmayan dizeler olduğu için doğrudur.
bazı

4
Bunun açıklığa kavuşturulması gerekiyor. "" boş değil ancak falsey sayılıyor. Bu nedenle, null için bir değer kontrol ediyorsanız ve bu "" olursa, bu testi doğru bir şekilde geçmez.
ScottKoon

99
Dikkat edilmesi ||gereken ilk "truey" değerini veya son "falsey" değerini (hiçbiri true olarak değerlendirilemiyorsa) &&döndürür ve tersi şekilde çalışır: son truey değerini veya ilk falsey değerini döndürmek.
Justin Johnson

19
Hala umurunda olan herkese FYI, bildirmek için türün yapıcısını kullanırsanız 0 ve boş dize null'larla aynı olarak değerlendirilir. var whatIWant = new Number(0) || 42; // is Number {[[PrimitiveValue]]: 0} var whatIWant = new String("") || "a million bucks"; // is String {length: 0, [[PrimitiveValue]]: ""}
Kevin Heidt

5
@LuisAntonioPestana var value = myObj && myObj.property || '', ''myObj veya myObj.property'nin yanlış olması durumunda geri dönecektir.
Ateş Goral

77
function coalesce() {
    var len = arguments.length;
    for (var i=0; i<len; i++) {
        if (arguments[i] !== null && arguments[i] !== undefined) {
            return arguments[i];
        }
    }
    return null;
}

var xyz = {};
xyz.val = coalesce(null, undefined, xyz.val, 5);

// xyz.val now contains 5

bu çözüm SQL birleştirme işlevi gibi çalışır, herhangi bir sayıda bağımsız değişkeni kabul eder ve hiçbirinin değeri yoksa null değerini döndürür. C # gibi davranıyor ?? "", false ve 0 değeri NULL DEĞİLDİR ve dolayısıyla gerçek değerler olarak sayılır. Bir .net arka planından geliyorsanız, bu en doğal duygu çözümü olacaktır.



13
Bu kadar geç bir ekleme için özür dilerim, ama tam olarak not etmek istedim, bu çözümün kısa devre değerlendirmesi olmadığı uyarısı var; argümanlarınız fonksiyon çağrılarıysa , mantıksal OR operatörünün davranışından farklı olan değerlerinin döndürülüp döndürülmediğine bakılmaksızın hepsi değerlendirilecektir.
Haravikk

63

Evet, çok yakında. Bkz burada öneriyi ve burada uygulama durumunu .

Şöyle görünüyor:

x ?? y

Misal

const response = {
  settings: {
    nullValue: null,
    height: 400,
    animationDuration: 0,
    headerText: '',
    showSplashScreen: false
  }
};

const undefinedValue = response.settings?.undefinedValue ?? 'some other default'; // result: 'some other default'
const nullValue = response.settings?.nullValue ?? 'some other default'; // result: 'some other default'
const headerText = response.settings?.headerText ?? 'Hello, world!'; // result: ''
const animationDuration = response.settings?.animationDuration ?? 300; // result: 0
const showSplashScreen = response.settings?.showSplashScreen ?? true; // result: false

2
Şimdi 3. aşamada ve bir sonraki TypeScript sürümü için planlanıyor! github.com/microsoft/TypeScript/issues/26578
lautaro.dragan

1
Nullish birleştirme operatörü ( x ?? y) ve isteğe bağlı zincirleme operatörü ( user.address?.street) artık Aşama 4'tür . Bunun anlamı hakkında iyi bir açıklama: 2ality.com/2015/11/tc39-process.html#stage-4%3A-finished .
Mass Dot Net

45

Eğer ||s 'C # bir yedek olarak ??değil iyi sizin durumunuzda yeterli, o boş dizeleri ve sıfırları yutar, çünkü her zaman kendi işlevi yazabilirsiniz geçerli:

 function $N(value, ifnull) {
    if (value === null || value === undefined)
      return ifnull;
    return value;
 }

 var whatIWant = $N(someString, 'Cookies!');

1
alert (null || '') hala boş bir dize uyarıyor ve bence bu uyarı ('' || 'blah') boş bir dize yerine blah uyarılarını sevdiğimi düşünüyorum - yine de bilmek iyi! (+1)
Daniel Schaffer

1
Ben aslında false(kesinlikle) null / undefined ve trueaksi takdirde - bir mantıksal ile kullanarak döndüren bir işlevi tanımlamayı tercih düşünüyorum ; birçok iç içe fonksiyon çağrısından daha okunabilir olabilir. örneğin $N(a) || $N(b) || $N(c) || ddaha okunabilir $N($N($N(a, b), c), d).
Bob

Brent Larsen'in çözümü daha genel
Assimilater

if .. return .. else ... returnüçlü için mükemmel bir durumdur. return (value === null || value === void 0) ? ifnull : value;
Alex McMillan

15

Burada kimse NaNbenim için de bir sıfır-değer değeri olan potansiyelden bahsetmedi . İki sentimi de ekleyeceğimi düşündüm.

Verilen kod için:

var a,
    b = null,
    c = parseInt('Not a number'),
    d = 0,
    e = '',
    f = 1
;

||İşleci kullanacak olsaydınız, ilk yanlış olmayan değeri alırsınız:

var result = a || b || c || d || e || f; // result === 1

Burada yayınlanan tipik birleştirme yöntemini kullanırsanız c, aşağıdaki değere sahip olacaksınız :NaN

var result = coalesce(a,b,c,d,e,f); // result.toString() === 'NaN'

Bunların hiçbiri benim için doğru görünmüyor. Dünyanızdan farklı olabilecek kendi küçük birleşme mantığı dünyamda, tanımsız, null ve NaN'yi "null-ish" olarak görüyorum. Yani, dbirleştirme yönteminden (sıfır) geri almak için beklenir .

Birinin beyni benim gibi çalışıyorsa ve dışlamak istiyorsanız NaN, bu yöntem bunu başaracaktır:

function coalesce() {
    var i, undefined, arg;

    for( i=0; i < arguments.length; i++ ) {
        arg = arguments[i];
        if( arg !== null && arg !== undefined
            && (typeof arg !== 'number' || arg.toString() !== 'NaN') ) {
            return arg;
        }
    }
    return null;
}

Kodu olabildiğince kısa yapmak ve biraz netlik eksikliği umursamayanlar için bunu @impinball tarafından önerilen şekilde kullanabilirsiniz. Bu, NaN'nin asla NaN'ye eşit olmaması gerçeğinden yararlanır. Burada daha fazla bilgi edinebilirsiniz: NaN neden NaN'ye eşit değil?

function coalesce() {
    var i, arg;

    for( i=0; i < arguments.length; i++ ) {
        arg = arguments[i];
        if( arg != null && arg === arg ) { //arg === arg is false for NaN
            return arg;
        }
    }
    return null;
}

En iyi uygulamalar - bağımsız değişkenleri dizi benzeri olarak ele alın, NaN! == NaN'den yararlanın ( typeof+ num.toString() === 'NaN'gereksizdir), geçerli bağımsız değişkeni değişken yerine depolayın arguments[i].
Isiah Meadows

@impinball, önerilen düzenlemeniz çalışmıyor, test durumumdan 0 (sıfır) yerine NaN döndürüyor. !== 'number'Zaten değil olduğunu değerlendirdiğim için teknik olarak kontrolü kaldırabilirim, nullya da undefinedbu, bu kodu okuyan herkes için çok açık olma avantajına sahiptir ve sipariş ne olursa olsun koşulu çalışır. Diğer önerileriniz kodu biraz kısaltın, bu yüzden bunları kullanacağım.
Kevin Nelson

2
@impinball, önerdiğiniz düzenlemede hatanızı buldum, olarak bıraktınız arg !== arg, ancak olması gerekiyor arg === arg... sonra işe yarıyor. Ancak, ne yaptığınız konusunda çok belirsiz olmanın dezavantajı vardır ... koddan geçen ve arg === arggereksiz olduğunu düşünen bir sonraki kişi tarafından kaldırılmasını önlemek için kodda yorum gerektirir ... ama koyacağım neyse.
Kevin Nelson

İyi yakalama. Ve bu arada, bu NaN! == NaN olgusundan yararlanarak NaN'leri kontrol etmenin hızlı bir yoludur. İsterseniz bunu açıklayabilirsiniz.
Isiah Meadows

1
"bir sayı değil" için kontrol yerleşik bir işlevle değiştirilebilir: isNaN ()
Yury Kozlov

5

null öğesinin JavaScript özel tanımına dikkat edin. javascriptte "değer yok" için iki tanım vardır. 1. Null: Bir değişken null olduğunda, içinde veri içermediği anlamına gelir, ancak değişken kodda zaten tanımlanmıştır. bunun gibi:

var myEmptyValue = 1;
myEmptyValue = null;
if ( myEmptyValue === null ) { window.alert('it is null'); }
// alerts

bu durumda, değişkeninizin türü aslında Nesne'dir. Dene.

window.alert(typeof myEmptyValue); // prints Object
  1. Tanımsız: kodda daha önce bir değişken tanımlanmadığında ve beklendiği gibi herhangi bir değer içermez. bunun gibi:

    if ( myUndefinedValue === undefined ) { window.alert('it is undefined'); }
    // alerts

böyle bir durumda, değişkeninizin türü 'undefined' olur.

tür dönüştüren karşılaştırma işlecini (==) kullanırsanız, JavaScript'in bu boş değerlerin her ikisi için de eşit olarak hareket edeceğini unutmayın. aralarında ayrım yapmak için her zaman yazım katı karşılaştırma işlecini (===) kullanın.


1
Aslında null bir değerdir. Object türünün özel bir değeri. Null değerine ayarlanan bir değişken, veri içerdiği anlamına gelir; veriler null nesnesine bir başvurudır. Kodunuzda tanımsız değerle bir değişken tanımlanabilir. Bu, bildirilmeyen değişken ile aynı değildir.
Ateş Goral

Bildirilen veya bildirilmeyen bir değişken arasındaki gerçek fark: alert (window.test) / * undefined * /; alert (pencerede "test") / * false * /; window.test = tanımsız; alert (window.test) / * tanımsız * /; alert (pencerede "test") / * true * /; için (pencerede var p) {/ * p "test" olabilir * /}
Ateş Goral

1
ancak (biraz paradoksal) tanımlanmamış değeri olan bir değişken tanımlayabilirsinizvar u = undefined;
Serge

@AtesGoral re null. Söylediğiniz doğru olsa da, kural olarak , "null" "(yararlı) verinin yokluğunu " temsil eder . Dolayısıyla "veri yok" olarak kabul edilir. Ve bunun "boş birleştirme operatörü" ile ilgili bir sorunun cevabı olduğunu unutmayalım; bu bağlamda null, dahili olarak nasıl temsil edildiğine bakılmaksızın kesinlikle "veri yok" olarak değerlendirilir.
ToolmakerSteve

4

Açıklamanızı okuduktan sonra @Ates Goral'ın cevabı, JavaScript'te C # ile aynı işlemi nasıl yapacağınızı sağlar.

@ Gumbo'nun cevabı null olup olmadığını kontrol etmenin en iyi yoludur; ancak, farkı dikkat etmek önemlidir ==karşı ===JavaScript özellikle bunun için kontrol konularında geldiğinde undefinedve / veya null.

Buradaki iki terim arasındaki fark hakkında gerçekten iyi bir makale var . Temel olarak, ==bunun yerine kullanırsanız ===, JavaScript'in karşılaştırdığınız değerleri birleştirmeye çalışacağını ve bu birleşmeden sonra karşılaştırmanın sonucunu döndüreceğini anlayın .


Bu makale (ve Jash) hakkında beni rahatsız eden bir şey, tanımsız bir window.hello özelliği herhangi bir nedenle null olarak değerlendiriliyor. Bunun yerine tanımsız olmalıdır. Firefox hata konsolunu deneyin ve kendiniz görün.
Ateş Goral

3

En Tepki Not create-react-apparacı zinciri destekleyen boş-kaynaştırma beri sürümü 3.3.0 (5.12.2019 yayınlandı) . Sürüm notlarından:

Opsiyonel Zincirleme ve Boş Değer Birleştirme Operatörleri

Artık isteğe bağlı zincirleme ve null birleştirme operatörlerini destekliyoruz!

// Optional chaining
a?.(); // undefined if `a` is null/undefined
b?.c; // undefined if `b` is null/undefined

// Nullish coalescing
undefined ?? 'some other default'; // result: 'some other default'
null ?? 'some other default'; // result: 'some other default'
'' ?? 'some other default'; // result: ''
0 ?? 300; // result: 0
false ?? true; // result: false

create-react-appBununla birlikte, 3.3.0+ kullanmanız durumunda, bugün zaten React uygulamalarınızda null-coalesce operatörünü kullanmaya başlayabilirsiniz.


3

Evet ve onun önerisi olan 4. Aşama şimdi. Bu, teklifin resmi ECMAScript standardına dahil edilmeye hazır olduğu anlamına gelir. Chrome, Edge ve Firefox'un son masaüstü sürümlerinde zaten kullanabilirsiniz, ancak bu özellik tarayıcılar arası kararlılığa ulaşana kadar biraz daha beklememiz gerekecek.

Davranışını göstermek için aşağıdaki örneğe bakın:

// note: this will work only if you're running latest versions of aforementioned browsers
const var1 = undefined;
const var2 = "fallback value";

const result = var1 ?? var2;
console.log(`Nullish coalescing results in: ${result}`);

Önceki örnek şuna eşdeğerdir:

const var1 = undefined;
const var2 = "fallback value";

const result = (var1 !== null && var1 !== undefined) ?
    var1 :
    var2;
console.log(`Nullish coalescing results in: ${result}`);

O Not nullish kaynaştırma olacak değil tehdit falsy değerler yolu ||operatör yaptılar (sadece denetler undefinedveya nulldeğerler), dolayısıyla olarak hareket edecek aşağıdaki pasajı şöyle:

// note: this will work only if you're running latest versions of aforementioned browsers
const var1 = ""; // empty string
const var2 = "fallback value";

const result = var1 ?? var2;
console.log(`Nullish coalescing results in: ${result}`);


TypesScript kullanıcıları için, kapalı başlayarak typescript 3.7 , bu özellik şimdi de mevcuttur.


2

Umarım yakında Nisan 2020'den itibaren teklif aşamasında olduğu için Javascript'te kullanıma sunulacaktır. Buradaki durumu uyumluluk ve destek için izleyebilirsiniz - https://developer.mozilla.org/en-US/docs/Web/ JavaScript / Referans / Operatörler / Nullish_coalescing_operator

Typescript kullanan kişiler için kullanabileceğiniz nullish kaynaştırma operatörü gelen typescript 3.7

Dokümanlardan -

Bu özelliği - ??operatör - nullveya ile uğraşırken varsayılan bir değere “geri dönmenin” bir yolu olarak düşünebilirsiniz undefined. Gibi kod yazdığımızda

let x = foo ?? bar();

bu, değerin foo“mevcut” olduğunda kullanılacağını söylemenin yeni bir yoludur ; ama nullya da olduğunda undefined, bar()onun yerine hesaplayın .


0

Tamam doğru cevap

JavaScript'te var mı? Evet öyle. FAKAT. Şu anda itibaren var 2020-02-06 at Sahne 3 ve henüz her yerde desteklenmez. Aşağıdaki URL'deki bağlantıyı izleyin ve nerede olduğu hakkında daha fazla bilgi için "Teknik Özellikler" ve "Tarayıcı uyumluluğu" başlıklarına gidin.

Alıntı: https://developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator

Boş değer birleştirici işleç (??), sol taraftaki işleneni boş veya tanımsız olduğunda sağ taraftaki işleneni döndüren ve aksi takdirde sol taraftaki işleneni döndüren mantıksal bir işleçtir.

Mantıksal OR (||) operatörünün aksine, null veya undefined olmayan bir falsy değeriyse sol işlenen döndürülür. Başka bir deyişle, || başka bir değişken foo için bir varsayılan değer sağlamak için, bazı yanlış değerleri kullanılabilir olarak değerlendirirseniz (ör. '' veya 0) beklenmedik davranışlarla karşılaşabilirsiniz. Daha fazla örnek için aşağıya bakın.

Örnek ister misiniz? Gönderdiğim bağlantıyı takip et, her şeye sahip.


Chrome 80+ sürümünde
nathan

MDN bağlantısı yardımcı olur, ancak bu yinelenen bir yanıttır. Bunun yerine vaughan'ın cevabı altında yorum yapmalısınız.
Chris

@Chris Cevabı yeterli değil, dolayısıyla cevabım.
Karl Morrison

0

Artık Chrome, Edge, Firefox, Safari vb.Gibi büyük tarayıcıların en son sürümünde tam desteğe sahip. İşte boş operatör ve Nullish Birleştirme Operatörü arasındaki karşılaştırma

const response = {
        settings: {
            nullValue: null,
            height: 400,
            animationDuration: 0,
            headerText: '',
            showSplashScreen: false
        }
    };
    /* OR Operator */
    const undefinedValue = response.settings.undefinedValue || 'Default Value'; // 'Default Value'
    const nullValue = response.settings.nullValue || 'Default Value'; // 'Default Value'
    const headerText = response.settings.headerText || 'Hello, world!'; //  'Hello, world!'
    const animationDuration = response.settings.animationDuration || 300; //  300
    const showSplashScreen = response.settings.showSplashScreen || true; //  true
    /* Nullish Coalescing Operator */
    const undefinedValue = response.settings.undefinedValue ?? 'Default Value'; // 'Default Value'
    const nullValue = response.settings.nullValue ?? ''Default Value'; // 'Default Value'
    const headerText = response.settings.headerText ?? 'Hello, world!'; // ''
    const animationDuration = response.settings.animationDuration ?? 300; // 0
    const showSplashScreen = response.settings.showSplashScreen ?? true; //  false
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.