--- 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.
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
See PR #1482 regarding the addition of this example.
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. |
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
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
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'"
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!"
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.
| Specification |
|---|
| {{SpecName('ESDraft', '#prod-Nulli', 'nullish coalescing expression')}} |
{{Compat("javascript.operators.nullish_coalescing")}}