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?
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.
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:
[]
) können nicht für Arrayindizes verwendet werden. Die Angabe von Arrayindizes zwischen dem Trennzeichentoken (z. B. .
) funktioniert jedoch wie oben gezeigt. 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'
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.
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
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>
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.
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/
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.
Dies wird wahrscheinlich nie das Tageslicht sehen ... aber hier ist es trotzdem.
[]
Klammer-Syntax durch .
.
Zeichen aufteilenundefined
)// "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
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]];
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')
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);
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
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.
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'
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
/**
* 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")
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]');
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;
};
Underscore
s 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...
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" } }
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);
}
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');
// (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"]));
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);
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.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;
};
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 ...
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