들어가기
객체 내에 특정 속성을 같은 값는 있는지 확인이 필요할 때가 있다. 속성을 지칭하는 키 길이 긴 경우에 확인하기 쉽지 않다. 예를 들어 "obj.data[1].item"이란 형태로 되어 있는 경우이다. 여기서는 해당 키가 문자열로 입력되고 특정 객체에서 문자열로 준 키에 해당하는 속성이 있는지 확인하는 방법을 소개하려고 한다.
작성자: ospace114@empal.com, http://ospace.tistory.com/
확인하는 방법
문자열로 된 키로 객체에 속성이 있는지 확인하는 방법이다. 예를 들어 다음과 같은 문자열 키들이다.
'info.name'
'info["name"]'
'data[0].item.value'
'data[0]["item"]["value"]'
방법은 단순하다. 위에 키들을 앞에서 순서대로 파싱해서 각각 속성 값을 추출하고 해당 속성이 있는지 검증한다.
실행결과는 키 값에서 존재하는 속성까지 표시된다. 아에 없다면 false가 된다.
function isalpha(c) {
return ("a" <= c && c <= "z") || ("A" <= c && c <= "Z") || "_" === c;
}
function isnum(c) {
return "0" <= c && c <= "9";
}
function hasProp(obj, prop) {
let [i, c, step, b_str, begin, end] = [0, 0, 1, 0, 0, 0, 0];
const keys = [];
const checkProp = (l, r) => {
if (l === r) return true;
const key = prop.substring(l, r);
if (!obj.hasOwnProperty(key)) return false;
obj = obj[key];
if ('function' === typeof obj) return false;
keys.push(key);
return true;
};
for (i = 0; i < prop.length; ++i) {
c = prop.charAt(i);
if (2 === step) {
if ('"' === c || "'" === c) {
++begin;
let b_str = c;
++i;
for (; i < prop.length; ++i) {
c = prop.charAt(i);
if ("\\" == c) ++i;
else if (b_str === c) break;
}
end = i;
c = prop.charAt(++i);
} else if (isnum(c)) {
++i;
for (; i < prop.length; ++i) {
c = prop.charAt(i);
if (!isnum(c)) break;
}
end = i;
}
if ("]" === c) {
step = 0;
} else {
throw Error(`invalid expression at ${i}: ${prop}`);
}
if (step) continue;
}
if (1 === step) {
if (isalpha(c) || "$" === c || (i && isnum(c))) continue;
if ("[" === c) {
end = i;
step = 2;
} else if ("." === c) {
end = i;
}
}
if (!checkProp(begin, end)) {
return keys.length ? keys.join(".") : false;
}
begin = end = i + 1;
if (0 === step) step = 1;
}
if (!(0 === step || 1 === step)) {
throw new Error(`invalid expression at ${i}: ${prop}`);
}
if (!checkProp(begin, i)) {
return keys.length ? keys.join(".") : false;
}
return keys.length ? keys.join(".") : false;
}
한번 테스트해보자.
let obj = { info:{name: 'foo'}, data:[{item:{value:10}}], etc: undefined };
console.log(hasProp(obj, 'info.name'));
// info.name
console.log(hasProp(obj, 'info["name"]'));
// info.name
console.log(hasProp(obj, 'data[0].item.value'));
// data.0.item.value
console.log(hasProp(obj, 'data[0]["item"]["value"]'));
// data.0.item.value
console.log(hasProp(obj, 'data[1].item'));
// data
console.log(hasProp(obj, 'foo'));
// false
마침
필요하신 분이 있을 지 모르겠지만, 참고되시라고 올렸습니다. 모두 즐프하세요. ospace.
반응형
'3.구현 > HTML5&Javascript' 카테고리의 다른 글
[Javascript] Javascript의 prototype에 대한 고찰 (0) | 2024.01.11 |
---|---|
[javascript] 예외활용한 유효성 검사 (0) | 2024.01.02 |
[javascript] 객체 변경 감지 (0) | 2023.11.05 |
[javascript] 자바스크립트 중급자는 이것만 알고가자 2 (2) | 2023.11.03 |
[javascript] 자바스크립트 중급자는 이것만 알고가자 1 (0) | 2023.11.02 |