Saltar al contenido

¿Cómo puedo acceder y procesar objetos anidados, matrices o JSON?

Después de de nuestra prolongada compilación de información dimos con la solución este asunto que pueden tener ciertos los usuarios. Te regalamos la solución y nuestro deseo es resultarte de mucha ayuda.

Solución:

Preliminares

JavaScript solo tiene un tipo de datos que puede contener varios valores: Objeto. Un Formación es una forma especial de objeto.

(Sencillo) Los objetos tienen la forma

key: value, key: value, ...

Las matrices tienen la forma

[value, value, ...]

Tanto las matrices como los objetos exponen una key -> value estructura. Claves en un array debe ser numérico, mientras que cualquier string se puede utilizar como key en objetos. los key-los pares de valores también se denominan “propiedades”.

Se puede acceder a las propiedades usando notación de puntos

const value = obj.someProperty;

o notación de corchetes, si el nombre de la propiedad no fuera un nombre de identificador de JavaScript válido [spec], o el nombre es el valor de una variable:

// the space is not a valid character in identifier names
const value = obj["some Property"];

// property name as variable
const name = "some Property";
const value = obj[name];

Por esta razón, array solo se puede acceder a los elementos mediante la notación entre corchetes:

const value = arr[5]; // arr.5 would be a syntax error

// property name / index as variable
const x = 5;
const value = arr[x];

Espera … ¿qué pasa con JSON?

JSON es una representación textual de datos, como XML, YAML, CSV y otros. Para trabajar con tales datos, primero tiene que convertirse a tipos de datos JavaScript, es decir, matrices y objetos (y se acaba de explicar cómo trabajar con ellos). ¿Cómo analizar JSON se explica en la pregunta Analizar JSON en JavaScript? .

Material de lectura adicional

Cómo acceder a matrices y objetos es un conocimiento fundamental de JavaScript y, por lo tanto, es recomendable leer la Guía de JavaScript de MDN, especialmente las secciones

  • Trabajar con objetos
  • Matrices
  • JavaScript elocuente: estructuras de datos


Acceder a estructuras de datos anidadas

Una estructura de datos anidada es una array u objeto que se refiere a otras matrices u objetos, es decir, sus valores son matrices u objetos. Se puede acceder a estas estructuras aplicando consecutivamente la notación de puntos o corchetes.

Aquí hay un ejemplo:

const data = 
    code: 42,
    items: [
        id: 1,
        name: 'foo'
    , 
        id: 2,
        name: 'bar'
    ]
;

Supongamos que queremos acceder al name del segundo elemento.

Así es como podemos hacerlo paso a paso:

Como podemos ver data es un objeto, por lo tanto, podemos acceder a sus propiedades mediante la notación de puntos. los items se accede a la propiedad de la siguiente manera:

data.items

El valor es un array, para acceder a su segundo elemento, tenemos que usar la notación de corchetes:

data.items[1]

Este valor es un objeto y usamos la notación de puntos nuevamente para acceder al name propiedad. Así que finalmente obtenemos:

const item_name = data.items[1].name;

Alternativamente, podríamos haber usado la notación entre corchetes para cualquiera de las propiedades, especialmente si el nombre contenía caracteres que lo habrían invalidado para el uso de la notación de puntos:

const item_name = data['items'][1]['name'];

Estoy intentando acceder a una propiedad pero solo obtengo undefined ¿espalda?

La mayor parte del tiempo cuando se undefined, el objeto/array simplemente no tiene una propiedad con ese nombre.

const foo = bar: baz: 42;
console.log(foo.baz); // undefined

Usar console.log o console.dir e inspeccionar la estructura del objeto / array. La propiedad a la que está intentando acceder podría estar realmente definida en un objeto anidado / array.

console.log(foo.bar.baz); // 42

¿Qué pasa si los nombres de las propiedades son dinámicos y no los conozco de antemano?

Si los nombres de las propiedades son desconocidos o queremos acceder a todas las propiedades de un objeto / elementos de un array, podemos usar el for...in[MDN] bucle para objetos y el for[MDN] bucle para que las matrices iteren sobre todas las propiedades / elementos.

Objetos

Para iterar sobre todas las propiedades de data, podemos iterar sobre el objeto al igual que:

for (const prop in data) 
    // `prop` contains the name of each property, i.e. `'code'` or `'items'`
    // consequently, `data[prop]` refers to the value of each property, i.e.
    // either `42` or the array

Dependiendo de la procedencia del objeto (y de lo que desee hacer), es posible que deba probar en cada iteración si la propiedad es realmente una propiedad del objeto o si es una propiedad heredada. Puedes hacer esto con Object#hasOwnProperty[MDN].

Como alternativa a for...in con hasOwnProperty, puedes usar Object.keys[MDN] para conseguir un array de nombres de propiedad:

Object.keys(data).forEach(function(prop) 
  // `prop` is the property name
  // `data[prop]` is the property value
);

Matrices

Para iterar sobre todos los elementos del data.itemsarray, usamos un for círculo:

for(let i = 0, l = data.items.length; i < l; i++) 
    // `i` will take on the values `0`, `1`, `2`,..., i.e. in each iteration
    // we can access the next element in the array with `data.items[i]`, example:
    // 
    // var obj = data.items[i];
    // 
    // Since each element is an object (in our example),
    // we can now access the objects properties with `obj.id` and `obj.name`. 
    // We could also use `data.items[i].id`.

También se podría usar for...in iterar sobre matrices, pero hay razones por las que esto debe evitarse: ¿Por qué 'for (var item in list)' con matrices se considera una mala práctica en JavaScript?

Con el creciente soporte de navegador de ECMAScript 5, el array método forEach[MDN] se convierte también en una alternativa interesante:

data.items.forEach(function(value, index, array) 
    // The callback is executed for each element in the array.
    // `value` is the element itself (equivalent to `array[index]`)
    // `index` will be the index of the element in the array
    // `array` is a reference to the array itself (i.e. `data.items` in this case)
); 

En entornos compatibles con ES2015 (ES6), también puede utilizar el for...of[MDN] bucle, que no solo funciona para matrices, sino para cualquier iterable:

for (const item of data.items) 
   // `item` is the array element, **not** the index

En cada iteración, for...of directamente nos da el siguiente elemento del iterable, no hay "índice" para acceder o usar.


¿Qué pasa si desconozco la "profundidad" de la estructura de datos?

Además de desconocido keys, la "profundidad" de la estructura de datos (es decir, cuántos objetos anidados) tiene, también puede ser desconocida. La forma de acceder a las propiedades profundamente anidadas generalmente depende de la estructura de datos exacta.

Pero si la estructura de datos contiene patrones repetidos, por ejemplo, la representación de un árbol binario, la solución generalmente incluye: recursivamente[Wikipedia] acceder a cada nivel de la estructura de datos.

Aquí hay un ejemplo para obtener el primer nodo hoja de un árbol binario:

function getLeaf(node) 
    if (node.leftChild) 
        return getLeaf(node.leftChild); // <- recursive call
    
    else if (node.rightChild) 
        return getLeaf(node.rightChild); // <- recursive call
    
    else  // node must be a leaf node
        return node;
    


const first_leaf = getLeaf(root);

const root = 
    leftChild: 
        leftChild: 
            leftChild: null,
            rightChild: null,
            data: 42
        ,
        rightChild: 
            leftChild: null,
            rightChild: null,
            data: 5
        
    ,
    rightChild: 
        leftChild: 
            leftChild: null,
            rightChild: null,
            data: 6
        ,
        rightChild: 
            leftChild: null,
            rightChild: null,
            data: 7
        
    
;
function getLeaf(node) 
    if (node.leftChild) 
        return getLeaf(node.leftChild);
     else if (node.rightChild) 
        return getLeaf(node.rightChild);
     else  // node must be a leaf node
        return node;
    


console.log(getLeaf(root).data);

Una forma más genérica de acceder a una estructura de datos anidada con desconocido keys y la profundidad es probar el tipo de valor y actuar en consecuencia.

Aquí hay un ejemplo que agrega todos los valores primitivos dentro de una estructura de datos anidada en un array (asumiendo que no contiene ninguna función). Si encontramos un objeto (o array) simplemente llamamos toArray nuevamente en ese valor (llamada recursiva).

function toArray(obj) 
    const result = [];
    for (const prop in obj) 
        const value = obj[prop];
        if (typeof value === 'object') 
            result.push(toArray(value)); // <- recursive call
        
        else 
            result.push(value);
        
    
    return result;

const data = 
  code: 42,
  items: [
    id: 1,
    name: 'foo'
  , 
    id: 2,
    name: 'bar'
  ]
;


function toArray(obj) 
  const result = [];
  for (const prop in obj) 
    const value = obj[prop];
    if (typeof value === 'object') 
      result.push(toArray(value));
     else 
      result.push(value);
    
  
  return result;


console.log(toArray(data));



Ayudantes

Dado que la estructura de un objeto complejo o array no es necesariamente obvio, podemos inspeccionar el valor en cada paso para decidir cómo avanzar. console.log[MDN] y console.dir[MDN] ayúdanos a hacer esto. Por ejemplo (salida de la consola de Chrome):

> console.log(data.items)
 [ Object, Object ]

Aquí vemos que eso data.items es un array con dos elementos que son ambos objetos. En la consola de Chrome, los objetos incluso se pueden expandir e inspeccionar de inmediato.

> console.log(data.items[1])
  Object
     id: 2
     name: "bar"
     __proto__: Object

Esto nos dice que data.items[1] es un objeto, y después de expandirlo vemos que tiene tres propiedades, id, name y __proto__. Esta última es una propiedad interna que se utiliza para la cadena de prototipos del objeto. Sin embargo, la cadena de prototipos y la herencia están fuera del alcance de esta respuesta.

Puedes acceder a él de esta manera

data.items[1].name

o

data["items"][1]["name"]

Ambas formas son iguales.

En caso de que esté intentando acceder a un item de la estructura de ejemplo por id o name, sin saber su posición en el array, la forma más fácil de hacerlo sería usar la biblioteca underscore.js:

var data = 
    code: 42,
    items: [
        id: 1,
        name: 'foo'
    , 
        id: 2,
        name: 'bar'
    ]
;

_.find(data.items, function(item) 
  return item.id === 2;
);
// Object id: 2, name: "bar"

Según mi experiencia, el uso de funciones de orden superior en lugar de for o for..in los bucles dan como resultado un código sobre el que es más fácil razonar y, por lo tanto, más fácil de mantener.

Solo mis 2 centavos.

valoraciones y reseñas

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *