---
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; // 拋出異常
```
### 模仿資料雙向綁定
效果如下圖:

```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>
```