Proxy는 특정 객체를 감싸 프로퍼티 읽기, 쓰기와 같은 객체에 가해지는 작업을 중간에서 가로채는 객체
let proxy = new Proxy(target, handler);
let obj = {
age:43,
};
let proxy = new Proxy(obj,{});
proxy.age1 = 1;
console.log(obj);
핸들러가 지정되지 않으면 proxy에 가해지는 모든 작업이 obj에 똑같이 적용된다.
자바스크립트 객체에는 [[prototype]]과 같은 숨김속성이 있듯이 숨김메소드가 있다.
[[Get]] get 프로퍼티를 읽을 때
[[Set]] set 프로퍼티에 쓸 때
[[HasProperty]] has in 연산자가 동작할 때
[[Delete]] deleteProperty delete 연산자가 동작할 때
[[Call]] apply 함수를 호출할 때
[[Construct]] construct new 연산자가 동작할 때
[[GetPrototypeOf]] getPrototypeOf Object.getPrototypeOf
[[SetPrototypeOf]] setPrototypeOf Object.setPrototypeOf
[[IsExtensible]] isExtensible Object.isExtensible
[[PreventExtensions]] preventExtensions Object.preventExtensions
[[DefineOwnProperty]] defineProperty Object.defineProperty, Object.defineProperties
[[GetOwnProperty]] getOwnPropertyDescriptor Object.getOwnPropertyDescriptor, for..in, Object.keys/values/entries
[[OwnPropertyKeys]] ownKeys Object.getOwnPropertyNames, Object.getOwnPropertySymbols, for..in, Object/keys/values/entries
외부적으로 객체의 프로퍼티에 접근할땐 [[Get]]이라는 숨김메서드가 작동하고 프로퍼티에 쓸땐 [[Set]]이라는 숨김메서드가 작동하는 것이다.
이러한 숨김메소드는 당연히 사용자가 호출할 수 없는 메소드들이다.
Proxy객체는 숨김메소드를 가로채어 사용자에게 여러작업을 할 수 있도록 수 있도록 하는 객체다.
Proxy객체 사용조건
let user = {
name: "John",
age: 30,
_password: "***"
};
user = new Proxy(user,{
ownKeys(obj){
return Object.keys(obj).filter(key=>{
if(!key.startsWith('_')){
return true;
}
});
}
});
console.log(Object.keys(user));
let user = { };
user = new Proxy(user, {
ownKeys(target) {
return ['a', 'b', 'c'];
}
getOwnPropertyDescriptor(obj,prop){
return {
enumerable:true,
configurable:true
}
}
});
for (const key in user) {
console.log(key);
}
for in, Object.keys, Object.values 메소드는 반복시 내부적으로 [[GetOwnProperty]]를 호출하여 enumerable속성을 확인한다.
let user = {
name: "John",
_password: "***",
checkPassword(pass:string){
return pass == this._password;
}
};
user = new Proxy(user,{
get(target,prop:string){
if(prop.startsWith('_')){
throw new Error("_ not permit");
}
return (typeof target[prop] == 'function' )?target[prop].bind(target):prop;
}
});
console.log( user.checkPassword('123') );
this가있는 핸들러를 get에서 바인딩하여 반환한다.
function sayHi(user) {
alert(Hello, ${user}!);
}
sayHi = delay(sayHi, 3000);
alert(sayHi.length); // 1 (*) 프락시는 "get length" 연산까지 타깃 객체에 전달해줍니다.
sayHi("John");