688 Stimmen

Zugriff auf verschachtelte JavaScript-Objekte und -Arrays über einen String-Pfad

Ich habe eine Datenstruktur wie diese:

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'
        }
    ]
};

Und ich möchte mit diesen Variablen auf die Daten zugreifen:

var part1name = "part1.name";
var part2quantity = "part2.qty";
var part3name1 = "part3[0].name";

part1name sollte gefüllt werden mit someObject.part1.name Wert, der "Teil 1" ist. Dasselbe gilt für part2quantity, das mit 60 gefüllt ist.

Gibt es irgendwie zu erreichen dies entweder mit reinen Javascript oder JQuery?

0 Stimmen

Sie sind sich nicht sicher, was Sie hier fragen? Möchten Sie part1.name abfragen können und den Text "part1.name" zurückerhalten? Oder möchten Sie den in part1.name gespeicherten Wert abrufen?

0 Stimmen

Haben Sie versucht, etwas zu tun wie var part1name = someObject.part1name; `

1 Stimmen

@BonyT : Ich möchte someObject.part1.name abfragen und den Wert davon zurückgeben ("Part 1"). Ich möchte jedoch, dass die Abfrage (ich nannte sie "den Schlüssel") in einer Variablen 'part1name' gespeichert wird. Vielen Dank für Ihre Antwort. @3nigma : Das habe ich sicherlich. Aber das ist nicht meine Absicht. Vielen Dank für die Antwort.

2voto

Mr. Polywhirl Punkte 34960

Basierend auf Alnitak's respuesta .

Ich habe das Polyfill in eine Prüfung verpackt und die Funktion auf eine einzige verkettete Reduktion reduziert.

if (Object.byPath === undefined) {
  Object.byPath = (obj, path) => path
    .replace(/\[(\w+)\]/g, '.$1')
    .replace(/^\./, '')
    .split(/\./g)
    .reduce((ref, key) => key in ref ? ref[key] : ref, obj)
}

const data = {
  foo: {
    bar: [{
      baz: 1
    }]
  }
}

console.log(Object.byPath(data, 'foo.bar[0].baz'))

2voto

Flavien Volken Punkte 15992

Obwohl reduce gut ist, bin ich überrascht, dass niemand forEach verwendet hat:

function valueForKeyPath(obj, path){
        const keys = path.split('.');
        keys.forEach((key)=> obj = obj[key]);
        return obj;
    };

Test%3B%0A%20%20%20%20%20%20%20%20return%20obj%3B%0A%20%20%20%20%7D%3B%0A%0Aalert(valueForKeyPath(test%2C%20'a.b.c')))

0 Stimmen

Sie prüfen nicht einmal, ob obj[key] tatsächlich existiert. Das ist unzuverlässig.

0 Stimmen

@CarlesAlcolea js prüft standardmäßig nicht, ob der Schlüssel eines Objekts existiert: a.b.c löst eine Ausnahme aus, wenn es keine Eigenschaft gibt b in Ihrem Objekt. Wenn Sie etwas brauchen, das den falschen Tastaturpfad stillschweigend abweist (was ich nicht empfehle), können Sie das forEach immer noch durch dieses ersetzen keys.forEach((key)=> obj = (obj||{})[key]);

0 Stimmen

Ich habe ein Objekt durchlaufen lassen, bei dem eine geschweifte Klammer fehlte, mein Fehler :)

2voto

Dm Mh Punkte 790

Ich entwickle einen Online Shop mit React. Ich habe versucht, die Werte im kopierten Zustandsobjekt zu ändern, um den ursprünglichen Zustand beim Absenden zu aktualisieren. Die obigen Beispiele haben bei mir nicht funktioniert, weil die meisten die Struktur des kopierten Objekts verändern. Ich habe ein funktionierendes Beispiel der Funktion für den Zugriff und die Änderung der Werte der tief verschachtelten Objekteigenschaften gefunden: https://lowrey.me/create-an-object-by-path-in-javascript-2/ Hier ist sie:

const createPath = (obj, path, value = null) => {
  path = typeof path === 'string' ? path.split('.') : path;
  let current = obj;
  while (path.length > 1) {
    const [head, ...tail] = path;
    path = tail;
    if (current[head] === undefined) {
      current[head] = {};
    }
    current = current[head];
  }
  current[path[0]] = value;
  return obj;
};

2voto

Alex Mckay Punkte 3029

Dies kann vereinfacht werden, indem die Logik in drei separate Funktionen aufgeteilt wird:

const isVal = a => a != null; // everything except undefined + null

const prop = prop => obj => {
    if (isVal(obj)) {
        const value = obj[prop];
        if (isVal(value)) return value;
        else return undefined;
    } else return undefined;
};

const path = paths => obj => {
    const pathList = typeof paths === 'string' ? paths.split('.') : paths;
    return pathList.reduce((value, key) => prop(key)(value), obj);
};

//usage:
const myObject = { foo: { bar: { baz: 'taco' } } };
const result = path('foo.bar')(myObject);
//results => { baz: 'taco' }

Diese Variante unterstützt:

  • Übergabe eines Array- oder String-Arguments
  • Umgang mit undefined Werte während des Aufrufs und der Ausführung
  • jede Funktion unabhängig zu testen
  • jede Funktion unabhängig zu nutzen

2voto

caleb Punkte 2529

Es gibt eine npm Modul, um dies zu tun: https://github.com/erictrinh/safe-access

Beispiel für die Verwendung:

var access = require('safe-access');
access(very, 'nested.property.and.array[0]');

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X