다음과 같은 데이터 구조가 있습니다.
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'
답변
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
답변
문자열을 직접 파싱해야합니다.
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";
구문 분석이 쉬워집니다.
답변
객체 내부의 배열 / 배열에서도 작동합니다. 유효하지 않은 값에 방어 적입니다.
/**
* 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>
답변
eval을 사용하여 :
var part1name = eval("someObject.part1.name");
랩은 에러시에 undefined를 돌려 준다
function path(obj, path) {
try {
return eval("obj." + path);
} catch(e) {
return undefined;
}
}
http://jsfiddle.net/shanimal/b3xTw/
평가의 힘을 발휘할 때는 상식과주의를 기울이십시오. 가벼운 세이버와 비슷합니다. 전원을 켜면 사지가 끊어 질 확률이 90 %입니다. 모두를위한 것은 아닙니다.