๋ฉํํ๋ก๊ทธ๋๋ฐ
Proxy
์ Reflect
๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ฉด ๊ธฐ๋ณธ ์ธ์ด ๋์(์: ์์ฑ ์กฐํ, ํ ๋น, ์ด๊ฑฐ, ํจ์ ํธ์ถ ๋ฑ)์ ๊ฐ๋ก์ฑ๊ณ ์ฌ์ฉ์ ์ ์ ๋์์ ์ ์ํ ์ ์์ต๋๋ค. ์ด ๋ ๊ฐ์ฒด๋ฅผ ํ์ฉํ๋ฉด JavaScript์์ ๋ฉํํ๋ก๊ทธ๋๋ฐ์ ํ ์ ์์ต๋๋ค.
ํ๋ก์
Proxy
๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ฉด ํน์ ๋์์ ๊ฐ๋ก์ฑ๊ณ ์ฌ์ฉ์ ์ ์ ๋์์ ๊ตฌํํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ๊ฐ์ฒด์์ ์์ฑ์ ๊ฐ์ ธ์ค๋ ๊ฒฝ์ฐ,
const handler = {
get(target, name) {
return name in target ? target[name] : 42;
},
};
const p = new Proxy({}, handler);
p.a = 1;
console.log(p.a, p.b); // 1, 42
Proxy
๊ฐ์ฒด๋ target
(์ฌ๊ธฐ์๋ ๋น ๊ฐ์ฒด)๊ณผ get
ํจ์ ์ด ๊ตฌํ๋ handler
๊ฐ์ฒด๋ฅผ ์ ์ํฉ๋๋ค. ์ฌ๊ธฐ์๋ ํ๋ก์๋ ๊ฐ์ฒด๊ฐ ์ ์๋์ง ์์ ์์ฑ์ ๊ฐ์ ธ์ฌ ๋ undefined
๋ฅผ ๋ฐํํ์ง ์๊ณ ๋์ ์ซ์ 42
๋ฅผ ๋ฐํํฉ๋๋ค.
์ถ๊ฐ ์์ ๋ Proxy
์ฐธ๊ณ ํ์ด์ง์์ ํ์ธํ ์ ์์ต๋๋ค.
์ฉ์ด
ํ๋ก์ ๊ธฐ๋ฅ์ ์ค๋ช ํ ๋ ๋ค์ ์ฉ์ด๊ฐ ์ฌ์ฉ๋ฉ๋๋ค.
- handler
-
ํธ๋ฉ์ ํฌํจํ๋ ์๋ฆฌ ํ์์ ๊ฐ์ฒด์ ๋๋ค.
- traps
-
์์ฑ ์ ๊ทผ๊ณผ ๊ฐ์ ๋์์ ์ ๊ณตํ๋ ๋ฉ์๋์ ๋๋ค. (์ด์์ฒด์ ์ 'ํธ๋ฉ' ๊ฐ๋ ๊ณผ ์ ์ฌํฉ๋๋ค.)
- target
-
ํ๋ก์๊ฐ ๊ฐ์ํํ๋ ๊ฐ์ฒด์ ๋๋ค. ํ๋ก์์ ์ ์ฅ์ ๋ฐฑ์๋๋ก ์์ฃผ ์ฌ์ฉ๋ฉ๋๋ค. ๊ฐ์ฒด์ ํ์ฅ ๋ถ๊ฐ ์ฌ๋ถ๋ ์ค์ ๋ถ๊ฐ ์์ฑ ๊ด๋ จ ๋ถ๋ณ์ฑ(๋ณ๊ฒฝ๋์ง ์๋ ์๋ฏธ)์ target์ ๊ธฐ์ค์ผ๋ก ๊ฒ์ฆ๋ฉ๋๋ค.
- invariants
-
์ฌ์ฉ์ ์ ์ ๋์์ ๊ตฌํํ ๋ ์ง์ผ์ผ ํ๋ '๋ถ๋ณ์ฑ'์ ์๋ฏธํฉ๋๋ค. ํธ๋ค๋ฌ์ ๋ถ๋ณ์ฑ์ ์๋ฐํ๋ฉด
TypeError
๊ฐ ๋ฐ์ํฉ๋๋ค.
ํธ๋ค๋ฌ์ ํธ๋ฉ
๋ค์ ํ๋ Proxy
๊ฐ์ฒด์์ ์ฌ์ฉํ ์ ์๋ ํธ๋ฉ์ ์์ฝํ ๊ฒ์
๋๋ค. ์์ธํ ์ค๋ช
๊ณผ ์์ ๋ ์ฐธ์กฐ ํ์ด์ง๋ฅผ ํ์ธํ์ธ์.
์ทจ์ ๊ฐ๋ฅํ Proxy
Proxy.revocable()
๋ฉ์๋๋ ์ทจ์ ๊ฐ๋ฅํ Proxy
๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด ๊ฒฝ์ฐ revoke
ํจ์๋ฅผ ํตํด ํ๋ก์๋ฅผ ๋นํ์ฑํํ ์ ์์ต๋๋ค.
์ดํ ํ๋ก์์ ๋ํ ๋ชจ๋ ๋์์ TypeError
๋ฅผ ๋ฐ์์ํต๋๋ค.
const revocable = Proxy.revocable(
{},
{
get(target, name) {
return `[[${name}]]`;
},
},
);
const proxy = revocable.proxy;
console.log(proxy.foo); // "[[foo]]"
revocable.revoke();
console.log(proxy.foo); // TypeError: ์ทจ์๋ ํ๋ก์์์ 'get'์ ์ํํ ์ ์์ต๋๋ค
proxy.foo = 1; // TypeError: ์ทจ์๋ ํ๋ก์์์ 'set'์ ์ํํ ์ ์์ต๋๋ค
delete proxy.foo; // TypeError: ์ทจ์๋ ํ๋ก์์์ 'deleteProperty'๋ฅผ ์ํํ ์ ์์ต๋๋ค
console.log(typeof proxy); // "object", typeof๋ ํธ๋ฉ์ ์คํํ์ง ์์ต๋๋ค
๋ฆฌํ๋ ์ (Reflection)
Reflect
๋ ์๋ฐ์คํฌ๋ฆฝํธ์์ ๊ฐ๋ก์ฑ๊ธฐ ๊ฐ๋ฅํ ์ฐ์ฐ์ ์ํํ ์ ์๋ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ ๋ด์ฅ ๊ฐ์ฒด์
๋๋ค. ์ด ๋ฉ์๋๋ค์ ํ๋ก์ ํธ๋ค๋ฌ์ ๋ฉ์๋์ ๋์ผํฉ๋๋ค.
Reflect
๋ ํจ์ ๊ฐ์ฒด๊ฐ ์๋๋๋ค.
Reflect
๋ ๊ธฐ๋ณธ ๋์์ ํธ๋ค๋ฌ์์ target
์ผ๋ก ์ ๋ฌํ ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด, Reflect.has()
๋ฅผ ์ฌ์ฉํ๋ฉด in
์ฐ์ฐ์๋ฅผ ํจ์์ฒ๋ผ ์ฌ์ฉํ ์ ์์ต๋๋ค:
Reflect.has(Object, "assign"); // true
๋ ๋์ apply() ํจ์
Reflect
๊ฐ ๋ฑ์ฅํ๊ธฐ ์ ์๋, ์ฃผ์ด์ง this
๊ฐ๊ณผ ๋ฐฐ์ด(๋๋ ์ ์ฌ ๋ฐฐ์ด ๊ฐ์ฒด)๋ก ์ ๊ณต๋ arguments
๋ฅผ ์ฌ์ฉํ์ฌ ํจ์๋ฅผ ํธ์ถํ ๋ ์ฃผ๋ก Function.prototype.apply()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ต๋๋ค.
Function.prototype.apply.call(Math.floor, undefined, [1.75]);
ํ์ง๋ง Reflect.apply
๋ฅผ ์ฌ์ฉํ๋ฉด ๋ ๊ฐ๊ฒฐํ๊ณ ์ดํดํ๊ธฐ ์ฌ์์ง๋๋ค.
Reflect.apply(Math.floor, undefined, [1.75]);
// 1
Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111]);
// "hello"
Reflect.apply(RegExp.prototype.exec, /ab/, ["confabulation"]).index;
// 4
Reflect.apply("".charAt, "ponies", [3]);
// "i"
์์ฑ ์ ์ ์ฑ๊ณต ์ฌ๋ถ ํ์ธ
Object.defineProperty
๋ ์์ฑ ์ ์์ ์ฑ๊ณตํ๋ฉด ๊ฐ์ฒด๋ฅผ ๋ฐํํ๊ณ , ์คํจํ๋ฉด TypeError
๋ฅผ ๋ฐ์์ํต๋๋ค. ๋ฐ๋ผ์ ์์ฑ์ ์ ์ํ๋ฉด์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋์ง ํ์ธํ๋ ค๋ฉด try...catch
๋ธ๋ก์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ๋ฐ๋ฉด, Reflect.defineProperty()
๋ ์ฑ๊ณต ์ฌ๋ถ๋ฅผ ๋ถ๋ฆฌ์ธ ๊ฐ์ผ๋ก ๋ฐํํ๋ฏ๋ก, ๋จ์ํ if...else
๋ธ๋ก์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค:
if (Reflect.defineProperty(target, property, attributes)) {
// ์ฑ๊ณต
} else {
// ์คํจ
}