--- tags: Javascript --- # JS Proxy(代理)筆記 對`Proxy`進行操作,會先經過`Proxy`作用在`target`身上,可以讓資料在存取前進行一些操作 在`Vue`中就有使用`Proxy`來組成資料,達成資料雙向綁定的特性。 語法如下: `var p = new Proxy(target, handler);` `target`: 只能是物件,而且並非是複製一份而是指向同個位置 `handler`: 定義在操作行為上的函數 ### 基本用法 `get`函式取值,`set`函式設值 ```javascript= var handler = { get: function(obj, prop) { console.log(`${obj}, ${prop}`); // 取值 return obj[prop]; }, set: function(obj, prop, newVal) { console.log(`${obj}, ${prop}, ${newVal}`); // 基本設值 obj[prop] = newVal; // 表示成功,沒寫console會有錯誤 return true; } }; var p = new Proxy({a: 1}, handler); p.a = 2; console.log(p.a); // 1 ``` `set`函式輸出`{a: 1} , a, 2` `get`函式輸出`{a: 2}, a` ### 驗證 可以在`set`函式中對值進行驗證 ```javascript= let validator = { set: function(obj, prop, value) { if (prop === 'age') { if (!Number.isInteger(value)) { throw new TypeError('年齡不是整數'); } if (value > 200) { throw new RangeError('年齡無效'); } } // 設值 obj[prop] = value; // 表示成功 return true; } }; let person = new Proxy({}, validator); person.age = 100; console.log(person.age); // 100 person.age = 'young'; // 拋出異常 person.age = 300; // 拋出異常 ``` ### 模仿資料雙向綁定 效果如下圖: ![](https://i.imgur.com/Vha1m7w.gif) ```htmlembedded= <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="app"> </div> <script> function render(key, value) { document.getElementById('app').innerHTML = `${key}: ${value}`; } var handler = { get: function(obj, prop) { console.log(`${obj}, ${prop}`); // 取值 return obj[prop]; }, set: function(obj, prop, newVal) { console.log(`${obj}, ${prop}, ${newVal}`); // 基本設值 obj[prop] = newVal; render(prop, obj[prop]); // 表示成功,沒寫console會有錯誤 return true; } }; var p = new Proxy({}, handler); p.name = 'John'; setTimeout(() => { p.name = 'Joe'; }, 2000); </script> </body> </html> ```