](1*eTPeG7b-fLwBd-cG2n6faA.jpeg)
# [Javascript] 使用 Proxy 為 Object 代理進行前處理
# 藉由 Proxy, 我們可以為 Object 定義屬於自己的 Object 特性
最近工作上碰到一個很特別的需求。
由於公司的多國語言使用的是  JSON Object  來進行管理,上頭希望直接用 key 就可以當作是英文的多國語句,當有某個英文關鍵字沒有被設定時,希望能夠直接以  Object  的  key  當作內容輸出。
例如:
var obj = {  | |
"a": "a",  | |
"b": 1,  | |
};  | |
console.log(obj["a"]); // "a"  | |
console.log(obj["b"]); // 1  | |
console.log(obj["no setting key"]) // 正常應該要顯示 undefined,但是希望這邊顯示 "no setting key"  | 
這種違反行為的效果著實讓我傷透腦筋,直到後來發現了 ES6 的  Proxy  。
Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种 “元编程”(meta programming),即对编程语言进行编程。
Proxy 可以理解成,在目标对象之前架设一层 “拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来 “代理” 某些操作,可以译为 “代理器”。 — ECMAScript 6 入门
利用  Proxy  ,我們可以擴增 Object 的功能或特性,做出屬於我們自己的物件特性。
Proxy 的使用格式為
obj = new Proxy(目標物件, handler物件);
所謂的  handler 物件  是用來做為  proxy  攔截  目標物件  而存在。因此我們必須在 handler object 中撰寫我們攔截  目標物件  後要進行的  getter  ,  setter  操作  function  。若  handler  沒有給予任何操作方法,則就跟一般物件無異。
以下給幾個範例:
賦值前的檢查
我們可以利用 proxy 來針對要賦值給予物件之前做檢查,以下面 code 為例:
setter 會接收三個參數  target Object  ,  property  ,  value
target object: 要被賦值的目標物件。property: 要被賦值的物件屬性 (也就是key)value: 要賦予的值
let person = new Proxy({}, {  | |
set: (targetObj, prop, value) => {  | |
if (prop === 'age') {  | |
        // 如果 要給值的 key 是 'age' 就事先檢查給予的值 | |
if (!Number.isInteger(value)) {  | |
            // 如果不是 integer 的話,就拋出 Error | |
throw new TypeError('The age is not an integer');  | |
        } | |
if (value > 200) {  | |
          // 如果 年紀大於 200 的話,也不合理 | |
throw new RangeError('The age seems invalid');  | |
        } | |
    } | |
    // 如果一切正常,則正常給值 | |
targetObj[prop] = value;  | |
    // 回傳 ok | |
return true;  | |
  } | |
});  | 
上面的這段的結果,會讓  person  變為一個  Proxy  物件,並且在給值前進行檢查,如果給值的對象是 age , 則給的值 必須是不大於 200 的整數 ,否則會賦值失敗。
來看看結果

當我們輸入字串時,會拋出 The age is not an integer 的 error。

當我們輸入浮點數時一樣會拋出 The age is not an integer 的 error。

當我們給予超過 200 的整數時,也會被阻擋掉。

只有當我們給予正確範圍的整數時,才能成功賦值。

而當我們要對物件的  key  賦值時,並不會遭到阻擋。

我們將  person  印出來看看,發現其實是一個  Proxy  物件。
# 因此回到我們今天的主題
上頭希望直接用 key 就可以當作是英文的多國語句,當有某個英文關鍵字沒有被設定時,希望能夠直接以
Object的key當作內容輸出。
這該怎麼做呢?
依照 proxy 的思路,就很簡單了。
我們只要在取值時做檢查就可以了。
寫一個 getter function
var language = {  | |
"I have a pen": "我有一支筆",  | |
"I have an apple": "我有一顆蘋果",  | |
} | |
language = new Proxy(language, {  | |
get: (tar, prop, reveiver) => {  | |
return ( !tar[prop] ) ? prop : tar[prop]  | |
	} | |
})  | 
上面的 code 在做的事情就是,當  language  在取值前先進行檢查,若有值則直接回傳原值;否則回傳  key  值。
如此就達到了我們原本的目的了。
來看看結果

        