--- 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")}}