Tengo una estructura de datos como esta:
var someObject = {
'part1' : {
'name': 'Part 1',
'size': '20',
'qty' : '50'
},
'part2' : {
'name': 'Part 2',
'size': '15',
'qty' : '60'
},
'part3' : [
{
'name': 'Part 3A',
'size': '10',
'qty' : '20'
}, {
'name': 'Part 3B',
'size': '5',
'qty' : '20'
}, {
'name': 'Part 3C',
'size': '7.5',
'qty' : '20'
}
]
};
Y me gustaría acceder a los datos usando estas variables:
var part1name = "part1.name";
var part2quantity = "part2.qty";
var part3name1 = "part3[0].name";
part1name debe rellenarse con someObject.part1.name
el valor de, que es "Parte 1". Lo mismo con la cantidad de part2 que se llenó con 60.
¿Hay alguna forma de lograr esto con javascript puro o JQuery?
javascript
jquery
path
nested
Komaruloh
fuente
fuente
var part1name = someObject.part1name;
`Respuestas:
Acabo de hacer esto basado en un código similar que ya tenía, parece funcionar:
Uso::
Vea una demostración en funcionamiento en http://jsfiddle.net/alnitak/hEsys/
EDITAR algunos han notado que este código arrojará un error si se pasa una cadena donde los índices del extremo izquierdo no corresponden a una entrada correctamente anidada dentro del objeto. Esta es una preocupación válida, pero en mi humilde opinión, es mejor abordarla con un
try / catch
bloqueo al llamar, en lugar de hacer que esta función regrese en silencioundefined
para un índice no válido.fuente
_.get(object, nestedPropertyString);
'part3[0].name.iDontExist'
. Agregar una verificación para ver sio
es un objeto en elif in
soluciona el problema. (Cómo lo haces depende de ti). Ver violín actualizado: jsfiddle.net/hEsys/418Esta es la solución que uso:
Ejemplo de uso:
Limitaciones:
[]
) para los índices de matriz, aunque especificar índices de matriz entre el token separador (por ejemplo,.
) funciona bien como se muestra arriba.fuente
_.reduce()
desde la biblioteca de subrayado o lodash)self
probablemente no esté definido aquí. Qué quiere decirthis
?Esto ahora es compatible con lodash usando
_.get(obj, property)
. Ver https://lodash.com/docs#getEjemplo de los documentos:
fuente
_.set(...)
_.get
mostrará el mismo comportamiento que cuando no se encuentra ninguna clave en el objeto proporcionado. por ejemplo_.get(null, "foo") -> undefined
,_.get(null, "foo", "bar") -> "bar"
. Sin embargo, este comportamiento no está definido en los documentos, por lo que está sujeto a cambios.ES6 : Solo una línea en Vanila JS (devuelve nulo si no encuentra en lugar de dar error):
O ejemplo:
Con operador de encadenamiento opcional :
Para una función lista para usar que también reconoce falso, 0 y número negativo y acepta valores predeterminados como parámetro:
Ejemplo a usar:
bono :
Para establecer una ruta (solicitada por @ rob-gordon) puede usar:
Ejemplo:
Acceda a la matriz con [] :
Ejemplo:
fuente
let o = {a:{b:{c:1}}}; let str = 'a.b.c'; str.split('.').splice(0, str.split('.').length - 1).reduce((p,c)=>p&&p[c]||null, o)[str.split('.').slice(-1)] = "some new value";
0
,undefined
ynull
valores.{a:{b:{c:0}}}
vuelve ennull
lugar de0
. Quizás la comprobación explícita de nulos o indefinidos aclarará estos problemas.(p,c)=>p === undefined || p === null ? undefined : p[c]
Reflect.has(o, k) ? ...
(ES6 Reflect.has ) funcionósetPath
establecerá el valor en la primera aparición del último selector. Por ejemplolet o = {}; setPath(o, 'a.a', 0)
resultados en{a: 0}
lugar de{a: {a: 0}}
. Vea esta publicación para una solución.Tendría que analizar la cadena usted mismo:
Esto requiere que también defina índices de matriz con notación de puntos:
Hace que el análisis sea más fácil.
MANIFESTACIÓN
fuente
[]
sintaxis a sintaxis de propiedad es bastante trivial.while (l > 0 && (obj = obj[current]) && i < l)
, este código también funciona para cadenas sin puntos.Funciona para matrices / matrices dentro del objeto también. Defensivo contra valores no válidos.
fuente
usando eval:
ajuste para devolver indefinido en caso de error
http://jsfiddle.net/shanimal/b3xTw/
Utilice el sentido común y la precaución al ejercer el poder de eval. Es un poco como un sable de luz, si lo enciendes hay un 90% de posibilidades de cortar una extremidad. No es para todos.
fuente
Puede lograr obtener el valor de un miembro de objeto profundo con notación de puntos sin ninguna biblioteca externa de JavaScript con el simple truco siguiente:
En su caso para obtener un valor de
part1.name
desdesomeObject
acaba de hacer:Aquí hay una demostración de violín simple: https://jsfiddle.net/harishanchu/oq5esowf/
fuente
Esto probablemente nunca verá la luz del día ... pero aquí está de todos modos.
[]
sintaxis del soporte con.
.
personajeundefined
)fuente
Es un trazador de líneas con lodash.
O mejor...
O la versión ES6 con reducción ...
Plunkr
fuente
Creo que estás pidiendo esto:
Podrías estar preguntando por esto:
Ambos funcionarán
O tal vez estás pidiendo esto
Finalmente podrías estar pidiendo esto
fuente
Split
método, sino más biensplit
.Aquí ofrezco más formas, que parecen más rápidas en muchos aspectos:
Opción 1: dividir cadena en. o [o] o 'o ", revertirlo, omitir elementos vacíos.
Opción 2 (la más rápida de todas, excepto
eval
): escaneo de caracteres de bajo nivel (sin expresión regular / división / etc, solo un escaneo rápido de caracteres). Nota: Este no admite comillas para índices.Opción 3: ( nuevo : la opción 2 se expandió para admitir cotizaciones, un poco más lenta pero aún más rápida)
JSPerf: http://jsperf.com/ways-to-dereference-a-delimited-property-string/3
Sin embargo, "eval (...)" sigue siendo el rey (en cuanto al rendimiento). Si tiene rutas de propiedad directamente bajo su control, no debería haber ningún problema con el uso de 'eval' (especialmente si se desea velocidad). Si tira de rutas de propiedad "sobre el cable" ( en la línea ! Lol: P), entonces sí, use otra cosa para estar seguro. Solo un idiota diría que nunca use "eval" en absoluto, ya que hay buenas razones para usarlo. Además, "se utiliza en el analizador JSON de Doug Crockford ". Si la entrada es segura, entonces no hay ningún problema. Use la herramienta correcta para el trabajo correcto, eso es todo.
fuente
Por si acaso, cualquiera que visite esta pregunta en 2017 o más tarde y busque una forma fácil de recordar , aquí hay una publicación de blog elaborada sobre Acceso a objetos anidados en JavaScript sin ser engañado por
No se puede leer la propiedad 'foo' de error indefinido
Acceda a objetos anidados utilizando Array Reduce
Tomemos este ejemplo de estructura
Para poder acceder a matrices anidadas, puede escribir su propia matriz para reducir la utilidad.
También hay un tipo excelente que maneja el tipo de biblioteca mínimo que hace todo esto por usted.
Con typy, su código se verá así
Descargo de responsabilidad: soy el autor de este paquete.
fuente
AngularJS
El enfoque de Speigg es muy ordenado y limpio, aunque encontré esta respuesta mientras buscaba la solución para acceder a las propiedades de alcance AngularJS $ por ruta de cadena y con una pequeña modificación hace el trabajo:
Simplemente coloque esta función en su controlador raíz y úselo en cualquier ámbito secundario como este:
fuente
$scope.$eval
otra forma de hacerlo con AngularJS.Todavía no he encontrado un paquete para hacer todas las operaciones con una ruta de cadena, así que terminé escribiendo mi propio paquete pequeño y rápido que admite insert (), get () (con retorno predeterminado), set () y eliminar ( ) operaciones.
Puede usar notación de puntos, corchetes, índices numéricos, propiedades de números de cadena y teclas con caracteres que no sean palabras. Uso simple a continuación:
https://www.npmjs.com/package/jsocrud
https://github.com/vertical-knowledge/jsocrud
fuente
Funciona con
fuente
Función simple, que permite una ruta de cadena o matriz.
O
fuente
Ahora hay un
npm
módulo para hacer esto: https://github.com/erictrinh/safe-accessEjemplo de uso:
fuente
Si bien reducir es bueno, me sorprende que nadie lo haya usado para cada uno:
Prueba
fuente
a.b.c
generará una excepción si no hay ninguna propiedadb
en su objeto. Si necesita algo silenciosamente descartando el camino de teclado incorrecto (que no recomiendo), aún puede reemplazar el forEach con estekeys.forEach((key)=> obj = (obj||{})[key]);
Acabo de tener la misma pregunta recientemente y usé con éxito https://npmjs.org/package/tea-properties que también
set
anidaba objetos / matrices:obtener:
conjunto:
fuente
Inspirado por la respuesta de @ webjay: https://stackoverflow.com/a/46008856/4110122
Hice esta función que puede usar para obtener / establecer / desarmar cualquier valor en el objeto
Para usarlo:
fuente
Estoy desarrollando una tienda en línea con React. Traté de cambiar los valores en el objeto de estado copiado para actualizar el estado original con él en el envío. Los ejemplos anteriores no me han funcionado, porque la mayoría de ellos mutan la estructura del objeto copiado. Encontré un ejemplo funcional de la función para acceder y cambiar los valores de las propiedades de objetos anidados profundos: https://lowrey.me/create-an-object-by-path-in-javascript-2/ Aquí está:
fuente
Basado en la respuesta de Alnitak .
Envolví el polyfill en un cheque y reduje la función a una reducción de cadena única.
fuente
Si necesita acceder a diferentes claves anidadas sin saberlo en el momento de la codificación (será trivial abordarlas), puede usar el descriptor de acceso de matriz:
Son equivalentes al descriptor de punto de acceso y pueden variar en tiempo de ejecución, por ejemplo:
es equivalente a
o
Espero que esto aborde tu pregunta ...
EDITAR
No usaré una cadena para mantener una especie de consulta xpath para acceder a un valor de objeto. Como debe llamar a una función para analizar la consulta y recuperar el valor, seguiría otra ruta (no:
o, si está incómodo con el método de aplicación
Las funciones son más cortas, más claras, el intérprete las revisa en busca de errores de sintaxis, etc.
Por cierto, creo que una simple tarea hecha en el momento adecuado será suficiente ...
fuente
Las soluciones aquí son solo para acceder a las claves profundamente anidadas. Necesitaba uno para acceder, agregar, modificar y eliminar las claves. Esto es lo que se me ocurrió:
path_to_key
: ruta en una matriz. Puedes reemplazarlo por tustring_path.split(".")
.type_of_function
: 0 para acceder (no pase ningún valor avalue
), 0 para agregar y modificar. 1 para borrar.fuente
Partiendo de la respuesta de Alnitak:
}
¡Esto también le permite establecer un valor!
También he creado un paquete npm y github con esto
fuente
En lugar de una cadena, se puede usar una matriz que aborde objetos y matrices anidadas, por ejemplo:
["my_field", "another_field", 0, "last_field", 10]
Aquí hay un ejemplo que cambiaría un campo basado en esta representación de matriz. Estoy usando algo así en react.js para campos de entrada controlados que cambian el estado de las estructuras anidadas.
fuente
Basado en una respuesta anterior, he creado una función que también puede manejar paréntesis. Pero no hay puntos dentro de ellos debido a la división.
fuente
fuente
Trabajando con
Underscore
'sproperty
opropertyOf
:Buena suerte...
fuente