Substitua um valor se nulo ou indefinido em JavaScript

128

Tenho um requisito para aplicar o ??operador C # ao JavaScript e não sei como. Considere isso em C #:

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

Agora eu tenho isso configurado em 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

Como faço isso corretamente?

Obrigado.

Edição: Encontrei metade do problema: não posso usar a notação 'indexador' para objetos ( my_object[0]). Existe uma maneira de contorná-lo? (Não conheço os nomes das propriedades dos filtros de antemão e não quero iterá-los).

Valentin Vasilyev
fonte

Respostas:

271

Aqui está o equivalente a JavaScript:

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

Observe que o operador lógico|| não retorna um valor booleano, mas o primeiro valor que pode ser convertido em true .

Além disso, use uma matriz de objetos em vez de um único objeto:

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

Isso pode ser acessado por índice.

quiabo
fonte
56
Observe que isso não funciona se 0 for um valor válido de i.
jt000
13
Se alguma coisa Falsey é uma entrada potencialmente válidos ( 0, false, string vazia), eu faria algo parecido com isso em vez disso: var j = (i === null) ? 10 : i;Que só irá substituir null, em vez de qualquer coisa que pode ser avaliada como falsa.
DBS
Existe um equivalente para isso no Groovy?
user6123723
se ifor indefinido, isso gerará um erro. parece inútil para mim assim .. (?)
phil294
@ phil294 var j = (i != null ? i : 10);deve funcionar, porque undefinedé ==nulo, assim i != nullcomo falsepara ambos nulle undefined.
Home
6

Vi metade do problema: não posso usar a notação 'indexador' para objetos (meu_objeto [0]). Existe uma maneira de contorná-lo?

Não; um objeto literal, como o nome indica, é um objeto , e não uma matriz, portanto, você não pode simplesmente recuperar uma propriedade com base em um índice, pois não há uma ordem específica de suas propriedades. A única maneira de recuperar seus valores é usando o nome específico:

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

Ou iterando sobre eles usando o for ... inloop:

for(var p in options.filters) {
    var someVar = options.filters[p]; //Returns the property being iterated
}
Alex Rozanski
fonte
1
@LinusGeffarth Observe que esse for inloop JS engraçado funciona apenas em literais de objetos! Ele falha miseravelmente em matrizes JS (fornece índice) e JS Maps (dá undefined). Espero que você não esqueça disso, para que não tenha uma surpresa de depuração! xP
varun
4

ES2020 Resposta

O novo Nullish Coalescing Operator está finalmente disponível no JavaScript, embora o suporte ao navegador seja limitado. De acordo com os dados da caniuse , apenas 48,34% dos navegadores são suportados (a partir de abril de 2020).

De acordo com a documentação,

O operador coalescente nulo (??) é um operador lógico que retorna seu operando do lado direito quando o operando do lado esquerdo é nulo ou indefinido e, de outro modo, retorna seu operando do lado esquerdo.

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

Isso garantirá que ambas as suas variáveis ​​tenham um valor de fallback de ''if filters[0]ou filters[1]are null, ou undefined.

Observe que o operador coalescente nulo não retorna o valor padrão para outros tipos de valor falso, como 0e ''. Se você deseja contabilizar todos os valores falsos, deve estar usando o operador OR ||.

fui
fonte
0

Designação nula lógica, solução 2020+

Um novo operador está sendo adicionado aos navegadores ??=,. Isso é equivalente avalue = value ?? defaultValue .

||=e &&=também estão chegando, links abaixo.

Isso verifica se o lado esquerdo está indefinido ou nulo, em curto-circuito, se já definido. Caso contrário, o lado esquerdo recebe o valor do lado direito.

Exemplos básicos

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

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

// Equivalent to
a = a ?? true

Exemplos de objeto / matriz

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

Exemplo funcional

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 }

?? = Suporte do navegador julho de 2020 - 0,03%

?? = Documentação Mozilla

|| = Documentação Mozilla

&& = Documentação Mozilla

Gibolt
fonte
0

Solução de desestruturação

O conteúdo da pergunta pode ter sido alterado, então tentarei responder completamente.

A reestruturação permite extrair valores de qualquer coisa com propriedades. Você também pode definir valores padrão quando nulos / indefinidos e aliases de nome.

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

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

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

NOTA: A capitalização é importante

Se estiver trabalhando com uma matriz, eis como você faz isso.

Nesse caso, o nome é extraído de cada objeto na matriz e recebe seu próprio alias. Como o objeto pode não existir, = {}também foi adicionado.

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

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

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

Tutorial mais detalhado

Suporte do navegador 92% julho de 2020

Gibolt
fonte