代理對像如何在 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。處理程序對象包含兩個屬性,get和set。這些屬性稱為陷阱。
代理對象陷阱是每當您對代理對象執行指定操作時調用的函數。陷阱允許您攔截和自定義代理對象的行為。從代理對象訪問屬性調用get陷阱,修改或操作代理對象的屬性調用set陷阱。
最後,代碼使用Proxy構造函數創建一個代理對象。它分別將originalObject和handler作為目標對象和處理程序傳遞。
使用代理對象
代理對像在 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"
此代碼塊通過代理陷阱get和set添加功能。現在,當您嘗試訪問或修改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上的所有可用屬性。添加的規則可防止訪問敏感信息,例如用戶的電子郵件或電話。嘗試訪問這些屬性中的任何一個都將觸發錯誤。
其他代理陷阱
get和set陷阱是最常見和最有用的,但還有 11 個其他 JavaScript 代理陷阱。他們是:
- apply:apply陷阱在您調用代理對像上的函數時運行。
- construct:構造陷阱在您使用 new 運算符從代理對象創建對象時運行。
- deleteProperty:deleteProperty陷阱在您使用delete運算符從代理對像中刪除屬性時運行。
- has – has陷阱在您使用in運算符檢查代理對像上是否存在屬性時運行。
- ownKeys –當您在代理對像上調用Object.getOwnPropertyNames或Object.getOwnPropertySymbols函數時, ownKeys陷阱就會運行。
- getOwnPropertyDescriptor – getOwnPropertyDescriptor陷阱在您調用代理對像上的Object.getOwnPropertyDescriptor函數時運行。
- defineProperty – defineProperty陷阱在您調用代理對像上的Object.defineProperty函數時運行。
- preventExtensions – preventExtensions陷阱在您調用代理對像上的Object.preventExtensions函數時運行。
- isExtensible – isExtensible陷阱在您調用代理對像上的Object.isExtensible函數時運行。
- getPrototypeOf – getPrototypeOf陷阱在您對代理對象調用Object.getPrototypeOf函數時運行。
- setPrototypeOf – setPrototypeOf陷阱在您對代理對象調用Object.setPrototypeOf函數時運行。
與set和get陷阱一樣,您可以使用這些陷阱來為您的對象添加新的功能、驗證和控制層,而無需修改原始對象。
代理對象的缺點
代理對象可以是一個強大的工具,用於向對象添加自定義功能或驗證。但它們也有一些潛在的缺點。其中一個缺點是難以調試,因為很難看到幕後發生的事情。
代理對像也可能難以使用,尤其是當您不熟悉它們時。在您的代碼中使用代理對象之前,您應該仔細考慮這些缺點。
發佈留言