정적타입의 언어를 사용한다면, int arr[]; 이와 같이 정수만 들어가는 배열을 만들 수 있다. 하지만 javaScript는 동적 타입의 언어이다. 뭐 물론 정적타입이 필요하면 typeScript를 사용하는 것은 꽤 좋은 선택이다.
하지만, 지금 제안할 내용은 자바스크립트에서 간단하게 타입이 제한된 배열이 필요할 때 사용할 수 있는 방법을 소개하고자 한다.
Proxy
혹시라도 해당 단어를 처음 보는 분을 위해서 단어 뜻을 말하면 대리인 정도로 해석 하면 된다. 뭐 개발자라면 프록시 서버라는 말은 자주 들어봤을 거라고 생각한다.
기본적인 사용법은 아래와 같다.
proxy변수에 행해지는 행위가 target에 전달된다고 보면 된다. 지금은 proxy가 아무런 행위도 하지 않기 때문에, target을 직접 핸들링하는 것과 다르지 않다.
const target = []
const proxy = new Proxy(target, {})
proxy.push(1)
proxy.push(2)
proxy.push(3)
proxy.push('a')
console.log(proxy.join(', '))
// 1, 2, 3, a
console.log(target.join(', '))
// 1, 2, 3, a
get 트랩
proxy에서 값을 읽을 때, 값을 읽을 때 실행 되는 트랩으로 기본 값을 특정값으로 쓰고 싶거나, 중간에 형변환이 필요할 때 사용 할 수 있다.
get(target, property, receiver): get메서드는 프로퍼티를 읽으려고 할 때 동작을 가로챈다.
target: 동작을 전달할 객체로 new Proxy의 첫 번째 이다.
property: 읽으려고 하는 속성의 이름이다.
( 주의: proxy[0]과 같이 숫자를 전달해도 문자열 '0'이니 참조하기 바란다. )
receiver: 설명이 길어지고 해당 예제에는 사용 되지 않으니 설명 생략.
const target = [1, '123a', 3, 'a']
const proxy = new Proxy(target, {
get(target, prop) {
return Number.isInteger(+prop) ? parseInt(target[prop]) : target[prop]
}
})
console.log(proxy.join(', '))
// 1, 123, 3, NaN
console.log(target.join(', '))
// 1, 123a, 3, a
proxy의 속성을 읽을 때, 트랩을 추가하여, 해당 속성의 값을 변경할 수 있다.
위에서 주의 할 점은 "Number.isInteger(+prop)"이다. join함수를 사용 할 때도 get트랩에 적용이 되니, 유효한 키인지 확인 하는 절차를 꼭 해주어야 한다.
set 트랩
이번 포스트의 주제는 set트랩을 사용하여 구현이 가능한 부분이다. 바로 정수만 입력가능한 set 트랩을 설정해보도록 하자. get트랩이랑 비슷하게 설정하면 된다.
set(target, property, value, receiver): set메서드는 프로퍼티를 값을 쓰려고 할 때, 동작을 가로챈다. 올바른 값을 쓴 경우에는 truthy반환 실패한 경우에는 falsy를 반환을 하도록 하자. 잘못된 값 입력을 error로 처리하기 위함이다.
target: 동작을 전달할 객체로 new Proxy의 첫 번째 이다.
property: 쓰려고 하는 속성의 이름이다.
value: 쓰려고 하는 값이다.
receiver: 설명이 길어지고 해당 예제에는 사용 되지 않으니 설명 생략.
const target = []
const proxy = new Proxy(target, {
set(target, prop, value) {
if( Number.isInteger(value) ) {
target[prop] = value
return true
}
}
})
target.push(1)
target.push('2')
proxy.push(3)
try { proxy.push('4') } catch {}
console.log(proxy.join(', '))
// 1, 2, 3
console.log(target.join(', '))
// 1, 2, 3
위와 같이 값의 입력 당시에 데이터의 형태를 확인 할 수 있다. 이것을 좀 응용 하면 타입이 있는 배열을 만들 수 있다.
타입이 있는 배열
작성 방법은 꽤 간단하다.
function initTypedArray(type, target = []) {
return new Proxy(target, {
set(target, prop, value) {
if(typeof value === type || !Number.isInteger(+prop)) {
target[prop] = value
return true
}
}
})
}
const strArray = initTypedArray('string')
strArray.push('hello')
strArray.push('world')
try { strArray.push(1) } catch {}
console.log(strArray.join(', '))
// hello, world
주의점이라고 하면, push를 하게 되면 length를 set을 하기 때문에 !Number.isInteger(+prop)를 꼭 추가할 수 있도록 하자.
간단하게 작성된 만큼 빈틈은 당연히 있다. 바로 보이는 문제만 보더라도 symbol속성을 접근을 하게 되면, 바로 에러가 날 것이다. 하지만, 뭐 proxy를 처음 접근해보는 사람에게는 꽤 괜찮은 내용이라고 생각된다.
댓글
댓글 쓰기