점 표기 문자열을 사용하여 객체 자식 속성 액세스
저는 일시적으로 매우 간단한 자바스크립트 문제에 시달리고 있지만, 아마도 올바른 검색 키워드를 놓치고 있는 것 같습니다!
우리에게 목표가 있다고 가정해 보세요.
var r = { a:1, b: {b1:11, b2: 99}};
99에 액세스하는 방법은 여러 가지가 있습니다.
r.b.b2
r['b']['b2']
내가 원하는 것은 문자열을 정의할 수 있는 것입니다.
var s = "b.b2";
99에 액세스하려면 다음을 사용합니다.
r.s or r[s] //(which of course won't work)
한 가지 방법은 점에서 문자열을 분할하고 재귀적/반복적으로 속성을 얻을 수 있는 함수를 작성하는 것입니다.하지만 더 단순하고 더 효율적인 방법이 있을까요?여기 있는 jQuery API 중에 유용한 것이 있습니까?
여기 얼마 전에 작성한 단순 함수가 있지만 기본 개체 속성에 사용할 수 있습니다.
function getDescendantProp(obj, desc) {
var arr = desc.split(".");
while(arr.length && (obj = obj[arr.shift()]));
return obj;
}
console.log(getDescendantProp(r, "b.b2"));
//-> 99
어레이 인덱스 액세스를 "허용"하도록 확장하는 답변이 있지만, 다음 방법으로 도트 표기법을 사용하여 숫자 인덱스를 지정할 수 있기 때문에 그렇게 할 필요는 없습니다.
getDescendantProp({ a: [ 1, 2, 3 ] }, 'a.2');
//-> 3
객체를 전달하는 동안 분할 및 축소initalValue
업데이트(TeChn4K가 게시한 댓글 덕분)
ES6 구문을 사용하면 훨씬 더 짧아집니다.
var r = { a:1, b: {b1:11, b2: 99}};
var s = "b.b2";
var value = s.split('.').reduce((a, b) => a[b], r);
console.log(value);
이전 버전
var r = { a:1, b: {b1:11, b2: 99}};
var s = "b.b2";
var value = s.split('.').reduce(function(a, b) {
return a[b];
}, r);
console.log(value);
lodash get() 및 set() 메서드를 사용할 수 있습니다.
점점 ~하다
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.get(object, 'a[0].b.c');
// → 3
설정
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// → 4
시나리오에서 찾고 있는 전체 어레이 변수를 문자열에 넣을 수 있는 경우eval()
기능.
var r = { a:1, b: {b1:11, b2: 99}};
var s = "r.b.b2";
alert(eval(s)); // 99
나는 사람들이 공포에 떠는 것을 느낄 수 있습니다.
@JohnB의 답변을 확장하여 setter 값도 추가하였습니다.플런크랫을 확인해 보세요.
http://plnkr.co/edit/lo0thC?p=preview
function getSetDescendantProp(obj, desc, value) {
var arr = desc ? desc.split(".") : [];
while (arr.length && obj) {
var comp = arr.shift();
var match = new RegExp("(.+)\\[([0-9]*)\\]").exec(comp);
// handle arrays
if ((match !== null) && (match.length == 3)) {
var arrayData = {
arrName: match[1],
arrIndex: match[2]
};
if (obj[arrayData.arrName] !== undefined) {
if (typeof value !== 'undefined' && arr.length === 0) {
obj[arrayData.arrName][arrayData.arrIndex] = value;
}
obj = obj[arrayData.arrName][arrayData.arrIndex];
} else {
obj = undefined;
}
continue;
}
// handle regular things
if (typeof value !== 'undefined') {
if (obj[comp] === undefined) {
obj[comp] = {};
}
if (arr.length === 0) {
obj[comp] = value;
}
}
obj = obj[comp];
}
return obj;
}
이게 제가 할 수 있는 가장 간단한 일입니다.
var accessProperties = function(object, string){
var explodedString = string.split('.');
for (i = 0, l = explodedString.length; i<l; i++){
object = object[explodedString[i]];
}
return object;
}
var r = { a:1, b: {b1:11, b2: 99}};
var s = "b.b2";
var o = accessProperties(r, s);
alert(o);//99
당신은 또한 할 수 있습니다.
var s = "['b'].b2";
var num = eval('r'+s);
다음은 배열로 재귀하고 모든 값을 반환하는 Andy E의 코드 확장입니다.
function GetDescendantProps(target, pathString) {
var arr = pathString.split(".");
while(arr.length && (target = target[arr.shift()])){
if (arr.length && target.length && target.forEach) { // handle arrays
var remainder = arr.join('.');
var results = [];
for (var i = 0; i < target.length; i++){
var x = this.GetDescendantProps(target[i], remainder);
if (x) results = results.concat(x);
}
return results;
}
}
return (target) ? [target] : undefined; //single result, wrap in array for consistency
}
그래서 이것을 고려할 때.target
:
var t =
{a:
{b: [
{'c':'x'},
{'not me':'y'},
{'c':'z'}
]
}
};
다음을 얻을 수 있습니다.
GetDescendantProps(t, "a.b.c") === ["x", "z"]; // true
지원되는 jQuery API 기능은 모르지만 다음과 같은 기능이 있습니다.
var ret = data; // Your object
var childexpr = "b.b2"; // Your expression
if (childexpr != '') {
var childs = childexpr.split('.');
var i;
for (i = 0; i < childs.length && ret != undefined; i++) {
ret = ret[childs[i]];
}
}
return ret;
Andy E의 답변을 확장하여 배열도 처리할 수 있도록 했습니다.
function getDescendantProp(obj, desc) {
var arr = desc.split(".");
//while (arr.length && (obj = obj[arr.shift()]));
while (arr.length && obj) {
var comp = arr.shift();
var match = new RegExp("(.+)\\[([0-9]*)\\]").exec(comp);
if ((match !== null) && (match.length == 3)) {
var arrayData = { arrName: match[1], arrIndex: match[2] };
if (obj[arrayData.arrName] != undefined) {
obj = obj[arrayData.arrName][arrayData.arrIndex];
} else {
obj = undefined;
}
} else {
obj = obj[comp]
}
}
return obj;
}
Regex를 수행하는 데 더 효율적인 방법이 있을 수 있지만, 그것은 소형입니다.
이제 다음과 같은 작업을 수행할 수 있습니다.
var model = {
"m1": {
"Id": "22345",
"People": [
{ "Name": "John", "Numbers": ["07263", "17236", "1223"] },
{ "Name": "Jenny", "Numbers": ["2", "3", "6"] },
{ "Name": "Bob", "Numbers": ["12", "3333", "4444"] }
]
}
}
// Should give you "6"
var x = getDescendantProp(model, "m1.People[1].Numbers[2]");
Andy E's, Jason More's 및 나만의 솔루션에 대한 성능 테스트는 http://jsperf.com/propertyaccessor 에서 이용할 수 있습니다.수집된 데이터에 추가하기 위해 사용자의 브라우저를 사용하여 자유롭게 테스트를 실행하십시오.
예후는 확실해요, 앤디 E의 해결책이 지금까지 가장 빨라요!
관심 있는 분들을 위해, 여기 원래 질문에 대한 제 해결책의 코드가 있습니다.
function propertyAccessor(object, keys, array) {
/*
Retrieve an object property with a dot notation string.
@param {Object} object Object to access.
@param {String} keys Property to access using 0 or more dots for notation.
@param {Object} [array] Optional array of non-dot notation strings to use instead of keys.
@return {*}
*/
array = array || keys.split('.')
if (array.length > 1) {
// recurse by calling self
return propertyAccessor(object[array.shift()], null, array)
} else {
return object[array]
}
}
짧은 대답: 아니요, 네이티브는 없습니다..access
원하는 대로 작동합니다.당신이 정확히 언급했듯이, 당신은 문자열을 분할하고 그 부분에 대해 루프/체크하는 당신만의 함수를 정의해야 할 것입니다.
물론, 여러분이 항상 할 수 있는 것은 (비록 나쁜 관행으로 여겨지더라도) 사용하는 것입니다.eval()
.
맘에 들다
var s = 'b.b2';
eval('r.' + s); // 99
여기에 @andy의 대답보다 조금 더 나은 방법이 있습니다, 어디에서.obj
(선택 사항)은 선택 사항이며, 다음으로 돌아갑니다.window
제공되지 않은 경우..
function getDescendantProp(desc, obj) {
obj = obj || window;
var arr = desc.split(".");
while (arr.length && (obj = obj[arr.shift()]));
return obj;
};
언급URL : https://stackoverflow.com/questions/8051975/access-object-child-properties-using-a-dot-notation-string
'programing' 카테고리의 다른 글
Python: 목록 위에서 반복하는 동안 목록 요소 제거 (0) | 2023.08.15 |
---|---|
안드로이드.뷰부풀리기예외:이진 XML 파일: 클래스 조각을 채우는 동안 오류가 발생했습니다. (0) | 2023.08.15 |
INSERT ... SELECT를 사용하여 잠금 대기 시간 초과를 방지하는 중 (0) | 2023.08.15 |
Access-Control-Allow-Origin 헤더로 여러 도메인을 처리하도록 Apache를 구성하는 방법은 무엇입니까? (0) | 2023.08.15 |
하위 창에서 인쇄 미리 보기가 열릴 때 Google Chrome이 Ajax 요청을 차단합니다. (0) | 2023.08.15 |