Dostęp do zagnieżdżonych obiektów JavaScript za pomocą klucza string

Mam taką strukturę danych:

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

I chciałbym uzyskać dostęp do danych za pomocą tej zmiennej:

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

Nazwa Part1 powinna być wypełniona wartością someObject.part1.name, która jest "Part 1". To samo z part2quantity, który wypełniony 60.

Czy w ogóle można to osiągnąć za pomocą czystego javascript lub JQuery?

Author: Paul Roub, 2011-06-27

28 answers

Właśnie zrobiłem to na podstawie jakiegoś podobnego kodu, który już miałem, wygląda na to, że działa:

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

Usage::

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

Zobacz działające demo na http://jsfiddle.net/alnitak/hEsys/

EDIT niektórzy zauważyli, że ten kod spowoduje błąd, jeśli przekazany zostanie ciąg znaków, w którym większość indeksów po lewej stronie nie odpowiada poprawnie zagnieżdżonemu wpisowi wewnątrz obiektu. Jest to słuszna troska, ale IMHO najlepiej zająć się blokiem try / catch podczas wywoływania, zamiast mieć to funkcja po cichu zwraca undefined dla nieprawidłowego indeksu.

 426
Author: Alnitak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-10 13:40:11

Jest to rozwiązanie, którego używam:

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

Przykładowe użycie:

// 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

Ograniczenia:

  • nie można używać nawiasów ([]) dla indeksów tablicowych-chociaż określanie indeksów tablic między tokenem separatora (np. .) działa dobrze, jak pokazano powyżej.
 125
Author: speigg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-15 00:59:02

Jest to teraz obsługiwane przez lodash przy użyciu _.get(obj, property). Zobacz https://lodash.com/docs#get

Przykład z docs:

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'
 113
Author: Ian Walker-Sperber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-08 20:59:00

Musiałbyś sam przeanalizować łańcuch:

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

Wymagało to również zdefiniowania indeksów tablic z notacją kropkową:

var part3name1 = "part3.0.name";

Ułatwia to parsowanie.

DEMO

 61
Author: Felix Kling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-04 13:46:31

Działa również dla tablic / tablic wewnątrz obiektu. Obrona przed nieprawidłowymi wartościami.

/**
 * 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>
 38
Author: TheZver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-27 10:47:43

ES6 : tylko jedna linia w Vanila JS (zwraca null, jeśli nie znajduje się zamiast błędu):

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

Lub exemple:

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

Dla gotowej do użycia funkcji, która rozpoznaje również liczbę false, 0 i ujemną i przyjmuje wartości domyślne jako parametr:

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

Exemple do użycia:

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:

To set a path (Requested by @rob-gordon) you can use:

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

Przykład:

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

tablica dostępowa z []:

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

Exemple

const myVar = {a:{b:[{c:1}]}}
resolvePath(myVar,'a.b[0].c') => 1
resolvePath(myVar,'a["b"][\'0\'].c') => 1
 26
Author: Adriano Spadoni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-19 19:05:09

Używając eval:

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

Wrap aby zwrócić undefined w przypadku błędu

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

Http://jsfiddle.net/shanimal/b3xTw/

używaj zdrowego rozsądku i ostrożności podczas władania mocą evala. Jest trochę jak miecz świetlny, jeśli go włączysz, jest 90% szans, że odetniesz kończynę. To nie dla wszystkich.

 20
Author: Shanimal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-24 06:55:46

Możesz uzyskać wartość elementu Deep object z notacją kropkową bez żadnej zewnętrznej biblioteki JavaScript za pomocą prostej następującej sztuczki:

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

W Twoim przypadku aby uzyskać wartość part1.name z someObject wystarczy wykonać:

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

Oto proste demo skrzypka: https://jsfiddle.net/harishanchu/oq5esowf/

 11
Author: Harish Anchu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-24 11:43:02

Tutaj oferuję więcej sposobów, które pod wieloma względami wydają się szybsze:

Opcja 1: Split string on . lub [Lub ] lub ' lub ", odwróć go, Pomiń puste elementy.

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

Opcja 2 (najszybsza ze wszystkich, z wyjątkiem eval): Skanowanie znaków niskiego poziomu(bez regex/split / etc, tylko Szybkie skanowanie znaków). uwaga: ten nie obsługuje cudzysłowów dla indeksów.

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)

Opcja 3: (nowy : opcja 2 rozszerzona o obsługę cytatów - nieco wolniejsza, ale wciąż szybko)

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/3

"eval(...) "jest jednak nadal królem (czyli pod względem wydajności). Jeśli masz ścieżki właściwości bezpośrednio pod kontrolą, nie powinno być żadnych problemów z używaniem 'eval' (szczególnie jeśli wymagana jest prędkość). Jeśli ciągnięcie ścieżek właściwości " over the wire "(on the line!? lol :P), to tak, użyj czegoś innego, aby być bezpiecznym. Tylko idiota powiedziałby, żeby nigdy nie używać "eval" w wszystkie, ponieważ istnieją są dobre powody kiedy go używać. Ponadto, " jest on używany w Parserze JSON Douga Crockforda."Jeśli wejście jest bezpieczne, to żadnych problemów. Użyj odpowiedniego narzędzia do właściwej pracy, to wszystko.

 8
Author: James Wilkins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:10

Myślę, że prosisz o to:

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

Możesz o to pytać:

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

Oba będą działać


A może prosisz o to

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

var part1name = someObject[partName][nameStr];

W końcu możesz o to prosić

var partName = "part1.name";

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

var part1name = someObject[partBits[0]][partBits[1]];
 7
Author: Hogan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-27 20:46:26

Podejście Speigga jest bardzo schludne i czyste, chociaż znalazłem tę odpowiedź podczas wyszukiwania rozwiązania dostępu do Właściwości AngularJS $scope za pomocą ścieżki łańcuchowej i z niewielką modyfikacją robi to zadanie:

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

Po prostu umieść tę funkcję w kontrolerze root i użyj jej dowolnego zakresu podrzędnego w ten sposób:

$scope.resolve( 'path.to.any.object.in.scope')
 6
Author: nesinervink,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-26 12:22:42

Jest to jeden liniowiec z 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"
Albo nawet lepiej...
const val = _.get(deep, prop);

Lub wersja ES6 z redukcją...

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

Plunkr

 4
Author: James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-18 00:50:51

Nie znalazłem jeszcze pakietu do wykonywania wszystkich operacji ze ścieżką łańcuchową, więc skończyło się na napisaniu własnego szybkiego pakietu, który obsługuje operacje insert (), get() (z domyślnym zwrotem), set() I remove ().

Możesz używać notacji kropkowej, nawiasów, indeksów liczbowych, właściwości liczb ciągów oraz kluczy ze znakami innymi niż słowa. Proste użytkowanie poniżej:

> 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
Author: Kyle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-25 01:32:44

Prosta funkcja, pozwalająca na ciąg znaków lub ścieżkę tablicy.

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

Lub

console.log(get(obj, ['a', 'b', 'c'])); //foo
 3
Author: Ben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-26 14:42:36

Istnieje npm moduł do tego: https://github.com/erictrinh/safe-access

Przykładowe użycie:

var access = require('safe-access');
access(very, 'nested.property.and.array[0]');
 2
Author: caleb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-13 18:56:11

Na wszelki wypadek, ktoś odwiedza to pytanie w 2017 lub później i szuka łatwego do zapamiętania sposobu, oto rozbudowany post na blogu o dostępie do zagnieżdżonych obiektów w JavaScript bez bycia oszukanym przez

nie można odczytać właściwości 'foo' undefined error

Dostęp Do Zagnieżdżonych Obiektów Za Pomocą Array Reduce

Weźmy przykładową strukturę

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

Aby mieć dostęp do zagnieżdżonych tablic, możesz napisać własną tablicę util.

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.

Istnieje również doskonały Typ obsługi minimalnej biblioteki typy , który robi to wszystko za Ciebie.

Z typami, Twój kod będzie wyglądał tak

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

Zastrzeżenie: jestem autorem tego pakietu.

 2
Author: Dinesh Pandiyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-08 13:01:53

To prawdopodobnie nigdy nie ujrzy światła dziennego... ale i tak tu jest.

  1. Zamień składnię [] na .
  2. podziel na ' znak
  3. Usuń puste ciągi
  4. znajdź ścieżkę (inaczej 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
 2
Author: Nick Grealy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-06 02:50:48
/**
 * 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;
}

Współpracuje z

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")
 1
Author: Vitim.us,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-29 19:51:35

Chociaż redukcja jest dobra, to dziwi mnie, że nikt nie używał forEach:

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

Test

 1
Author: Flavien Volken,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-15 14:03:14

Jeśli potrzebujesz uzyskać dostęp do innego zagnieżdżonego klucza bez znajomości go w czasie kodowania (adresowanie go będzie banalne), możesz użyć accessora notacji tablicy:

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

Są równoważne do notacji Dot accessor i mogą się różnić w czasie wykonywania, na przykład:

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

var part1name = someObject[part][property];

Jest równoważne

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

Lub

var part1name = someObject.part1.name;
Mam nadzieję, że to odpowiedź na twoje pytanie...

EDIT

Nie użyję ciągu do mantain pewnego rodzaju XPath zapytanie aby uzyskać dostęp do wartość obiektu. Ponieważ musisz wywołać funkcję, aby przetworzyć zapytanie i pobrać wartość, podążałbym inną ścieżką (nie:

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);

Lub, jeśli jesteś niespokojny z zastosuj metodę

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);

Funkcje są krótsze, jaśniejsze, interpreter sprawdza je za ciebie pod kątem błędów składniowych i tak dalej.

Przy okazji, czuję, że proste zadanie wykonane we właściwym czasie będzie wystarczające...
 0
Author: Eineki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-27 11:35:18

Niedawno miałem to samo pytanie i z powodzeniem użyłem https://npmjs.org/package/tea-properties który również set zagnieżdżony obiekt / tablice:

Get:

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

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

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

Zestaw:

var o = {};

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

assert(o.prop.arr[0].foo, 'bar'); // true
 0
Author: abernier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-04 00:41:22

Rozwiązania tutaj służą tylko do uzyskiwania dostępu do głęboko zagnieżdżonych kluczy. Potrzebowałem go do uzyskiwania dostępu, dodawania, modyfikowania i usuwania kluczy. Oto co wymyśliłem:

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: ścieżka w tablicy. Możesz go zastąpić przez string_path.split(".").
  • type_of_function: 0 dla dostępu (nie przekazuje żadnej wartości do value), 0 dla dodawania i modyfikowania. 1 do usunięcia.
 0
Author: ayushgp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-23 09:45:46

Zamiast ciągu można użyć tablicy adresującej zagnieżdżone obiekty i tablice np.: ["my_field", "another_field", 0, "last_field", 10]

Oto przykład, który zmieniłby pole na podstawie tej reprezentacji tablicy. Używam czegoś takiego w reaccie.js dla kontrolowanych pól wejściowych, które zmieniają stan zagnieżdżonych struktur.

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
Author: Jodo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-25 08:12:18

Bazując na poprzedniej odpowiedzi, stworzyłem funkcję, która może również obsługiwać nawiasy. Ale nie ma w nich kropek ze względu na rozszczepienie.

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
Author: Vincent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-01 12:44:48

// (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
Author: Oboo Chin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-23 12:37:22

Praca z Underscore's property lub 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>
Powodzenia...
 0
Author: Akash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-22 11:49:45

Co z tym rozwiązaniem:

setJsonValue: function (json, field, val) {
  if (field !== undefined){
    try {
      eval("json." + field + " = val");
    }
    catch(e){
      ;
    }
  }  
}

A ten, za zdobycie:

getJsonValue: function (json, field){
  var value = undefined;
  if (field !== undefined) {
    try {
      eval("value = json." + field);
    } 
    catch(e){
      ;
    }
  }
  return value;
};

Prawdopodobnie niektórzy uznają je za niebezpieczne, ale muszą być wtedy znacznie szybsze, analizując ciąg znaków.

 -1
Author: Jonan Georgiev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-04 19:54:04

Budowanie z odpowiedzi Alnitaka:

if(!Object.prototype.byString){
  //NEW byString which can update values
Object.prototype.byString = function(s, v, o) {
  var _o = o || this;
      s = s.replace(/\[(\w+)\]/g, '.$1'); // CONVERT INDEXES TO PROPERTIES
      s = s.replace(/^\./, ''); // STRIP A LEADING DOT
      var a = s.split('.'); //ARRAY OF STRINGS SPLIT BY '.'
      for (var i = 0; i < a.length; ++i) {//LOOP OVER ARRAY OF STRINGS
          var k = a[i];
          if (k in _o) {//LOOP THROUGH OBJECT KEYS
              if(_o.hasOwnProperty(k)){//USE ONLY KEYS WE CREATED
                if(v !== undefined){//IF WE HAVE A NEW VALUE PARAM
                  if(i === a.length -1){//IF IT'S THE LAST IN THE ARRAY
                    _o[k] = v;
                  }
                }
                _o = _o[k];//NO NEW VALUE SO JUST RETURN THE CURRENT VALUE
              }
          } else {
              return;
          }
      }
      return _o;
  };

}

To pozwala również ustawić wartość!

Stworzyłem pakiet npmi github z tym również

 -1
Author: Tamb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-15 21:40:23