Baseline Widely available
Proxy
ê°ì²´ë¥¼ ì¬ì©íë©´ í ê°ì²´ì ëí 기본 ìì
ì ê°ë¡ì±ê³ ì¬ì ìíë íë¡ì를 ë§ë¤ ì ììµëë¤.
Proxy
ê°ì²´ë¥¼ ì¬ì©íë©´ ìë Object
ëì ì¬ì©í ì ìë ê°ì²´ë¥¼ ë§ë¤ì§ë§, ì´ ê°ì²´ì ìì± ê°ì ¸ì¤ê¸°, ì¤ì ë° ì ìì ê°ì 기본 ê°ì²´ ìì
ì ì¬ì ìí ì ììµëë¤. íë¡ì ê°ì²´ë ì¼ë°ì ì¼ë¡ ìì± ì¡ì¸ì¤ë¥¼ 기ë¡íê³ , ì
ë ¥ì ì í¨ì±ì ê²ì¬íê³ , íìì ì§ì íê±°ë, ìì íë ë° ì¬ì©ë©ëë¤.
ë ê°ì 매ê°ë³ì를 ì¬ì©íì¬ Proxy
를 ìì±í©ëë¤.
target
: íë¡ìí ì본 ê°ì²´handler
: ê°ë¡ì±ë ìì
ê³¼ ê°ë¡ì±ë ìì
ì ì¬ì ìíë ë°©ë²ì ì ìíë ê°ì²´ì
ëë¤.ì를 ë¤ì´ ìë ì½ëë ìì±ì´ ë ê°ë¿ì¸ ê°ë¨í ëìê³¼ ìì±ì´ ìë í¨ì¬ ë ê°ë¨í í¸ë¤ë¬ë¥¼ ì ìí©ëë¤.
const target = {
message1: "hello",
message2: "everyone",
};
const handler1 = {};
const proxy1 = new Proxy(target, handler1);
í¸ë¤ë¬ê° ë¹ì´ ì기 ë문ì ì´ íë¡ìë ìë ëìì²ë¼ ìëí©ëë¤.
console.log(proxy1.message1); // hello
console.log(proxy1.message2); // everyone
íë¡ì를 커ì¤í í기 ìí´ ì²ë¦¬ê¸° ê°ì²´ì í¨ì를 ì ìí©ëë¤.
const target = {
message1: "hello",
message2: "everyone",
};
const handler2 = {
get(target, prop, receiver) {
return "world";
},
};
const proxy2 = new Proxy(target, handler2);
ëì ê°ì²´ì ìì± ì¡ì¸ì¤ë¥¼ ê°ë¡ì±ë get()
ì²ë¦¬ê¸°ë¥¼ ì ê³µíìµëë¤.
ì²ë¦¬ê¸° í¨ìë ëì ê°ì²´ì ëí í¸ì¶ì ì¡ìë´ê¸° ë문ì í¸ë©(traps) ì´ë¼ê³ ë ë¶ë¦
ëë¤. ìì handler2
ì ìë ë§¤ì° ê°ë¨í í¸ë©ì 모ë ìì± ì ê·¼ì를 ì¬ì ìí©ëë¤.
console.log(proxy2.message1); // world
console.log(proxy2.message2); // world
Reflect
í´ëì¤ì ëìì¼ë¡ ì¼ë¶ ì ê·¼ììê² ìë ëìì ì ê³µíê³ ë¤ë¥¸ ì ê·¼ì를 ì¬ì ìí ì ììµëë¤.
const target = {
message1: "hello",
message2: "everyone",
};
const handler3 = {
get(target, prop, receiver) {
if (prop === "message2") {
return "world";
}
return Reflect.get(...arguments);
},
};
const proxy3 = new Proxy(target, handler3);
console.log(proxy3.message1); // hello
console.log(proxy3.message2); // world
ìì±ì
Proxy()
ì Proxy
ê°ì²´ë¥¼ ìì±í©ëë¤.
Proxy.revocable()
ì·¨ì ê°ë¥í Proxy
ê°ì²´ë¥¼ ìì±í©ëë¤.
ì´ ê°ë¨í ìììë ìì± ì´ë¦ì´ ê°ì²´ì ìì¼ë©´ ì«ì 37
ì 기본ê°ì¼ë¡ ë°íí©ëë¤. get()
ì²ë¦¬ê¸°ë¥¼ ì¬ì©í©ëë¤.
const handler = {
get(obj, prop) {
return prop in obj ? obj[prop] : 37;
},
};
const p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;
console.log(p.a, p.b);
// 1, undefined
console.log("c" in p, p.c);
// false, 37
No-op í¬ìë© íë¡ì
ì´ ìììë 기본 JavaScript ê°ì²´ë¥¼ ì¬ì©íì¬ íë¡ìê° ëª¨ë ìì ì ëì ê°ì²´ìê² ì ë¬í©ëë¤.
const target = {};
const p = new Proxy(target, {});
p.a = 37;
// ëì ê°ì²´ìê² ìì
ì ë¬
console.log(target.a);
// 37
// (ìì
ì´ ì ëë¡ ì ë¬ë¨!)
ì´ "no-op"ë ì¼ë° JavaScript ê°ì²´ì ëí´ ìëíì§ë§ DOM ìì, Map
ê°ì²´ ëë ë´ë¶ ì¬ë¡¯ì´ ìë 모ë 기본 ê°ì²´ìë ìëíì§ ììµëë¤. ìì¸í ë´ì©ì íë¼ì´ë¹ ìì± í¬ìë© ììì 참조íììì¤.
íë¡ìë ì¬ì í ë¤ë¥¸ ID를 ê°ì§ ë ë¤ë¥¸ ê°ì²´ë¡, ëíë ê°ì²´ì ì¸ë¶ ì¬ì´ìì ìëíë íë¡ìì¼ ë¿ì ëë¤. ë°ë¼ì íë¡ìë ìë ê°ì²´ì íë¼ì´ë¹ ìì±ì ì§ì ì ê·¼í ì ììµëë¤.
class Secret {
#secret;
constructor(secret) {
this.#secret = secret;
}
get secret() {
return this.#secret.replace(/\d+/, "[REDACTED]");
}
}
const aSecret = new Secret("123456");
console.log(aSecret.secret); // [REDACTED]
// no-op í¬ìë© ê°ì§ë§...
const proxy = new Proxy(aSecret, {});
console.log(proxy.secret); // TypeError: Cannot read private member #secret from an object whose class did not declare it
ì´ë íë¡ìì get
í¸ë©ì´ í¸ì¶ë ë this
ê°ì´ ìë secret
ì´ ìë proxy
ì´ë¯ë¡ #secret
ì ì¡ì¸ì¤í ì ì기 ë문ì
ëë¤. ì´ ë¬¸ì 를 í´ê²°íë ¤ë©´ ìë secret
ì this
ë¡ ì¬ì©íì¸ì.
const proxy = new Proxy(aSecret, {
get(target, prop, receiver) {
// 기본ì ì¼ë¡ 'this'ê°ì´ ë¤ë¥¸
// Reflect.get(target, prop, receiver)ì²ë¼ ë³´ì
ëë¤.
return target[prop];
},
});
console.log(proxy.secret);
ë©ìëì ê²½ì° ë©ìëì this
ê°ë ìë ê°ì²´ë¡ 리ëë ì
í´ì¼ í©ëë¤.
class Secret {
#x = 1;
x() {
return this.#x;
}
}
const aSecret = new Secret();
const proxy = new Proxy(aSecret, {
get(target, prop, receiver) {
const value = target[prop];
if (value instanceof Function) {
return function (...args) {
return value.apply(this === receiver ? target : this, args);
};
}
return value;
},
});
console.log(proxy.x());
ì¼ë¶ 기본 JavaScript ê°ì²´ìë JavaScript ì½ëìì ì¡ì¸ì¤í ì ìë ë´ë¶ ì¬ë¡¯ ì´ë¼ë ìì±ì´ ììµëë¤. ì를 ë¤ì´, Map
ê°ì²´ìë ë§µì í¤-ê° ìì ì ì¥íë [[MapData]]
ë¼ë ë´ë¶ ì¬ë¡¯ì´ ììµëë¤. ë°ë¼ì ë§µì ëí ì ë¬ íë¡ìë ê°ë¨íê² ë§ë¤ ì ììµëë¤.
const proxy = new Proxy(new Map(), {});
console.log(proxy.size); // TypeError: get size method called on incompatible Proxy
ì´ ë¬¸ì 를 í´ê²°íë ¤ë©´ ìì ì¤ëª
ë "this
-recovering" íë¡ì를 ì¬ì©í´ì¼ í©ëë¤.
íë¡ì를 ì¬ì©íë©´ ê°ì²´ì ëí´ ì ë¬ë ê°ì ì½ê² íì¸í ì ììµëë¤. ì´ ìì ììë set()
ì²ë¦¬ê¸°ë¥¼ ì¬ì©í©ëë¤.
const validator = {
set(obj, prop, value) {
if (prop === "age") {
if (!Number.isInteger(value)) {
throw new TypeError("The age is not an integer");
}
if (value > 200) {
throw new RangeError("The age seems invalid");
}
}
// ê°ì ì ì¥íë 기본 ëì
obj[prop] = value;
// ì±ê³µ íì
return true;
},
};
const person = new Proxy({}, validator);
person.age = 100;
console.log(person.age); // 100
person.age = "young"; // ìì¸ ë°ì
person.age = 300; // ìì¸ ë°ì
ìì±ì íì¥í기
í¨ì íë¡ìë ì ìì±ìë¡ ìì±ì를 ì½ê² íì¥í ì ììµëë¤. ì´ ìì ììë construct()
ê³¼ apply()
ì²ë¦¬ê¸°ë¥¼ ì¬ì©í©ëë¤.
function extend(sup, base) {
base.prototype = Object.create(sup.prototype);
base.prototype.constructor = new Proxy(base, {
construct(target, args) {
const obj = Object.create(base.prototype);
this.apply(target, obj, args);
return obj;
},
apply(target, that, args) {
sup.apply(that, args);
base.apply(that, args);
},
});
return base.prototype.constructor;
}
const Person = function (name) {
this.name = name;
};
const Boy = extend(Person, function (name, age) {
this.age = age;
});
Boy.prototype.gender = "M";
const Peter = new Boy("Peter", 13);
console.log(Peter.gender); // "M"
console.log(Peter.name); // "Peter"
console.log(Peter.age); // 13
DOM ë
¸ë ì¡°ì
ì´ ìììë Proxy
를 ì¬ì©íì¬ ë ê°ì ë¤ë¥¸ ììì ìì±ì í ê¸í©ëë¤. ë°ë¼ì í ììì ìì±ì ì¤ì íë©´ ë¤ë¥¸ ììì ìì±ì´ ì¤ì ëì§ ììµëë¤.
selected
ìì±ì ê°ì§ ê°ì²´ì ëí íë¡ìì¸ view
ê°ì²´ë¥¼ ìì±í©ëë¤. íë¡ì í¸ë¤ë¬ë set()
ì²ë¦¬ê¸°ë¥¼ ì ìí©ëë¤.
view.selected
ì HTML ìì를 í ë¹íë©´ ììì 'aria-selected'
ìì±ì´ true
ë¡ ì¤ì ë©ëë¤. ê·¸ë° ë¤ì view.selected
ì ë¤ë¥¸ ìì를 í ë¹íë©´ ì´ ììì 'aria-selected'
ìì±ì´ true
ë¡ ì¤ì ëê³ ì´ì ììì 'aria-selected'
ìì±ì´ ìëì¼ë¡ false
ë¡ ì¤ì ë©ëë¤.
const view = new Proxy(
{
selected: null,
},
{
set(obj, prop, newval) {
const oldval = obj[prop];
if (prop === "selected") {
if (oldval) {
oldval.setAttribute("aria-selected", "false");
}
if (newval) {
newval.setAttribute("aria-selected", "true");
}
}
// ê°ì ì ì¥íë기본 ëì
obj[prop] = newval;
// ì±ê³µ íì
return true;
},
},
);
const item1 = document.getElementById("item-1");
const item2 = document.getElementById("item-2");
// item1 ì í
view.selected = item1;
console.log(`item1: ${item1.getAttribute("aria-selected")}`);
// item1: true
// item2를 ì ííê³ item1ì ì í í´ì
view.selected = item2;
console.log(`item1: ${item1.getAttribute("aria-selected")}`);
// item1: false
console.log(`item2: ${item2.getAttribute("aria-selected")}`);
// item2: true
ê° ìì ë° ì¶ê° ìì±
products
íë¡ì ê°ì²´ë ì ë¬ë ê°ì ê³ì°íê³ íìí ê²½ì° ë°°ì´ë¡ ë³íí©ëë¤. ëí ê°ì²´ë getter ë° setter 모ëìê² latestBrowser
ë¼ë ì¶ê° ìì±ì ì§ìí©ëë¤.
const products = new Proxy(
{
browsers: ["Internet Explorer", "Netscape"],
},
{
get(obj, prop) {
// ì¶ê° ìì±
if (prop === "latestBrowser") {
return obj.browsers[obj.browsers.length - 1];
}
// ê°ì ì ì¥íë 기본 ëì
return obj[prop];
},
set(obj, prop, value) {
// ì¶ê° ìì±
if (prop === "latestBrowser") {
obj.browsers.push(value);
return true;
}
// ê°ì´ ë°°ì´ì´ ìë ê²½ì° ë°°ì´ë¡ ë³í
if (typeof value === "string") {
value = [value];
}
// ê°ì ì ì¥íë 기본 ëì
obj[prop] = value;
// ì±ê³µ íì
return true;
},
},
);
console.log(products.browsers);
// ['Internet Explorer', 'Netscape']
products.browsers = "Firefox";
// (ì¤ìë¡) 문ìì´ì ë겨ì¤
console.log(products.browsers);
// ['Firefox'] <- 문ì ìì´ ê°ì ë°°ì´ë¡ ë³íë¨
products.latestBrowser = "Chrome";
console.log(products.browsers);
// ['Firefox', 'Chrome']
console.log(products.latestBrowser);
// 'Chrome'
ìì±ì¼ë¡ ë°°ì´ ìì´í
ê°ì²´ 찾기
ì´ íë¡ìë ì¼ë¶ ì í¸ë¦¬í° 기ë¥ì¼ë¡ ë°°ì´ì íì¥í©ëë¤. ë³´ìë¤ìí¼ Object.defineProperties()
를 ì¬ì©íì§ ìê³ ë ìì±ì ì ì°íê² "ì ì"í ì ììµëë¤. ì´ ìì ë í´ë¹ ì
ë¡ í
ì´ë¸ íì ì°¾ë ë° ì ì©í ì ììµëë¤. ì´ ê²½ì° ëìì table.rows
ê° ë©ëë¤.
const products = new Proxy(
[
{ name: "Firefox", type: "browser" },
{ name: "SeaMonkey", type: "browser" },
{ name: "Thunderbird", type: "mailer" },
],
{
get(obj, prop) {
// ê°ì ì ì¥íë 기본 ëì. propì ë³´íµ int
if (prop in obj) {
return obj[prop];
}
// productì ì를 ê°ì ¸ì´. products.lengthì ëí ë³ì¹
if (prop === "number") {
return obj.length;
}
let result;
const types = {};
for (const product of obj) {
if (product.name === prop) {
result = product;
}
if (types[product.type]) {
types[product.type].push(product);
} else {
types[product.type] = [product];
}
}
// ì´ë¦ì¼ë¡ product ê°ì ¸ì¤ê¸°
if (result) {
return result;
}
// typeì¼ë¡ product ê°ì ¸ì¤ê¸°
if (prop in types) {
return types[prop];
}
// typesë¡ product ê°ì ¸ì¤ê¸°
if (prop === "types") {
return Object.keys(types);
}
return undefined;
},
},
);
console.log(products[0]); // { name: 'Firefox', type: 'browser' }
console.log(products["Firefox"]); // { name: 'Firefox', type: 'browser' }
console.log(products["Chrome"]); // undefined
console.log(products.browser); // [{ name: 'Firefox', type: 'browser' }, { name: 'SeaMonkey', type: 'browser' }]
console.log(products.types); // ['browser', 'mailer']
console.log(products.number); // 3
ìì í trap ìì
êµíì ì¸ ëª©ì ì¼ë¡ ìì í ìí traps
목ë¡ì ìì±í기 ìí´ ì´ ì íì ìì
ì í¹í ì í©í ë¤ì´í°ë¸ ê°ì²´ê° ìë ê°ë¨í ì¿ í¤ íë ììí¬ì ìí´ ìì±ë ì ì ê°ì²´ docCookies
를 íë¡ìííë ¤ê³ í©ëë¤.
/*
const docCookies = ... ì¬ê¸°ì "docCookies"를 ê°ì ¸ìµëë¤.
https://reference.codeproject.com/dom/document/cookie/simple_document.cookie_framework
*/
const docCookies = new Proxy(docCookies, {
get(target, key) {
return target[key] || target.getItem(key) || undefined;
},
set(target, key, value) {
if (key in target) {
return false;
}
return target.setItem(key, value);
},
deleteProperty(target, key) {
if (!(key in target)) {
return false;
}
return target.removeItem(key);
},
ownKeys(target) {
return target.keys();
},
has(target, key) {
return key in target || target.hasItem(key);
},
defineProperty(target, key, descriptor) {
if (descriptor && "value" in descriptor) {
target.setItem(key, descriptor.value);
}
return target;
},
getOwnPropertyDescriptor(target, key) {
const value = target.getItem(key);
return value
? {
value,
writable: true,
enumerable: true,
configurable: false,
}
: undefined;
},
});
/* ì¿ í¤ í
ì¤í¸ */
console.log((docCookies.myCookie1 = "First value"));
console.log(docCookies.getItem("myCookie1"));
docCookies.setItem("myCookie1", "Changed value");
console.log(docCookies.myCookie1);
ëª
ì¸ ë¸ë¼ì°ì í¸íì± ê°ì´ 보기
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4