March 18, 2025

JS Proxy


[筆記] JS Proxy


Proxy -> 代理 以物件(Object)為主。

🚩 範例一: 查找電話,某些屬性不允許訪問,但是原資料也會有。所以設定條件。

let star = {
  name: "aaa",
  age: "20",
  number: "09123456789",
};

let proxy = new Proxy(star, {
  // 攔截用戶獲取(get)的行為
  get: function (target, key, receiver) {
    if (key === "number") {
      return "123456789";
    }
    return Reflect.get(target, key, receiver);
  },
});

console.log(proxy.number); // 123456789

🚩 範例二: 實現 陣列負索引查找,在取值時,針對 index 做條件式控制回傳的 index。

let arr = [1, 2, 3, 4, 5];

function newArray() {
  return new Proxy(arr, {
    // target: arr, index: -1([-1]), receiver: 沒用到...
    get: (target, index, receiver) => {
      index = Number(index); // 轉型
      if (index < 0) {
        index = index + target.length; // -1+6 =5(也是最後一個)
      }
      return Reflect.get(target, index, receiver);
    },
  });
}

// 把這個帶有 proxy 代理的新array 覆蓋在 arr上
arr = newArray(arr);

console.log(arr[-1]); // 5

🚩 範例三: 限制年齡設置(偏驗證),所以在下面 luka.age = -1 出現 error

let data = {
  name: "luka",
  age: 10,
};

const luka = new Proxy(data, {
  set(target, prop, newValue) {
    if (prop === "age" && newValue < 0) {
      throw new Error("age不能小於0");
    }
    target[prop] = newValue;
  },
});

console.log(luka.age); // 10
luka.age = 15;
console.log(luka.age); // 15
luka.age = -1; // error

🚩 範例四: 依使用者輸入 book.XXX / book['XXX'] 依參數不同導出不同轉換結果

const book = new Proxy(
  {
    name: "javascript試煉",
    price: 150,
  },
  {
    get(target, prop) {
      if (prop === "twd") {
        return target.price * 30;
      }
      if (prop === "usd") {
        return target.price;
      }
      return target[prop];
    },
  }
);
console.log(book.usd); // 150
console.log(book.twd); // 4500

🚩 範例五: 資料處理格式化。

const form = new Proxy(
  {},
  {
    set: (obj, prop, value) => {
      if (prop === "content") {
        obj[prop] = {
          ...value,
          isEditing: false,
          hasSubmitted: false,
        };
      }
    },
  }
);

form.content = {
  label: "Age",
  defaultValue: 20,
};

console.log(form.content);
// {
//  label: 'Age',
//  defaultValue: 20,
//  isEditing: false,
//  hasSubmitted: false
// }