문자열 키를 사용하여 중첩 JavaScript 객체에 액세스
다음과 같은 데이터 구조가 있습니다.
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'
}
]
};
그리고이 변수를 사용하여 데이터에 액세스하고 싶습니다 :
var part1name = "part1.name";
var part2quantity = "part2.qty";
var part3name1 = "part3[0].name";
part1name someObject.part1.name
은 'Part 1'인 값 으로 채워 져야합니다 . 60으로 채워진 part2quantity와 동일한 것.
순수한 자바 스크립트 또는 JQuery로 이것을 달성 할 수 있습니까?
방금 이미 가지고있는 유사한 코드를 기반으로 이것을 만들었습니다. 작동하는 것처럼 보입니다.
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;
}
용법::
Object.byString(someObj, 'part3[0].name');
http://jsfiddle.net/alnitak/hEsys/ 에서 실무 데모를보십시오.
EDIT 일부는 가장 왼쪽의 색인이 객체 내에 올바르게 중첩 된 항목에 해당하지 않는 문자열을 전달하면이 코드가 오류를 발생시키는 것으로 나타났습니다. 이것은 유효한 관심사이지만 try / catch
,이 함수 undefined
가 유효하지 않은 인덱스를 자동으로 리턴하는 것보다는 호출 할 때 IMHO가 블록 으로 처리하는 것이 가장 좋습니다 .
이것이 내가 사용하는 솔루션입니다.
function resolve(path, obj=self, separator='.') {
var properties = Array.isArray(path) ? path : path.split(separator)
return properties.reduce((prev, curr) => prev && prev[curr], obj)
}
사용법 예 :
// 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
한계 :
[]
구분 기호 (예 :) 사이에 배열 인덱스를 지정하면.
위와 같이 올바르게 작동 하지만 배열 인덱스에 대괄호 ( )를 사용할 수 없습니다 .
이것은 이제 lodash를 사용하여 지원됩니다 _.get(obj, property)
. 참조 https://lodash.com/docs#get를
문서의 예 :
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'
문자열을 직접 파싱해야합니다.
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';
}
}
또한 점 표기법으로 배열 인덱스를 정의해야합니다.
var part3name1 = "part3.0.name";
구문 분석이 쉬워집니다.
ES6 : Vanila JS에서 단 한 줄만 (오류 대신에 찾지 못하면 null을 반환합니다) :
'path.string'.split('.').reduce((p,c)=>p&&p[c]||null, MyOBJ)
또는 예 :
'a.b.c'.split('.').reduce((p,c)=>p&&p[c]||null, {a:{b:{c:1}}})
false, 0 및 음수도 인식하고 기본값을 매개 변수로 사용하는 즉시 사용 가능한 기능의 경우 :
const resolvePath = (object, path, defaultValue) => path
.split('.')
.reduce((o, p) => o ? o[p] : defaultValue, object)
사용 예 :
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
보너스 :
경로 를 설정 하려면 (@ rob-gordon 요청) 다음을 사용할 수 있습니다.
const setPath = (object, path, value) => path
.split('.')
.reduce((o,p,i) => o[p] = path.split('.').length === ++i ? value : o[p] || {}, object)
예:
let myVar = {}
setPath(myVar, 'a.b.c', 42) => 42
console.log(myVar) => {a: {b: {c: 42}}}
[]으로 배열에 액세스하십시오 .
const resolvePath = (object, path, defaultValue) => path
.split(/[\.\[\]\'\"]/)
.filter(p => p)
.reduce((o, p) => o ? o[p] : defaultValue, object)
예:
const myVar = {a:{b:[{c:1}]}}
resolvePath(myVar,'a.b[0].c') => 1
resolvePath(myVar,'a["b"][\'0\'].c') => 1
객체 내부의 배열 / 배열에서도 작동합니다. 유효하지 않은 값에 방어 적입니다.
/**
* 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>
평가 사용 :
var part1name = eval("someObject.part1.name");
랩은 에러시에 정의되지 않은 것을 돌려 준다
function path(obj, path) {
try {
return eval("obj." + path);
} catch(e) {
return undefined;
}
}
http://jsfiddle.net/shanimal/b3xTw/
평가의 힘을 발휘할 때는 상식과주의를 사용하십시오. 가벼운 세이버와 비슷합니다. 전원을 켜면 사지가 끊어 질 확률이 90 %입니다. 모두를위한 것은 아닙니다.
다음과 같은 간단한 트릭으로 외부 JavaScript 라이브러리없이 도트 표기법을 사용하여 심층 객체 멤버의 가치를 얻을 수 있습니다.
new Function('_', 'return _.' + path)(obj);
귀하의 경우의 값을 구하는 part1.name
에서 someObject
바로 수행하십시오 :
new Function('_', 'return _.part1.name')(someObject);
간단한 바이올린 데모는 다음과 같습니다. https://jsfiddle.net/harishanchu/oq5esowf/
이것은 아마도 하루의 빛을 보지 못할 것입니다 ...하지만 여기는 어쨌든 있습니다.
- 교체
[]
브래킷 구문.
.
캐릭터 분할- 빈 문자열 제거
- 경로를 찾으십시오 (그렇지 않으면
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
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"
아니면 더 나은 ...
const val = _.get(deep, prop);
또는 ES6 버전 / 축소 ...
const val = prop.split('.').reduce((r, val) => { return r ? r[val] : undefined; }, deep);
나는 당신이 이것을 요구한다고 생각합니다 :
var part1name = someObject.part1.name;
var part2quantity = someObject.part2.qty;
var part3name1 = someObject.part3[0].name;
당신은 이것을 요청할 수 있습니다 :
var part1name = someObject["part1"]["name"];
var part2quantity = someObject["part2"]["qty"];
var part3name1 = someObject["part3"][0]["name"];
둘 다 작동합니다
아니면 당신이 이것을 요구하고 있습니다
var partName = "part1";
var nameStr = "name";
var part1name = someObject[partName][nameStr];
마지막으로 당신은 이것을 요구할 수 있습니다
var partName = "part1.name";
var partBits = partName.split(".");
var part1name = someObject[partBits[0]][partBits[1]];
여기에 여러 가지면에서 더 빠른 것처럼 보이는 더 많은 방법이 있습니다.
옵션 1 :에서 문자열 분할. 또는 [또는] 또는 '또는 ", 반대로 뒤집거나 빈 항목을 건너 뜁니다.
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;
}
옵션 2 (를 제외하고 가장 빠름 eval
) : 낮은 수준의 문자 스캔 (정규식 / 분할 / 등이없고 빠른 문자 스캔). 참고 :이 인덱스에는 따옴표를 지원하지 않습니다.
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)
옵션 3 : ( 신규 : 옵션 2가 따옴표를 지원하도록 확장 됨-조금 느리지 만 여전히 빠름)
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 (...)"은 여전히 왕입니다 (성능은 현명합니다). 직접 제어 할 수있는 속성 경로가있는 경우 'eval'사용에 문제가 없어야합니다 (특히 속도가 필요한 경우). 속성 와이어를 "와이어 위로"( 줄에 !? lol : P) 당기면 안전합니다. 그것을 사용해야 할 충분한 이유 가 있기 때문에 바보 만이 "평가"를 전혀 사용하지 말라고 말할 것입니다. 또한 " Doug Crockford의 JSON 파서 에서 사용됩니다 ." 입력이 안전하다면 아무런 문제가 없습니다. 올바른 작업에 적합한 도구를 사용하십시오.
Speigg의 접근 방식은 매우 깔끔하고 깨끗하지만 문자열 경로로 AngularJS $ scope 속성에 액세스하는 솔루션을 검색하는 동안이 회신을 찾았으며 약간 수정하면 작업을 수행합니다.
$scope.resolve = function( path, obj ) {
return path.split('.').reduce( function( prev, curr ) {
return prev[curr];
}, obj || this );
}
이 함수를 루트 컨트롤러에 넣고 다음과 같은 자식 범위를 사용하십시오.
$scope.resolve( 'path.to.any.object.in.scope')
2017 년 이후 에이 질문을 방문하고 기억하기 쉬운 방법 을 찾는 사람을 위해, JavaScript로 중첩 된 객체 에 액세스 하는 것에 대한 정교한 블로그 게시물 이 있습니다.
정의되지 않은 오류 의 'foo'속성을 읽을 수 없습니다
Array Reduce를 사용하여 중첩 된 객체에 액세스
이 예제 구조를 보자
const user = {
id: 101,
email: 'jack@dev.com',
personalInfo: {
name: 'Jack',
address: [{
line1: 'westwish st',
line2: 'washmasher',
city: 'wallas',
state: 'WX'
}]
}
}
중첩 배열에 액세스하려면 자신의 array reduce 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.
또한이 모든 것을 수행 하는 최소한의 라이브러리 typy 를 처리하는 훌륭한 유형 이 있습니다.
typy를 사용하면 코드가 다음과 같이 보입니다.
const city = t(user, 'personalInfo.address[0].city').safeObject;
면책 조항 : 나는이 패키지의 저자입니다.
문자열 경로로 모든 작업을 수행하는 패키지를 아직 찾지 못했기 때문에 insert (), get () (기본 반환), set () 및 remove ( ) 작업.
점 표기법, 대괄호, 숫자 인덱스, 문자열 번호 속성 및 단어가 아닌 문자가있는 키를 사용할 수 있습니다. 아래 간단한 사용법 :
> 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
문자열이나 배열 경로를 허용하는 간단한 기능.
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
또는
console.log(get(obj, ['a', 'b', 'c'])); //foo
이 npm
모듈은이 일을 지금 : https://github.com/erictrinh/safe-access
사용법 예 :
var access = require('safe-access');
access(very, 'nested.property.and.array[0]');
/**
* 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;
}
와 일하다
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")
감소는 좋지만 아무도 사용하지 않은 것에 놀랐습니다.
function valueForKeyPath(obj, path){
const keys = path.split('.');
keys.forEach((key)=> obj = obj[key]);
return obj;
};
@webjay의 답변에서 영감을 얻었습니다 : https://stackoverflow.com/a/46008856/4110122
이 기능을 사용 하여 객체의 값을 가져 오기 / 설정 / 설정 해제 할 수 있습니다
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;
}
}
그것을 사용하려면 :
// 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');
코딩 타임에 알지 못하고 다른 중첩 키에 액세스 해야하는 경우 (키를 다루는 것이 쉽지 않을 것입니다) 배열 표기법 접근자를 사용할 수 있습니다.
var part1name = someObject['part1']['name'];
var part2quantity = someObject['part2']['qty'];
var part3name1 = someObject['part3'][0]['name'];
이들은 점 표기법 접근 자와 동일하며 런타임에 다음과 같이 달라질 수 있습니다.
var part = 'part1';
var property = 'name';
var part1name = someObject[part][property];
에 해당
var part1name = someObject['part1']['name'];
또는
var part1name = someObject.part1.name;
나는 이것이 당신의 질문을 해결하기를 바랍니다
편집하다
객체 값에 액세스하기 위해 일종의 xpath 쿼리 를 유지 하기 위해 문자열을 사용하지 않습니다 . 쿼리를 구문 분석하고 값을 검색하는 함수를 호출해야하므로 다른 경로를 따르지 않습니다 (:
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);
또는 apply 메소드 가 마음에 들지 않으면
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);
함수는 더 짧고 명확하며 인터프리터는 구문 오류 등을 확인합니다.
그건 그렇고, 적절한시기에 이루어진 간단한 과제가 충분하다고 생각합니다 ...
최근에 같은 질문이 있었고 객체 / 배열 도 중첩 된 https://npmjs.org/package/tea-properties 를 성공적으로 사용했습니다 set
.
가져 오기:
var o = {
prop: {
arr: [
{foo: 'bar'}
]
}
};
var properties = require('tea-properties');
var value = properties.get(o, 'prop.arr[0].foo');
assert(value, 'bar'); // true
세트:
var o = {};
var properties = require('tea-properties');
properties.set(o, 'prop.arr[0].foo', 'bar');
assert(o.prop.arr[0].foo, 'bar'); // true
여기에있는 솔루션은 깊이 중첩 된 키에 액세스하기위한 것입니다. 키에 액세스, 추가, 수정 및 삭제하기 위해 하나가 필요했습니다. 이것이 내가 생각해 낸 것입니다.
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
: 배열의 경로. 로 교체 할 수 있습니다string_path.split(".")
.type_of_function
: 액세스 (0에 값을 전달하지value
않음)의 경우 0, 추가 및 수정의 경우 0 삭제하려면 1입니다.
문자열 대신 배열을 중첩 된 객체와 배열에 사용할 수 있습니다. 예 : ["my_field", "another_field", 0, "last_field", 10]
다음은이 배열 표현을 기반으로 필드를 변경하는 예입니다. 중첩 된 구조의 상태를 변경하는 제어 된 입력 필드에 react.js에서 이와 같은 것을 사용하고 있습니다.
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);
이전 답변을 바탕으로 대괄호를 처리 할 수있는 함수를 만들었습니다. 그러나 분할로 인해 내부에 점이 없습니다.
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);
}
// (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"]));
작업 Underscore
의 property
나 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>
행운을 빕니다...
React로 온라인 상점을 개발 중입니다. 제출시 원래 상태를 업데이트하기 위해 복사 된 상태 객체의 값을 변경하려고했습니다. 위의 예제는 대부분 복사 된 객체의 구조를 변경하기 때문에 효과가 없었습니다. 깊게 중첩 된 객체 속성의 값에 액세스하고 변경하는 함수의 작동 예를 찾았습니다. https://lowrey.me/create-an-object-by-path-in-javascript-2/ 여기에 있습니다 :
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;
};
Mohamad Hamouday 'Answer의 연장은 빠진 열쇠를 채울 것입니다
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;
}
}
예
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" } }
이 솔루션은 어떻습니까?
setJsonValue: function (json, field, val) {
if (field !== undefined){
try {
eval("json." + field + " = val");
}
catch(e){
;
}
}
}
그리고 이것은 다음을 얻습니다.
getJsonValue: function (json, field){
var value = undefined;
if (field !== undefined) {
try {
eval("value = json." + field);
}
catch(e){
;
}
}
return value;
};
아마도 일부는 안전하지 않은 것으로 간주하지만 문자열을 구문 분석하는 것보다 훨씬 빠릅니다.
참고 URL : https://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key
'Programming' 카테고리의 다른 글
현재 C 또는 C ++ 표준 문서는 어디에서 찾을 수 있습니까? (0) | 2020.02.22 |
---|---|
Jquery를 사용하여 CSS 표시 없음을 변경하거나 속성을 차단하는 방법은 무엇입니까? (0) | 2020.02.22 |
jQuery를 사용하여 배열에서 특정 값을 제거하는 방법 (0) | 2020.02.22 |
더 큰 div 안에 이미지 센터를 (세로 및 가로로) 만드는 방법 (0) | 2020.02.22 |
JavaScript 문자열 개행 문자? (0) | 2020.02.21 |