--- title: Operator null'owego scalania (??) slug: Web/JavaScript/Reference/Operators/Nullish_coalescing_operator tags: - JavaScript - Language feature - Operator - Reference - nullish coalescing translation_of: Web/JavaScript/Reference/Operators/Nullish_coalescing_operator original_slug: Web/JavaScript/Referencje/Operatory/Nullish_coalescing_operator ---

{{JSSidebar("Operators")}}

Operator null'owego scalania (??) - to operator logiczny, stosowany w wyrażeniach, który zwraca to co jest po jego lewej stronie, tak długo, jak to nie jest null, albo undefined, wtedy zwraca to, co jest po prawej.

Początkowo ewaluowane jest tylko wyrażenie z lewej strony.
Dopiero, gdy zachodzi taka potrzeba, ewaluowane jest prawe wyrażenie.

Jest podobny do logicznego operatora LUB (||)Logical OR (||) ), ale LUB decyduje o tym, czy wziąć prawą wartość, na innej podstawie:
Czy lewa wartość jest fałszopodobna (Falsy)?
null i undefined są fałszopodobne, ale sęk w tym, że nie tylko one, ale również np. 0, czy "". Czasem nie chce się podmieniać niczego za 0 i "", uważając je za dopuszczalne wartości.
Wtedy właśnie przydaje się ten operator.

{{EmbedInteractiveExample("pages/js/expressions-nullishcoalescingoperator.html")}}

Składnia

LWyr ?? PWyr
Pole Opis
LWyr Wyrażenie główne, ewaluowane na początku.
Jeżeli jego wartość wynikowa jest null, albo undefined, to nie ona zostanie zwrócona, ale wartość wynikowa wyrażenia PWyr
PWyr Wyrażenie zamienne, ewaluowane, kiedy wartość LWyr jest null, albo undefined.

Przykłady

Użycie operatora

W tym przykładzie użyjemy operatora null'owego scalania do podania zapasowych wartości, przy inicjowaniu stałych:

const wartoscNull = null;
const warA = wartoscNull ?? "domyślne dla A";
console.log(warA);

// konsola: "domyślne dla A"



const pustyTekst = "";   // fałszopodobny
const warB = pustyTekst ?? "domyślne dla B";
console.log(warB);

// konsola: ""
// ponieważ "??" reaguje tylko konkretnie na null albo undefined



const jakasLiczba = 42;
const warC = jakasLiczba ?? 0;
console.log(warC);

// konsola: 42

Porównanie działania "??" i "||"

Wcześniej przed pojawieniem się tego operatora, używano LUB (||) (Logical OR (||)):

let liczba;
let zabezpLicz = liczba || 1;
// zmienna "wejscie" nie była nigdy zapełniona żadną wartością,
// więc była "undefined", a undefined jest fałszopodobne, więc
// JavaScript wziął zapasowe '1'.

console.log(2 * zabezpLicz);
// konsola: 2

To działa, ale...
przez to jakim operatorem jest LUB, nie tylko undefined zostanie tu zamienione, ale też i 0, które, w kontekście tego przykładu, powiedzmy, że jest wartością, która powinna być ok:

let liczba = 0;
let zabezpLicz = liczba || 1;
// zmienna "wejscie" została zapełniona zerem, ale jest fałszopodobne,
//więc JavaScript wziął zapasowe '1'.

console.log(2 * zabezpLicz);
// konsola: 2
// chcieliśmy: 0

Operator null'owego scalania rozwiązuje ten problem:

let liczba = 0;
let zabezpLicz = liczba ?? 1;
// zmienna "wejscie" została zapełniona zerem,
//mimo tego, że jest fałszopodobne, "??" akceptuje je, bo to nie null, ani undefined, i
//JavaScript zostawia '0'.

console.log(2 * zabezpLicz);
// konsola: 0

Pomijanie ewaluacji

Podobnie jak inne operatory logiczne LUB (Logical OR (||)) i I (Logical AND (&&)), ten operator rozpoczyna od ewaluacji wyrażenia po lewej stronie, i dopiero gdy trzeba, zajmuje się prawą stroną:

function A(){
  console.log("Tu A!");
  return false;
}
function B(){
  console.log("Tu B!");
  return true;
}

if( A() ?? B() ) console.log("Otrzymano 'true'");
else console.log("Otrzymano 'false'");
// konsola: "Otrzymano 'false'"

i :

function A(){
  console.log("Tu A!");
  return null; // teraz tu jest zwracany null, na który reaguje "??"
}
function B(){
  console.log("Tu B!");
  return true;
}

if( A() ?? B() ) console.log("Otrzymano 'true'");
else console.log("Otrzymano 'false'");
// konsola: "Otrzymano 'true'"

Nie działa seryjnie, ani z LUB, ani z I

W wyrażeniach, nie można stawiać zwyczajnie operatora null'owego scalania w otoczeniu operatorów LUB i I, mimo ustalonej kolejności wykonywania działań. Będzie to odbierane jako błąd składniowy:

null || undefined ?? "yyy..."; // to będzie SyntaxError
true || undefined ?? "aha.";   // to też będzie SyntaxError
//bo tu chodzi o to, że jest "||" i "??" razem, nie o wartości.

Trzeba je rozdzielić nawiasami:

(null || undefined) ?? "yyy...";  // zwraca: "yyy..."
null || (undefined ?? "działa!"); // zwraca: "działa!"

Odniesienie do Operatora opcjonalnego dostępu "?."

Sposób w który operator null'owego scalania pracuje z wartościami null i undefined, jest intuicyjny analogicznie u operatora opcjonalnego dostępu (Optional chaining (?.), i razem pozwalają na ciekawe akcje, np.:

class objekt{
  tekst;

  constructor(tekst = null){
    this.tekst = tekst;
  }

  odczytTekst(){
    return this.tekst;
  }
  wpisTekst(w){
    this.tekst = w;
    return true;
  }
}

let objekty = [new objekt("cześć!"), null, new objekt()];



// zadanie kodu: zamień tekst'y w objekt'ach na duże litery,
// używając funkcji dostępu, a pozostawiając puste wartości
// bez zmian


// wersja typeof
for(let i = 0; i < objekty.length; i++)
  if(typeof(objekty[i]) == "object")
    if(typeof(objekty[i].odczytTekst()) == "string")
      objekty[i].wpisTekst(objekty[i].odczytTekst().toUpperCase());


// wersja operatorów "??" i "?."
for(let i = 0; i < objekty.length; i++)
  objekty[i]?.wpisTekst(objekty[i]?.odczytTekst()?.toUpperCase() ?? null);

console.log(objekty);

Czasami użycie tych operatorów upraszcza kod.
Poza tym każda funkcja jest wywoływana najwyżej raz i może to być co kolwiek.

Specyfikacje

Specification
{{SpecName('ESDraft', '#prod-Nulli', 'nullish coalescing expression')}}

Wsparcie przeglądarek

{{Compat("javascript.operators.nullish_coalescing")}}

Zobacz też...