javascript - operator - operadores ternarios php
Acceso a la propiedad nulo-seguro(y asignaciĆ³n condicional) en ES6/2015 (10)
¿Hay un operador de acceso a propiedad
null
seguro (propagación / existencia nula) en ES6 (ES2015 / JavaScript.next / Harmony) como
?.
en
CoffeeScript
por ejemplo?
¿O está planeado para ES7?
var aThing = getSomething()
...
aThing = possiblyNull?.thing
Esto será más o menos como:
if (possiblyNull != null) aThing = possiblyNull.thing
Idealmente, la solución no debería asignar (incluso
undefined
) a
aThing
si
possiblyNull
aThing
es
null
Alternativa de vainilla para acceso seguro a la propiedad
(((a.b || {}).c || {}).d || {}).e
La asignación condicional más concisa probablemente sería esta
try { b = a.b.c.d.e } catch(e) {}
No es tan bueno como el? operador, pero para lograr un resultado similar podría hacer:
user && user.address && user.address.postcode
Dado que
null
e
undefined
son valores
falsos
(
consulte esta referencia
), la propiedad después del operador
&&
solo se accede si el precedente no es nulo o indefinido.
Alternativamente, podría escribir una función como esta:
function _try(func, fallbackValue) {
try {
var value = func();
return (value === null || value === undefined) ? fallbackValue : value;
} catch (e) {
return fallbackValue;
}
}
Uso:
_try(() => user.address.postcode) // return postcode or undefined
O, con un valor de reserva:
_try(() => user.address.postcode, "none") // return postcode or a custom string
No, no hay operador de propagación nulo en ES6. Tendrá que ir con uno de los patrones conocidos .
Sin embargo, puede utilizar la desestructuración:
({thing: aThing} = possiblyNull);
Hay muchas discusiones (por ejemplo, this ) para agregar un operador de este tipo en ES7, pero ninguna realmente despegó.
No. Puede usar lodash#get o algo así para esto en JavaScript.
Pensé que esta pregunta necesitaba un poco de actualización para 2018. Esto se puede hacer muy bien sin ninguna biblioteca que use
Object.defineProperty()
y se puede usar de la siguiente manera:
Object.defineProperty(Object.prototype, ''safeGet'', {
enumerable: false,
writable: false,
value: function(p) {
return p.split(''.'').reduce((acc, k) => {
if (acc && k in acc) return acc[k];
return undefined;
}, this);
}
});
Considero que esto es seguro (y js-ético) debido a las definiciones
writeable
y
enumerable
ahora disponibles para el método
defineProperty
de
Object
, como se
documenta en MDN
definición de la función a continuación:
Object.defineProperty(Object.prototype, ''safeGet'', { enumerable: false, writable: false, value: function(p) { return p.split(''.'').reduce((acc, k) => { if (acc && k in acc) return acc[k]; return undefined; }, this); } });
He reunido un jsBin con salida de consola para demostrar esto. Tenga en cuenta que en la versión jsBin también he agregado una excepción personalizada para valores vacíos. Esto es opcional, por lo que lo he dejado fuera de la definición mínima anterior.
Las mejoras son bienvenidas
Sé que esta es una pregunta de JavaScript, pero creo que Ruby maneja esto de todas las formas solicitadas, por lo que creo que es un punto de referencia relevante.
.&
,
try
, y && tienen sus puntos fuertes y posibles dificultades.
Un gran resumen de esas opciones aquí:
http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/
TLDR;
La conclusión de Rubyists es que
dig
es más fácil para los ojos y una garantía más fuerte de que se asignará
un valor
o
null
.
Aquí hay una implementación simple en TypeScript:
a = dig(b, ''c'', ''d'', ''e'');
foo = () => ({});
bar = dig(a, foo, ''b'', ''c'')
Esto se puede usar para cualquier profundidad de anidamiento y funciones de manejo.
myVariable.safeGet(''propA.propB.propC'');
El enfoque de
try
es igualmente agradable de leer en JS, como se muestra en las respuestas anteriores.
Tampoco requiere bucles, lo cual es un inconveniente de esta implementación.
Un método seguro de obtención profunda parece un ajuste natural para underscore.js, pero el problema es evitar la programación de cadenas. Modificando la respuesta de @ Felipe para evitar la programación de cadenas (o al menos retrasa los casos límite a la persona que llama):
function safeGet(obj, props) {
return (props.length==1) ? obj[keys[0]] :safeGet(obj[props[0]], props.slice(1))
}
Ejemplo:
var test = {
a: {
b: ''b property value'',
c: { }
}
}
safeGet(test, [''a'', ''b''])
safeGet(test, "a.b".split(''.''))
Yendo por la lista here , actualmente no hay una propuesta para agregar un recorrido seguro a Ecmascript. Entonces, no solo no hay una buena manera de hacer esto, sino que no se agregará en el futuro previsible.
Actualización (2019-06-27): Parece que la gente todavía está encontrando esto, aquí está la historia actual:
- Especificación de encadenamiento opcional (Etapa 2): https://github.com/tc39/proposal-optional-chaining
- Complemento Babel v7: https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining
Actualización (2017-08-01): si desea utilizar un complemento oficial, puede probar la versión alfa de Babel 7 con la nueva transformación. Su experiencia puede ser diferente
https://www.npmjs.com/package/babel-plugin-transform-optional-chaining
Original :
Una característica que logra que se encuentra actualmente en la etapa 1: encadenamiento opcional.
https://github.com/tc39/proposal-optional-chaining
Si desea usarlo hoy, hay un complemento de Babel que lo logra.
export function dig(target: any, ...keys: Array<string>): any {
let digged = target
for (const key of keys) {
if (typeof digged === ''undefined'') {
return undefined // can also return null or a default value
}
if (typeof key === ''function'') {
digged = key(digged)
} else {
digged = digged[key]
}
}
return digged
}