Zastąp wartość, jeśli null lub undefined w JavaScript

128

Mam wymóg zastosowania ??operatora C # do JavaScript i nie wiem jak. Rozważ to w C #:

int i?=null;
int j=i ?? 10;//j is now 10

Teraz mam to ustawione w JavaScript:

var options={
       filters:{
          firstName:'abc'
       } 
    };
var filter=options.filters[0]||'';//should get 'abc' here, it doesn't happen
var filter2=options.filters[1]||'';//should get empty string here, because there is only one filter

Jak mam to zrobić poprawnie?

Dzięki.

EDYCJA: zauważyłem połowę problemu: nie mogę używać notacji „indeksatora” do obiektów ( my_object[0]). Czy jest sposób, aby to ominąć? (Nie znam wcześniej nazw właściwości filtrów i nie chcę ich iterować).

Walentyna Wasiljewa
źródło

Odpowiedzi:

271

Oto odpowiednik JavaScript:

var i = null;
var j = i || 10; //j is now 10

Zauważ, że operator logiczny|| nie zwraca wartości logicznej, ale pierwszą wartość, którą można przekonwertować na wartość true .

Dodatkowo użyj tablicy obiektów zamiast jednego pojedynczego obiektu:

var options = {
    filters: [
        {
            name: 'firstName',
            value: 'abc'
        }
    ]
};
var filter  = options.filters[0] || '';  // is {name:'firstName', value:'abc'}
var filter2 = options.filters[1] || '';  // is ''

Dostęp do tego można uzyskać za pomocą indeksu.

Gumbo
źródło
57
Zauważ, że to nie zadziała, jeśli 0 jest prawidłową wartością i.
jt000
13
Jeśli coś falsey jest potencjalnie ważne wejściowego ( 0, false, pusty ciąg znaków), chciałbym zrobić coś takiego zamiast: var j = (i === null) ? 10 : i;Który będzie tylko wymienić null, niż cokolwiek, co można ocenić na false.
DBS
Czy istnieje odpowiednik tego w Groovy?
user6123723
jeśli ijest niezdefiniowana, spowoduje to błąd. wydaje mi się bezużyteczne, więc ... (?)
phil294
@ phil294 var j = (i != null ? i : 10);powinno działać, ponieważ undefinedjest ==null, więc i != nulljest falsedla obu nulli undefined.
ToolmakerSteve
6

Zauważyłem połowę problemu: nie mogę używać notacji „indeksator” do obiektów (my_object [0]). Czy jest sposób, aby to ominąć?

Nie; literał obiektu, jak sama nazwa wskazuje, jest obiektem , a nie tablicą, więc nie można po prostu pobrać właściwości na podstawie indeksu, ponieważ nie ma określonej kolejności ich właściwości. Jedynym sposobem na pobranie ich wartości jest użycie określonej nazwy:

var someVar = options.filters.firstName; //Returns 'abc'

Lub iterując je za pomocą for ... inpętli:

for(var p in options.filters) {
    var someVar = options.filters[p]; //Returns the property being iterated
}
Alex Różański
źródło
1
@LinusGeffarth Zauważ, że ta zabawna for inpętla JS działa tylko na literałach obiektów! Zawodzi żałośnie na tablicach JS (daje indeks) i mapach JS (daje undefined). Mam nadzieję, że o tym nie zapomnisz, aby nie zaskoczyć Cię debugowanie! xP
varun
4

Odpowiedź ES2020

Nowy Nullish Coalescing Operator jest wreszcie dostępny w JavaScript, chociaż obsługa przeglądarek jest ograniczona. Według danych caniuse obsługiwanych jest tylko 48,34% przeglądarek (stan na kwiecień 2020).

Zgodnie z dokumentacją

Nullish łączący operator (??) jest operatorem logicznym, który zwraca swój prawostronny operand, gdy jego lewostronny operand ma wartość null lub jest niezdefiniowany, aw przeciwnym razie zwraca operand po lewej stronie.

const options={
  filters:{
    firstName:'abc'
  } 
};
const filter = options.filters[0] ?? '';
const filter2 = options.filters[1] ?? '';

Zapewni to, że obie zmienne będą miały wartość zastępczą ''if filters[0]lub filters[1]nulllub undefined.

Zwróć uwagę, że zerowy operator łączenia nie zwraca wartości domyślnej dla innych typów fałszywych wartości, takich jak 0i ''. Jeśli chcesz uwzględnić wszystkie fałszywe wartości, powinieneś użyć operatora OR ||.

Wentjun
źródło
0

Logiczne przypisanie zerowe, rozwiązanie 2020+

Nowy operator jest obecnie dodawany do przeglądarek ??=. Jest to równoważne z value = value ?? defaultValue.

||=a &&=także będą dostępne, linki poniżej.

Sprawdza, czy lewa strona jest niezdefiniowana lub zerowa, zwarcie, jeśli jest już zdefiniowane. Jeśli nie, lewej stronie przypisywana jest wartość po prawej stronie.

Podstawowe przykłady

let a          // undefined
let b = null
let c = false

a ??= true  // true
b ??= true  // true
c ??= true  // false

// Equivalent to
a = a ?? true

Przykłady obiektów / tablic

let x = ["foo"]
let y = { foo: "fizz" }

x[0] ??= "bar"  // "foo"
x[1] ??= "bar"  // "bar"

y.foo ??= "buzz"  // "fizz"
y.bar ??= "buzz"  // "buzz"

x  // Array [ "foo", "bar" ]
y  // Object { foo: "fizz", bar: "buzz" }

Przykład funkcjonalny

function config(options) {
    options.duration ??= 100
    options.speed ??= 25
    return options
}

config({ duration: 555 })   // { duration: 555, speed: 25 }
config({})                  // { duration: 100, speed: 25 }
config({ duration: null })  // { duration: 100, speed: 25 }

?? = Obsługa przeglądarek, lipiec 2020 r. - 0,03%

?? = Dokumentacja Mozilli

|| = Dokumentacja Mozilli

&& = Dokumentacja Mozilli

Gibolt
źródło
0

Rozwiązanie niszczące

Treść pytania mogła się zmienić, więc postaram się dokładnie odpowiedzieć.

Destrukturyzacja pozwala wyciągać wartości z wszystkiego, co ma właściwości. Można również zdefiniować wartości domyślne, gdy null / undefined oraz aliasy nazw.

const options = {
    filters : {
        firstName : "abc"
    } 
}

const {filters: {firstName = "John", lastName = "Smith"}} = options

// firstName = "abc"
// lastName = "Smith"

UWAGA: wielkość liter ma znaczenie

Jeśli pracujesz z tablicą, oto jak to zrobić.

W tym przypadku nazwa jest wyodrębniana z każdego obiektu w tablicy i otrzymuje własny alias. Ponieważ obiekt mógł nie istnieć, = {}został również dodany.

const options = {
    filters: [{
        name: "abc",
        value: "lots"
    }]
}

const {filters:[{name : filter1 = "John"} = {}, {name : filter2 = "Smith"} = {}]} = options

// filter1 = "abc"
// filter2 = "Smith"

Bardziej szczegółowy samouczek

Wsparcie przeglądarek 92% lipiec 2020

Gibolt
źródło