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).

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.


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
}

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 ||.


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


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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.