it-swarm.com.de

Zugriff auf verschachtelte JavaScript-Objekte mit dem Schlüssel "string"

Ich habe eine Datenstruktur wie folgt:

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 dieser Variablen auf die Daten zugreifen:

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

part1name sollte mit dem Wert von someObject.part1.name gefüllt werden, der "Teil 1" ist. Gleiches mit part2quantity, das sich mit 60 füllte.

Gibt es das überhaupt mit reinem Javascript oder JQuery?

348
Komaruloh

Ich habe das nur gemacht, basierend auf einem ähnlichen Code, den ich bereits hatte, es scheint zu funktionieren:

Object.byString = function(o, s) {
    s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
    s = s.replace(/^\./, '');           // strip a leading dot
    var a = s.split('.');
    for (var i = 0, n = a.length; i < n; ++i) {
        var k = a[i];
        if (k in o) {
            o = o[k];
        } else {
            return;
        }
    }
    return o;
}

Verwendungszweck::

Object.byString(someObj, 'part3[0].name');

Sehen Sie eine funktionierende Demo unter http://jsfiddle.net/alnitak/hEsys/

EDIT Einige haben bemerkt, dass dieser Code einen Fehler ausgibt, wenn eine Zeichenfolge übergeben wird, bei der die am weitesten links liegenden Indizes keinem richtig geschachtelten Eintrag innerhalb des Objekts entsprechen. Dies ist ein gültiges Problem, aber IMHO sollte beim Aufruf am besten mit einem try / catch-Block adressiert werden, anstatt diese Funktion automatisch für einen ungültigen Index undefined zurückgeben zu müssen.

452
Alnitak

Dies ist die Lösung, die ich verwende:

function resolve(path, obj=self, separator='.') {
    var properties = Array.isArray(path) ? path : path.split(separator)
    return properties.reduce((prev, curr) => prev && prev[curr], obj)
}

Verwendungsbeispiel:

// accessing property path on global scope
resolve("document.body.style.width")
// or
resolve("style.width", document.body)

// accessing array indexes
// (someObject has been defined in the question)
resolve("part3.0.size", someObject) // returns '10'

// accessing non-existent properties
// returns undefined when intermediate properties are not defined:
resolve('properties.that.do.not.exist', {hello:'world'})

// accessing properties with unusual keys by changing the separator
var obj = { object: { 'a.property.name.with.periods': 42 } }
resolve('object->a.property.name.with.periods', obj, '->') // returns 42

// accessing properties with unusual keys by passing a property name array
resolve(['object', 'a.property.name.with.periods'], obj) // returns 42

Einschränkungen:

  • Klammern ([]) können nicht für Arrayindizes verwendet werden. Die Angabe von Arrayindizes zwischen dem Trennzeichentoken (z. B. .) funktioniert jedoch wie oben gezeigt. 
140
speigg

Dies wird nun von lodash mit _.get(obj, property) unterstützt. Siehe https://lodash.com/docs#get

Beispiel aus den Dokumenten:

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// → 3

_.get(object, ['a', '0', 'b', 'c']);
// → 3

_.get(object, 'a.b.c', 'default');
// → 'default'
131

Sie müssen die Zeichenfolge selbst analysieren:

function getProperty(obj, prop) {
    var parts = prop.split('.');

    if (Array.isArray(parts)) {
        var last = parts.pop(),
        l = parts.length,
        i = 1,
        current = parts[0];

        while((obj = obj[current]) && i < l) {
            current = parts[i];
            i++;
        }

        if(obj) {
            return obj[last];
        }
    } else {
        throw 'parts is not valid array';
    }
}

Dazu mussten Sie auch Array-Indizes mit Punktnotation definieren:

var part3name1 = "part3.0.name";

Es erleichtert das Parsen.

DEMO

61
Felix Kling

ES6: Nur eine Zeile in Vanila JS (es wird null zurückgegeben, wenn es nicht gefunden wird, anstatt einen Fehler zu geben):

'path.string'.split('.').reduce((p,c)=>p&&p[c]||null, MyOBJ)

oder Beispiel:

'a.b.c'.split('.').reduce((p,c)=>p&&p[c]||null, {a:{b:{c:1}}})

Für eine einsatzbereite Funktion, die auch false, 0 und negative Zahlen erkennt und Standardwerte als Parameter akzeptiert:

const resolvePath = (object, path, defaultValue) => path
   .split('.')
   .reduce((o, p) => o ? o[p] : defaultValue, object)

Zu verwendendes Beispiel:

resolvePath(window,'document.body') => <body>
resolvePath(window,'document.body.xyz') => undefined
resolvePath(window,'document.body.xyz', null) => null
resolvePath(window,'document.body.xyz', 1) => 1

Bonus :

Für set einen Pfad (angefordert von @ rob-gordon) können Sie Folgendes verwenden:

const setPath = (object, path, value) => path
   .split('.')
   .reduce((o,p,i) => o[p] = path.split('.').length === ++i ? value : o[p] || {}, object)

Beispiel:

let myVar = {}
setPath(myVar, 'a.b.c', 42) => 42
console.log(myVar) => {a: {b: {c: 42}}}

Greifen Sie mit [] auf das Array zu :

const resolvePath = (object, path, defaultValue) => path
   .split(/[\.\[\]\'\"]/)
   .filter(p => p)
   .reduce((o, p) => o ? o[p] : defaultValue, object)

beispiel

const myVar = {a:{b:[{c:1}]}}
resolvePath(myVar,'a.b[0].c') => 1
resolvePath(myVar,'a["b"][\'0\'].c') => 1
44
Adriano Spadoni

Funktioniert auch für Arrays/Arrays innerhalb des Objekts. Defensiv gegen ungültige Werte.

/**
 * Retrieve nested item from object/array
 * @param {Object|Array} obj
 * @param {String} path dot separated
 * @param {*} def default value ( if result undefined )
 * @returns {*}
 */
function path(obj, path, def){
    var i, len;

    for(i = 0,path = path.split('.'), len = path.length; i < len; i++){
        if(!obj || typeof obj !== 'object') return def;
        obj = obj[path[i]];
    }

    if(obj === undefined) return def;
    return obj;
}

//////////////////////////
//         TEST         //
//////////////////////////

var arr = [true, {'sp ace': true}, true]

var obj = {
  'sp ace': true,
  arr: arr,
  nested: {'dotted.str.ing': true},
  arr3: arr
}

shouldThrow(`path(obj, "arr.0")`);
shouldBeDefined(`path(obj, "arr[0]")`);
shouldBeEqualToNumber(`path(obj, "arr.length")`, 3);
shouldBeTrue(`path(obj, "sp ace")`);
shouldBeEqualToString(`path(obj, "none.existed.prop", "fallback")`, "fallback");
shouldBeTrue(`path(obj, "nested['dotted.str.ing'])`);
<script src="https://cdn.rawgit.com/coderek/e7b30bac7634a50ad8fd/raw/174b6634c8f57aa8aac0716c5b7b2a7098e03584/js-test.js"></script>

39
TheZver

mit eval:

var part1name = eval("someObject.part1.name");

wrap, um bei einem Fehler undefined zurückzukehren

function path(obj, path) {
    try {
        return eval("obj." + path);
    } catch(e) {
        return undefined;
    }
}

http://jsfiddle.net/shanimal/b3xTw/

Bitte wende den gesunden Menschenverstand und Vorsicht an, wenn du die Kraft des eval ausübst. Es ist ein bisschen wie ein Lichtschwert. Wenn Sie ihn einschalten, besteht eine Chance von 90%, dass Sie ein Glied durchtrennen. Es ist nicht jedermanns Sache.

21
Shanimal

Mit dem folgenden einfachen Trick können Sie den Wert eines tiefen Objektelements mit Punktnotation ohne externe JavaScript-Bibliothek abrufen:

new Function('_', 'return _.' + path)(obj);

Um den Wert von part1.name von someObject zu erhalten, machen Sie einfach Folgendes:

new Function('_', 'return _.part1.name')(someObject);

Hier ist eine einfache Geige-Demo: https://jsfiddle.net/harishanchu/oq5esowf/

14
Harish Anchu

Hier biete ich mehr Möglichkeiten, die in vielerlei Hinsicht schneller erscheinen:

Option 1: String aufteilen. oder [oder] oder 'oder ", umkehren, leere Elemente überspringen.

function getValue(path, Origin) {
    if (Origin === void 0 || Origin === null) Origin = self ? self : this;
    if (typeof path !== 'string') path = '' + path;
    var parts = path.split(/\[|\]|\.|'|"/g).reverse(), name; // (why reverse? because it's usually faster to pop off the end of an array)
    while (parts.length) { name=parts.pop(); if (name) Origin=origin[name]; }
    return Origin;
}

Option 2 (mit Ausnahme von eval am schnellsten): Niedrigstufiger Zeichenscan (kein Regex/Split/etc, nur ein schneller Char-Scan). Hinweis: Diese unterstützt keine Anführungszeichen für Indizes.

function getValue(path, Origin) {
    if (Origin === void 0 || Origin === null) Origin = self ? self : this;
    if (typeof path !== 'string') path = '' + path;
    var c = '', pc, i = 0, n = path.length, name = '';
    if (n) while (i<=n) ((c = path[i++]) == '.' || c == '[' || c == ']' || c == void 0) ? (name?(Origin = Origin[name], name = ''):(pc=='.'||pc=='['||pc==']'&&c==']'?i=n+2:void 0),pc=c) : name += c;
    if (i==n+2) throw "Invalid path: "+path;
    return Origin;
} // (around 1,000,000+/- ops/sec)

Option 3: ( new : Option 2 erweitert, um Anführungszeichen zu unterstützen - etwas langsamer, aber immer noch schnell)

function getValue(path, Origin) {
    if (Origin === void 0 || Origin === null) Origin = self ? self : this;
    if (typeof path !== 'string') path = '' + path;
    var c, pc, i = 0, n = path.length, name = '', q;
    while (i<=n)
        ((c = path[i++]) == '.' || c == '[' || c == ']' || c == "'" || c == '"' || c == void 0) ? (c==q&&path[i]==']'?q='':q?name+=c:name?(origin?origin=Origin[name]:i=n+2,name='') : (pc=='['&&(c=='"'||c=="'")?q=c:pc=='.'||pc=='['||pc==']'&&c==']'||pc=='"'||pc=="'"?i=n+2:void 0), pc=c) : name += c;
    if (i==n+2 || name) throw "Invalid path: "+path;
    return Origin;
}

JSPerf: http://jsperf.com/ways-to-dereference-a-delimited-property-string/

"eval (...)" ist aber immer noch König (Performance weise das ist). Wenn Sie Eigenschaftspfade direkt unter Ihrer Kontrolle haben, sollte es keine Probleme mit der Verwendung von 'eval' geben (insbesondere, wenn Geschwindigkeit gewünscht wird). Wenn Sie Eigenschaftspfade "über die Leitung" ziehen ( in der Zeile !? lol: P), verwenden Sie zur Sicherheit etwas anderes. Nur ein Idiot würde sagen, niemals "eval" zu benutzen, da es SIND gute Gründe wann man es benutzt. Außerdem wird es in Doug Crockfords JSON-Parser verwendet. Wenn die Eingabe sicher ist, dann überhaupt keine Probleme. Verwenden Sie das richtige Werkzeug für den richtigen Job, das wars.

7
James Wilkins

Dies wird wahrscheinlich nie das Tageslicht sehen ... aber hier ist es trotzdem.

  1. Ersetzen Sie [] Klammer-Syntax durch .
  2. Nach . Zeichen aufteilen
  3. Entfernen Sie leere Zeichenfolgen
  4. Finde den Pfad (sonst undefined)

// "one liner" (ES6)

const deep_value = (obj, path) => 
  path
    .replace(/\[|\]\.?/g, '.')
    .split('.')
    .filter(s => s)
    .reduce((acc, val) => acc && acc[val], obj);
    
// ... and that's it.

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

console.log(deep_value(someObject, "part1.name"));               // Part 1
console.log(deep_value(someObject, "part2.qty"));                // 60
console.log(deep_value(someObject, "part3[0].name"));            // Part 3A

7
Nick Grealy

Ich denke du fragst das:

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

Sie könnten danach fragen:

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

Beides wird funktionieren


Oder vielleicht fragen Sie das?

var partName = "part1";
var nameStr = "name";

var part1name = someObject[partName][nameStr];

Zum Schluss könnte man das fragen

var partName = "part1.name";

var partBits = partName.split(".");

var part1name = someObject[partBits[0]][partBits[1]];
6
Hogan

Der Ansatz von Speigg ist sehr ordentlich und sauber, obwohl ich diese Antwort gefunden habe, als ich nach einer Lösung gesucht habe, um auf die Eigenschaften des AngularJS $ -Ocopes per Stringpfad zuzugreifen.

$scope.resolve = function( path, obj ) {
    return path.split('.').reduce( function( prev, curr ) {
        return prev[curr];
    }, obj || this );
}

Platzieren Sie diese Funktion einfach in Ihrem Root-Controller und verwenden Sie ihn wie folgt:

$scope.resolve( 'path.to.any.object.in.scope')
6
nesinervink

Es ist ein Liner mit Lodash.

const deep = { l1: { l2: { l3: "Hello" } } };
const prop = "l1.l2.l3";
const val = _.reduce(prop.split('.'), function(result, value) { return result ? result[value] : undefined; }, deep);
// val === "Hello"

Oder noch besser ...

const val = _.get(deep, prop);

Oder ES6-Version mit ...

const val = prop.split('.').reduce((r, val) => { return r ? r[val] : undefined; }, deep);

Plunkr

5
James

Nur für den Fall, dass jemand diese Frage in 2017 oder später besucht und nach einer einfach zu merkenden Art und Weise sucht. Hier ist ein ausführlicher Blogbeitrag über Auf verschachtelte Objekte in JavaScript zugreifen ohne bamboozled zu sein 

Eigenschaft 'foo' von undefined kann nicht gelesen werden Fehler

Zugriff auf verschachtelte Objekte mithilfe von Array Reduce

Nehmen wir diese Beispielstruktur

const user = {
    id: 101,
    email: '[email protected]',
    personalInfo: {
        name: 'Jack',
        address: [{
            line1: 'westwish st',
            line2: 'washmasher',
            city: 'wallas',
            state: 'WX'
        }]
    }
}

Um auf verschachtelte Arrays zugreifen zu können, können Sie ein eigenes Array schreiben, das util reduziert.

const getNestedObject = (nestedObj, pathArr) => {
    return pathArr.reduce((obj, key) =>
        (obj && obj[key] !== 'undefined') ? obj[key] : undefined, nestedObj);
}

// pass in your object structure as array elements
const name = getNestedObject(user, ['personalInfo', 'name']);

// to access nested array, just pass in array index as an element the path array.
const city = getNestedObject(user, ['personalInfo', 'address', 0, 'city']);
// this will return the city from the first address item.

Es gibt auch einen hervorragenden Typ, der die minimale Bibliothek typy behandelt, die all dies für Sie erledigt.

Mit typy wird Ihr Code so aussehen

const city = t(user, 'personalInfo.address[0].city').safeObject;

Haftungsausschluss: Ich bin der Autor dieses Pakets.

4
Dinesh Pandiyan

Ich habe noch kein Paket gefunden, das alle Operationen mit einem String-Pfad durchführt, und so schrieb ich mein eigenes kleines Paket, das insert (), get () (mit Standardrückgabe), set () und remove ) Operationen.

Sie können Punktnotation, Klammern, Zahlenindizes, Zeichenfolgennummerneigenschaften und Schlüssel mit Nicht-Word-Zeichen verwenden. Einfache verwendung unten:

> var jsocrud = require('jsocrud');

...

// Get (Read) ---
> var obj = {
>     foo: [
>         {
>             'key w/ non-Word chars': 'bar'
>         }
>     ]
> };
undefined

> jsocrud.get(obj, '.foo[0]["key w/ non-Word chars"]');
'bar'

https://www.npmjs.com/package/jsocrud

https://github.com/vertical-knowledge/jsocrud

3
Kyle

Einfache Funktion, die entweder einen String oder einen Arraypfad zulässt.

function get(obj, path) {
  if(typeof path === 'string') path = path.split('.');

  if(path.length === 0) return obj;
  return get(obj[path[0]], path.slice(1));
}

const obj = {a: {b: {c: 'foo'}}};

console.log(get(obj, 'a.b.c')); //foo

OR

console.log(get(obj, ['a', 'b', 'c'])); //foo
3
Ben
/**
 * Access a deep value inside a object 
 * Works by passing a path like "foo.bar", also works with nested arrays like "foo[0][1].baz"
 * @author Victor B. https://Gist.github.com/victornpb/4c7882c1b9d36292308e
 * Unit tests: http://jsfiddle.net/Victornpb/0u1qygrh/
 */
function getDeepVal(obj, path) {
    if (typeof obj === "undefined" || obj === null) return;
    path = path.split(/[\.\[\]\"\']{1,2}/);
    for (var i = 0, l = path.length; i < l; i++) {
        if (path[i] === "") continue;
        obj = obj[path[i]];
        if (typeof obj === "undefined" || obj === null) return;
    }
    return obj;
}

Arbeitet mit

getDeepVal(obj,'foo.bar')
getDeepVal(obj,'foo.1.bar')
getDeepVal(obj,'foo[0].baz')
getDeepVal(obj,'foo[1][2]')
getDeepVal(obj,"foo['bar'].baz")
getDeepVal(obj,"foo['bar']['baz']")
getDeepVal(obj,"foo.bar.0.baz[1]['2']['w'].aaa[\"f\"].bb")
2
Vitim.us

Dafür gibt es jetzt ein npm-Modul: https://github.com/erictrinh/safe-access

Verwendungsbeispiel:

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

Während das Reduzieren gut ist, wundert es mich, dass niemand für jeden Gebrauch gemacht hat:

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

Prüfung

1
Flavien Volken

Arbeiten mit Underscores property oder propertyOf:

var test = {
  foo: {
    bar: {
      baz: 'hello'
    }
  }
}
var string = 'foo.bar.baz';


// document.write(_.propertyOf(test)(string.split('.')))

document.write(_.property(string.split('.'))(test));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>

Viel Glück...

0
Akash

Die Erweiterung von Mohamad Hamouday 'Answer füllt fehlende Schlüssel aus

function Object_Manager(obj, Path, value, Action, strict) 
{
    try
    {
        if(Array.isArray(Path) == false)
        {
            Path = [Path];
        }

        let level = 0;
        var Return_Value;
        Path.reduce((a, b)=>{
            console.log(level,':',a, '|||',b)
            if (!strict){
              if (!(b in a)) a[b] = {}
            }


            level++;
            if (level === Path.length)
            {
                if(Action === 'Set')
                {
                    a[b] = value;
                    return value;
                }
                else if(Action === 'Get')
                {
                    Return_Value = a[b];
                }
                else if(Action === 'Unset')
                {
                    delete a[b];
                }
            } 
            else 
            {
                return a[b];
            }
        }, obj);
        return Return_Value;
    }

    catch(err)
    {
        console.error(err);
        return obj;
    }
}

Beispiel


obja = {
  "a": {
    "b":"nom"
  }
}

// Set
path = "c.b" // Path does not exist
Object_Manager(obja,path.split('.'), 'test_new_val', 'Set', false);

// Expected Output: Object { a: Object { b: "nom" }, c: Object { b: "test_new_value" } }

0
sam

Basierend auf einer vorherigen Antwort habe ich eine Funktion erstellt, die auch Klammern verarbeiten kann. Aber keine Punkte in ihnen wegen der Spaltung.

function get(obj, str) {
  return str.split(/\.|\[/g).map(function(crumb) {
    return crumb.replace(/\]$/, '').trim().replace(/^(["'])((?:(?!\1)[^\\]|\\.)*?)\1$/, (match, quote, str) => str.replace(/\\(\\)?/g, "$1"));
  }).reduce(function(obj, prop) {
    return obj ? obj[prop] : undefined;
  }, obj);
}
0
Vincent

Inspiriert von @ webjays Antwort: https://stackoverflow.com/a/46008856/4110122

Ich habe diese Funktion gemacht, mit der Sie einen beliebigen Wert in object Get/Set/Unset _ ​​setzen können

function Object_Manager(obj, Path, value, Action) 
{
    try
    {
        if(Array.isArray(Path) == false)
        {
            Path = [Path];
        }

        let level = 0;
        var Return_Value;
        Path.reduce((a, b)=>{
            level++;
            if (level === Path.length)
            {
                if(Action === 'Set')
                {
                    a[b] = value;
                    return value;
                }
                else if(Action === 'Get')
                {
                    Return_Value = a[b];
                }
                else if(Action === 'Unset')
                {
                    delete a[b];
                }
            } 
            else 
            {
                return a[b];
            }
        }, obj);
        return Return_Value;
    }

    catch(err)
    {
        console.error(err);
        return obj;
    }
}

Um es zu benutzen:

 // Set
 Object_Manager(Obj,[Level1,Level2,Level3],New_Value, 'Set');

 // Get
 Object_Manager(Obj,[Level1,Level2,Level3],'', 'Get');

 // Unset
 Object_Manager(Obj,[Level1,Level2,Level3],'', 'Unset');
0

// (IE9+) Two steps

var pathString = "[0]['property'].others[3].next['final']";
var obj = [{
  property: {
    others: [1, 2, 3, {
      next: {
        final: "SUCCESS"
      }
    }]
  }
}];

// Turn string to path array
var pathArray = pathString
    .replace(/\[["']?([\w]+)["']?\]/g,".$1")
    .split(".")
    .splice(1);

// Add object prototype method
Object.prototype.path = function (path) {
  try {
    return [this].concat(path).reduce(function (f, l) {
      return f[l];
    });
  } catch (e) {
    console.error(e);
  }
};

// usage
console.log(obj.path(pathArray));
console.log(obj.path([0,"doesNotExist"]));

0
Oboo Chin

Anstelle einer Zeichenfolge kann ein Array verwendet werden, um verschachtelte Objekte und Arrays zu adressieren, z. B .: ["my_field", "another_field", 0, "last_field", 10] 

Hier ist ein Beispiel, das ein Feld basierend auf dieser Arraydarstellung ändern würde. Ich verwende so etwas in react.js für gesteuerte Eingabefelder, die den Zustand verschachtelter Strukturen ändern. 

let state = {
        test: "test_value",
        nested: {
            level1: "level1 value"
        },
        arr: [1, 2, 3],
        nested_arr: {
            arr: ["buh", "bah", "foo"]
        }
    }

function handleChange(value, fields) {
    let update_field = state;
    for(var i = 0; i < fields.length - 1; i++){
        update_field = update_field[fields[i]];
    }
    update_field[fields[fields.length-1]] = value;
}

handleChange("update", ["test"]);
handleChange("update_nested", ["nested","level1"]);
handleChange(100, ["arr",0]);
handleChange('changed_foo', ["nested_arr", "arr", 3]);
console.log(state);
0
Jodo

Die Lösungen hier sind nur für den Zugriff auf die tief verschachtelten Schlüssel. Ich brauchte einen, um auf die Schlüssel zuzugreifen, sie hinzuzufügen, zu ändern und zu löschen. Das ist was ich mir ausgedacht habe:

var deepAccessObject = function(object, path_to_key, type_of_function, value){
    switch(type_of_function){
        //Add key/modify key
        case 0: 
            if(path_to_key.length === 1){
                if(value)
                    object[path_to_key[0]] = value;
                return object[path_to_key[0]];
            }else{
                if(object[path_to_key[0]])
                    return deepAccessObject(object[path_to_key[0]], path_to_key.slice(1), type_of_function, value);
                else
                    object[path_to_key[0]] = {};
            }
            break;
        //delete key
        case 1:
            if(path_to_key.length === 1){
                delete object[path_to_key[0]];
                return true;
            }else{
                if(object[path_to_key[0]])
                    return deepAccessObject(object[path_to_key[0]], path_to_key.slice(1), type_of_function, value);
                else
                    return false;
            }
            break;
        default:
            console.log("Wrong type of function");
    }
};
  • path_to_key: Pfad in einem Array. Sie können es durch Ihre string_path.split(".") ersetzen.
  • type_of_function: 0 für den Zugriff (übergeben Sie keinen beliebigen Wert an value), 0 für das Hinzufügen und Ändern. 1 zum Löschen.
0
ayushgp

Ich entwickle einen Online-Shop mit React. Ich habe versucht, Werte im kopierten Statusobjekt zu ändern, um den ursprünglichen Status beim Senden zu aktualisieren. Die obigen Beispiele haben bei mir nicht funktioniert, da die meisten von ihnen die Struktur des kopierten Objekts verändern. Ich habe ein funktionierendes Beispiel für die Funktion zum Zugreifen auf und Ändern von Werten der tief verschachtelten Objekteigenschaften gefunden: https://lowrey.me/create-an-object-by-path-in-javascript-2/ Here it is :

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;
};
0
Dm Mh

Wenn Sie auf verschiedene verschachtelte Schlüssel zugreifen müssen, ohne sie zum Zeitpunkt der Codierung zu kennen (es ist einfach, sie zu adressieren), können Sie den Array-Notations-Accessor verwenden:

var part1name = someObject['part1']['name'];
var part2quantity = someObject['part2']['qty'];
var part3name1 =  someObject['part3'][0]['name'];

Sie entsprechen dem Punktnotations-Accessor und können zur Laufzeit variieren. Beispiel:

var part = 'part1';
var property = 'name';

var part1name = someObject[part][property];

ist äquivalent zu 

var part1name = someObject['part1']['name'];

oder 

var part1name = someObject.part1.name;

Ich hoffe, dass Sie Ihre Frage beantworten ...

EDIT

Ich verwende keine Zeichenfolge, um eine Art xpath query für den Zugriff auf einen Objektwert zu erhalten. Da Sie eine Funktion aufrufen müssen, um die Abfrage zu parsen und den Wert abzurufen, würde ich einem anderen Pfad folgen (nicht:

var part1name = function(){ return this.part1.name; }
var part2quantity = function() { return this['part2']['qty']; }
var part3name1 =  function() { return this.part3[0]['name'];}

// usage: part1name.apply(someObject);

oder, wenn Sie mit der Methode apply nicht zufrieden sind 

var part1name = function(obj){ return obj.part1.name; }
var part2quantity = function(obj) { return obj['part2']['qty']; }
var part3name1 =  function(obj) { return obj.part3[0]['name'];}

// usage: part1name(someObject);

Die Funktionen sind kürzer und übersichtlicher, der Interpreter prüft sie auf Syntaxfehler usw.

Ich denke übrigens, dass eine einfache, zur richtigen Zeit vorgenommene Aufgabe ausreicht ...

0
Eineki

Hatte gerade die gleiche Frage vor kurzem und erfolgreich verwendet https://npmjs.org/package/tea-properties die auch set verschachtelte Objekte/Arrays

erhalten:

var o = {
  prop: {
    arr: [
      {foo: 'bar'}
    ]
  }
};

var properties = require('tea-properties');
var value = properties.get(o, 'prop.arr[0].foo');

assert(value, 'bar'); // true

einstellen:

var o = {};

var properties = require('tea-properties');
properties.set(o, 'prop.arr[0].foo', 'bar');

assert(o.prop.arr[0].foo, 'bar'); // true
0
abernier