Reemplazar un valor si es nulo o indefinido en JavaScript

128

Tengo el requisito de aplicar el ??operador C # a JavaScript y no sé cómo. Considere esto en C #:

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

Ahora tengo esta configuración en 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

¿Cómo lo hago correctamente?

Gracias.

EDITAR: Descubrí la mitad del problema: no puedo usar la notación 'indexador' para los objetos ( my_object[0]). ¿Hay alguna forma de evitarlo? (No sé los nombres de las propiedades de los filtros de antemano y no quiero iterar sobre ellos).

Valentin Vasilyev
fuente

Respuestas:

271

Aquí está el equivalente de JavaScript:

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

Tenga en cuenta que el operador lógico|| no devuelve un valor booleano, sino el primer valor que se puede convertir a verdadero .

Además, use una matriz de objetos en lugar de un solo objeto:

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

Se puede acceder a él mediante index.

Gumbo
fuente
57
Tenga en cuenta que esto no funciona si 0 es un valor válido de i.
jt000
13
En todo caso Falsey- es una entrada potencialmente válidas ( 0, false, cadena vacía), me gustaría hacer algo como esto en su lugar: var j = (i === null) ? 10 : i;Lo que sólo reemplazará null, en lugar de algo que puede ser evaluada a falso.
DBS
¿Hay un equivalente para esto en Groovy?
user6123723
si ino está definido, arrojará un error. me parece inútil así .. (?)
phil294
@ phil294 var j = (i != null ? i : 10);debería funcionar, porque undefinedes ==nulo, también lo i != nulles falsepara ambos nully undefined.
ToolmakerSteve
6

Descubrí la mitad del problema: no puedo usar la notación 'indexador' para los objetos (my_object [0]). ¿Hay alguna forma de evitarlo?

No; un objeto literal, como su nombre lo indica, es un objeto y no una matriz, por lo que no puede simplemente recuperar una propiedad basada en un índice, ya que no existe un orden específico de sus propiedades. La única forma de recuperar sus valores es usando el nombre específico:

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

O iterando sobre ellos usando el for ... inciclo:

for(var p in options.filters) {
    var someVar = options.filters[p]; //Returns the property being iterated
}
Alex Rozanski
fuente
1
@LinusGeffarth Tenga en cuenta que este divertido for inbucle JS solo funciona en literales de objeto. Falla miserablemente en matrices JS (da índice) y JS Maps (da undefined). Espero que no lo olvide, ¡no sea que se encuentre con una sorpresa de depuración! xP
varun
4

Respuesta ES2020

El nuevo Nullish Coalescing Operator finalmente está disponible en JavaScript, aunque el soporte del navegador es limitado. Según los datos de caniuse , solo el 48,34% de los navegadores son compatibles (a abril de 2020).

Según la documentación,

El operador coalescente nulo (??) es un operador lógico que devuelve su operando del lado derecho cuando su operando del lado izquierdo es nulo o indefinido y, de lo contrario, devuelve su operando del lado izquierdo.

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

Esto asegurará que ambas variables tengan un valor de respaldo de ''si filters[0]o filters[1]son null, o undefined.

Tenga en cuenta que el operador de fusión nula no devuelve el valor predeterminado para otros tipos de valores falsos como 0y ''. Si desea contabilizar todos los valores falsos, debe utilizar el operador OR ||.

fuejun
fuente
0

Asignación de anulación lógica, solución 2020+

Actualmente se está añadiendo un nuevo operador para los navegadores, ??=. Esto es equivalente avalue = value ?? defaultValue .

||= y &&= también vienen, enlaces a continuación.

Esto verifica si el lado izquierdo está indefinido o es nulo, en cortocircuito si ya está definido. De lo contrario, al lado izquierdo se le asigna el valor del lado derecho.

Ejemplos 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

Ejemplos de objetos / matrices

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

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

?? = Soporte del navegador julio de 2020 - .03%

?? = Documentación de Mozilla

|| = Documentación de Mozilla

&& = Documentación de Mozilla

Gibolt
fuente
0

Solución de desestructuración

Es posible que el contenido de la pregunta haya cambiado, así que intentaré responder de manera exhaustiva.

La desestructuración le permite extraer valores de cualquier cosa con propiedades. También puede definir valores predeterminados cuando es nulo / no definido y alias de nombre.

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

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

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

NOTA: La capitalización importa

Si trabaja con una matriz, así es como lo hace.

En este caso, el nombre se extrae de cada objeto de la matriz y se le asigna su propio alias. Dado que el objeto podría no existir = {}, también se agregó.

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

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

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

Tutorial más detallado

Compatibilidad con navegadores 92% julio de 2020

Gibolt
fuente