Reflect는 중간에서 가로챌 수 있는 JavaScript작업에 대한 메서드를 제공하는 내장객체다.
메서드의 종류는 프록시 처리기와 동일하며 Reflect는 함수객체가 아니기때문에 Proxy처럼 생성자로 사용할 수 없다.
obj[prop] Reflect.get(obj, prop) [[Get]]
obj[prop] = value Reflect.set(obj, prop, value) [[Set]]
delete obj[prop] Reflect.deleteProperty(obj, prop) [[Delete]]
new F(value) Reflect.construct(F, value) [[Construct]]
let user = {};
Reflect.set(user,'age',34);
console.log(user);
Reflect를 사용하면 연산자 (new, delete ...)를 함수 (Reflect.construct, Reflect.deleteProperty, ...)로 호출 할 수 있다.
let user = {
name: "John",
};
user = new Proxy(user, {
get(target, prop, receiver) {
alert(`GET ${prop}`);
return Reflect.get(target, prop, receiver); // (1)
},
set(target, prop, val, receiver) {
alert(`SET ${prop}=${val}`);
return Reflect.set(target, prop, val, receiver); // (2)
}
});
let name = user.name; // shows "GET name"
user.name = "Pete"; // shows "SET name=Pete"
위에서 target[prop]으로 처리해도 되는것을 Reflect를 이용했을때 이점을 생각해보자
set의 경우 Reflect는 반환값을 알아서 처리해주니 편한 이점이 있다.
Proxy get/set의 매개변수는 Reflect 매개변수와 같기때문에 get(...args)처럼 간략히 사용할 수 있다.
let user = {
_name: "Guest",
get name() {
return this._name;
}
};
let userProxy = new Proxy(user, {
get(target, prop, receiver) {
return target[prop]; // (*) target = user
}
});
let admin = {
__proto__: userProxy,
_name: "Admin"
};
// Expected: Admin
alert(admin.name);
admin이 userProxy를 상속받았을때 admin.name속성에 접근하면 proxy의 get이 호출되고 target[prop]으로 user의 getter가 호출되어 Guest가 반환된다.
proxy get에서 target[prop]이 user속성에 접근하게 되는 문제가 발생한다.
get(target, prop, receiver) receiver가 proxy객체인데 return receiver[prop]를 사용하면 자신접근을 발생하여 무한루프에 빠진다.
user getter가 this를 admin으로 참조하도록 해야한다.
let user = {
_name: "Guest",
get name() {
return this._name;
}
};
let userProxy = new Proxy(user, {
get(target, prop, receiver) { // receiver = admin
return Reflect.get(target, prop, receiver); // (*)
}
});
let admin = {
__proto__: userProxy,
_name: "Admin"
};
alert(admin.name); // Admin
Reflect.get(target, prop, receiver) 세번째인자를 전달하면 getter는 receiver를 this로 바인딩한다.