代理對像如何在 JavaScript 中工作?

代理對像如何在 JavaScript 中工作?

JavaScript 代理對象允許您攔截和自定義另一個對象的行為,而無需修改原始對象。

使用代理對象,您可以驗證數據、提供額外功能以及控制對屬性和函數的訪問。

了解所有關於代理對象的用途以及如何在 JavaScript 中創建它們的信息。

創建代理對象

在 JavaScript 中,您可以使用Proxy構造函數創建代理對象。該構造函數有兩個參數:一個用於包裝代理的目標對象和一個處理程序對象,其屬性定義代理在執行操作時的行為。

它接受這些參數並創建一個您可以用來代替目標對象的對象。這個創建的對象可以重新定義獲取、設置和定義屬性等核心操作。您還可以使用這些代理對象來記錄屬性訪問和驗證、格式化或清理輸入。

例如:

const originalObject = {
  foo: "bar"
}

const handler = {
  get: function(target, property) {
    return target[property];
  },
  set: function(target, property, value) {
    target[property] = value;
  }
};


const proxy = new Proxy(originalObject, handler)

此代碼創建一個目標對象originalObject,它具有單個屬性foo和一個處理程序對象handler。處理程序對象包含兩個屬性,getset。這些屬性稱為陷阱。

代理對象陷阱是每當您對代理對象執行指定操作時調用的函數。陷阱允許您攔截和自定義代理對象的行為。從代理對象訪問屬性調用get陷阱,修改或操作代理對象的屬性調用set陷阱。

最後,代碼使用Proxy構造函數創建一個代理對象。它分別將originalObjecthandler作為目標對象和處理程序傳遞。

使用代理對象

代理對像在 JavaScript 中有多種用途,其中一些如下。

向對象添加功能

您可以使用代理對象來包裝現有對象並添加新功能,例如日誌記錄或錯誤處理,而無需修改原始對象。

要添加新功能,您需要使用Proxy構造函數並為要攔截的操作定義一個或多個陷阱。

例如:

const userObject = {
  firstName: "Kennedy",
  lastName: "Martins",
  age: 20,
};

const handler = {
  get: function (target, property) {
    console.log(`Getting property "${property}"`);
    return target[property];
  },
  set: function (target, property, value) {
    console.log(`Setting property "${property}"to value "${value}"`);
    target[property] = value;
  },
};

const proxy = new Proxy(userObject, handler);

console.log(proxy.firstName); // Getting property "firstName"Kennedy
console.log(proxy.lastName); // Getting property "lastName"Martins
proxy.age = 23; // Setting property "age" to value "23"

此代碼塊通過代理陷阱getset添加功能。現在,當您嘗試訪問或修改userObject的屬性時,代理對象會先將您的操作記錄到控制台,然後再訪問或修改該屬性。

在將數據設置到對象之前驗證數據

您可以使用代理對象來驗證數據並確保它滿足特定條件,然後再將其設置到對像上。您可以通過在處理程序對象的設置陷阱中定義驗證邏輯來實現。

例如:

const userObject = {
  firstName: "Kennedy",
  lastName: "Martins",
  age: 20,
};

const handler = {
  get: function (target, property) {
    console.log(`Getting property "${property}"`);
    return target[property];
  },
  set: function (target, property, value) {
    if (
      property === "age" &&
      typeof value == "number" &&
      value > 0 &&
      value < 120
    ) {
      console.log(`Setting property "${property}"to value "${value}"`);
      target[property] = value;
    } else {
      throw new Error("Invalid parameter. Please review and correct.");
    }
  },
};


const proxy = new Proxy(userObject, handler);
proxy.age = 21;

此代碼塊將驗證規則添加到設置陷阱。您可以為userObject實例的age屬性分配任何值。但是,使用添加的驗證規則,如果它是一個大於 0 且小於 120 的數字,則只能為 age 屬性分配一個新值。您嘗試在age屬性上設置的任何不符合要求條件的值將觸發錯誤並打印錯誤消息。

控制對對象屬性的訪問

您可以使用代理對象來隱藏對象的某些屬性。通過在獲取陷阱中為您要控制訪問的屬性定義限制邏輯來實現。

例如:

const userObject = {
  firstName: "Kennedy",
  lastName: "Martins",
  age: 20,
  phone: 1234567890,
  email: "foo@bar.com",
};

const handler = {
  get: function (target, property) {
    if (property === "phone" || property === "email") {
      throw new Error("Access to info denied");
    } else {
      console.log(`Getting property "${property}"`);
      return target[property];
    }
  },
  set: function (target, property, value) {
    console.log(`Setting property "${property}"to value "${value}"`);
    target[property] = value;
  },
};

const proxy = new Proxy(userObject, handler);

console.log(proxy.firstName); // Getting property "firstName"Kennedy
console.log(proxy.email); // Throws error

上面的代碼塊對get陷阱添加了某些限制。最初,您可以訪問userObject上的所有可用屬性。添加的規則可防止訪問敏感信息,例如用戶的電子郵件或電話。嘗試訪問這些屬性中的任何一個都將觸發錯誤。

其他代理陷阱

getset陷阱是最常見和最有用的,但還有 11 個其他 JavaScript 代理陷阱。他們是:

  • applyapply陷阱在您調用代理對像上的函數時運行。
  • construct構造陷阱在您使用 new 運算符從代理對象創建對象時運行。
  • deletePropertydeleteProperty陷阱在您使用delete運算符從代理對像中刪除屬性時運行。
  • hashas陷阱在您使用in運算符檢查代理對像上是否存在屬性時運行。
  • ownKeys –當您在代理對像上調用Object.getOwnPropertyNamesObject.getOwnPropertySymbols函數時, ownKeys陷阱就會運行。
  • getOwnPropertyDescriptorgetOwnPropertyDescriptor陷阱在您調用代理對像上的Object.getOwnPropertyDescriptor函數時運行。
  • definePropertydefineProperty陷阱在您調用代理對像上的Object.defineProperty函數時運行。
  • preventExtensionspreventExtensions陷阱在您調用代理對像上的Object.preventExtensions函數時運行。
  • isExtensibleisExtensible陷阱在您調用代理對像上的Object.isExtensible函數時運行。
  • getPrototypeOfgetPrototypeOf陷阱在您對代理對象調用Object.getPrototypeOf函數時運行。
  • setPrototypeOfsetPrototypeOf陷阱在您對代理對象調用Object.setPrototypeOf函數時運行。

setget陷阱一樣,您可以使用這些陷阱來為您的對象添加新的功能、驗證和控制層,而無需修改原始對象。

代理對象的缺點

代理對象可以是一個強大的工具,用於向對象添加自定義功能或驗證。但它們也有一些潛在的缺點。其中一個缺點是難以調試,因為很難看到幕後發生的事情。

代理對像也可能難以使用,尤其是當您不熟悉它們時。在您的代碼中使用代理對象之前,您應該仔細考慮這些缺點。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *