JavaScript中的Proxy詳解

1.?什么是Proxy?

Proxy是ES6引入的一個強大特性,它允許你創建一個對象的代理,從而可以攔截和自定義該對象的基本操作。Proxy提供了一種機制,可以在對象的基本操作,如屬性查找、賦值、枚舉、函數調用等之前或之后執行自定義行為。

基本語法如下:

const proxy = new Proxy(target, handler);

target:要代理的目標對象,可以是任何類型的對象,包括數組、函數或另一個代理;

handler:一個對象,其屬性是定義代理行為的函數,稱為"陷阱"或"trap";

2.?所有的handler方法

2.1. get(target, prop, receiver) - 攔截屬性讀取

const person = {name: "Alice",age: 30,
};const proxy = new Proxy(person, {get(target, prop) {console.log(`Reading property: ${prop}`);return prop in target ? target[prop] : "Default";},
});console.log(proxy.name); // "Reading property: name" → "Alice"
console.log(proxy.gender); // "Reading property: gender" → "Default"

2.2. set(target, prop, value, receiver) - 攔截屬性設置

const validator = {set(target, prop, value) {if (prop === "age") {if (!Number.isInteger(value) || value < 0) {throw new TypeError("Age must be a positive integer");}}console.log(`Setting ${prop} to ${value}`);target[prop] = value;return true; // 表示設置成功},
};const person = new Proxy({}, validator);
person.age = 25; // "Setting age to 25"
person.age = -5; // 拋出錯誤: Age must be a positive integer

2.3.?has(target, prop) - 攔截 in 操作符

const hiddenProps = ["secret", "password"];
const target = {name: "Bob",secret: "123",
};const proxy = new Proxy(target, {has(target, prop) {if (hiddenProps.includes(prop)) {return false; // 隱藏屬性}return prop in target;},
});console.log("name" in proxy); // true
console.log("secret" in proxy); // false

2.4.?deleteProperty(target, prop) - 攔截 delete 操作

const protectedData = {name: "Charlie",id: "12345",
};const proxy = new Proxy(protectedData, {deleteProperty(target, prop) {if (prop === "id") {throw new Error("Cannot delete ID property");}delete target[prop];return true;},
});delete proxy.name; // 成功
delete proxy.id; // 拋出錯誤: Cannot delete ID property

2.5.?apply(target, thisArg, arguments) - 攔截函數調用

function sum(a, b) {return a + b;
}const loggingProxy = new Proxy(sum, {apply(target, thisArg, args) {console.log(`Function called with args: ${args}`);console.log(`thisArg: ${thisArg}`);const result = target.apply(thisArg, args);console.log(`Function returned: ${result}`);return result;},
});loggingProxy(2, 3);
// "Function called with args: 2,3"
// "thisArg: undefined"
// "Function returned: 5"
// → 5

2.6.?construct(target, argumentsList, newTarget) - 攔截 new 操作符

class Person {constructor(name) {this.name = name;}
}const PersonProxy = new Proxy(Person, {construct(target, args, newTarget) {console.log(`Creating instance with args: ${args}`);// 可以修改參數或添加額外邏輯if (args.length === 0) {args = ["Anonymous"];}return new target(...args);},
});const p1 = new PersonProxy("Alice");
// "Creating instance with args: Alice"
const p2 = new PersonProxy();
// "Creating instance with args:" → name: "Anonymous"

2.7.?ownKeys(target) - 攔截 Object.keys() 等操作

const user = {name: "Dave",age: 40,_password: "****",
};const proxy = new Proxy(user, {ownKeys(target) {return Object.keys(target).filter((key) => !key.startsWith("_"));},
});console.log(Object.keys(proxy)); // ["name", "age"]
console.log(Object.getOwnPropertyNames(proxy)); // ["name", "age"]

2.8.?getOwnPropertyDescriptor(target, prop) - 攔截 Object.getOwnPropertyDescriptor()

const target = {name: "Eve",
};const proxy = new Proxy(target, {getOwnPropertyDescriptor(target, prop) {console.log(`Getting descriptor for: ${prop}`);const descriptor = Object.getOwnPropertyDescriptor(target, prop);// 可以修改描述符if (prop === "name") {descriptor.enumerable = false;}return descriptor || undefined;},
});console.log(Object.getOwnPropertyDescriptor(proxy, "name"));
// "Getting descriptor for: name" → {value: "Eve", writable: true, enumerable: false, configurable: true}

2.9.?defineProperty(target, prop, descriptor) - 攔截 Object.defineProperty()

const target = {};const proxy = new Proxy(target, {defineProperty(target, prop, descriptor) {console.log(`Defining property ${prop}`);if (prop.startsWith("_")) {throw new Error(`Cannot define private property: ${prop}`);}return Reflect.defineProperty(target, prop, descriptor);},
});Object.defineProperty(proxy, "name", { value: "Frank" }); // 成功
Object.defineProperty(proxy, "_secret", { value: "123" }); // 拋出錯誤

2.10.?preventExtensions(target) - 攔截 Object.preventExtensions()

const target = { name: "Grace" };
const proxy = new Proxy(target, {preventExtensions(target) {console.log("Attempt to prevent extensions");// 可以決定是否允許阻止擴展return false; // 返回false表示不允許阻止擴展// 或者調用 Reflect.preventExtensions(target)},
});Object.preventExtensions(proxy);
// "Attempt to prevent extensions"
// 拋出 TypeError (因為返回了false)

2.11.?isExtensible(target) - 攔截 Object.isExtensible()

const target = {};const proxy = new Proxy(target, {isExtensible(target) {console.log("Checking extensibility");// 可以返回自定義值return false; // 總是返回不可擴展// 或者調用 Reflect.isExtensible(target)},
});console.log(Object.isExtensible(proxy));
// "Checking extensibility" → false

2.12.?getPrototypeOf(target) - 攔截 Object.getPrototypeOf()

const originalProto = { version: 1 };
const obj = Object.create(originalProto);const proxy = new Proxy(obj, {getPrototypeOf(target) {console.log("Getting prototype");// 可以返回不同的原型return { version: 2 }; // 返回假原型// 或者調用 Reflect.getPrototypeOf(target)},
});console.log(Object.getPrototypeOf(proxy));
// "Getting prototype" → {version: 2}

2.13.?setPrototypeOf(target, prototype) - 攔截 Object.setPrototypeOf()

const target = {};
const proxy = new Proxy(target, {setPrototypeOf(target, proto) {console.log(`Setting prototype to: ${proto}`);// 可以阻止設置原型throw new Error("Prototype modification not allowed");// 或者調用 Reflect.setPrototypeOf(target, proto)},
});Object.setPrototypeOf(proxy, {});
// "Setting prototype to: [object Object]"
// 拋出錯誤: Prototype modification not allowed

2.14.?綜合示例:實現一個全面的數據驗證代理

const createValidatedObject = (schema, initialData = {}) => {return new Proxy(initialData, {set(target, prop, value) {// 檢查屬性是否在schema中定義if (!(prop in schema)) {throw new Error(`Property "${prop}" is not allowed`);}// 獲取驗證函數const validator = schema[prop];// 驗證值if (!validator(value)) {throw new Error(`Invalid value for property "${prop}"`);}// 設置值target[prop] = value;return true;},get(target, prop) {if (prop in target) {return target[prop];}throw new Error(`Property "${prop}" does not exist`);},deleteProperty(target, prop) {if (prop in schema && !schema[prop].configurable) {throw new Error(`Cannot delete property "${prop}"`);}delete target[prop];return true;},});
};// 定義schema
const userSchema = {name: (value) => typeof value === "string" && value.length > 0,age: (value) => Number.isInteger(value) && value >= 0,email: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
};// 創建代理對象
const user = createValidatedObject(userSchema);// 使用示例
user.name = "Alice"; // 成功
user.age = 30; // 成功
user.email = "alice@example.com"; // 成功try {user.age = -5; // 拋出錯誤: Invalid value for property "age"
} catch (e) {console.error(e.message);
}try {user.gender = "female"; // 拋出錯誤: Property "gender" is not allowed
} catch (e) {console.error(e.message);
}

這些示例涵蓋了 Proxy 的主要 handler 方法,展示了它們在實際開發中的應用場景。通過這些示例,你可以看到 Proxy 如何為 JavaScript 對象提供強大的攔截和自定義能力。

3.?常用場景

下面是Proxy在實際開發中的10種常見應用場景的完整代碼示例:

3.1. 數據驗證

const createValidator = (rules) => {return new Proxy({},{set(target, prop, value) {if (!rules[prop]) {throw new Error(`Property "${prop}" is not allowed`);}if (!rules[prop](value)) {throw new Error(`Invalid value for "${prop}"`);}target[prop] = value;return true;},});
};// 使用示例
const userValidator = createValidator({name: (val) => typeof val === "string" && val.length >= 2,age: (val) => Number.isInteger(val) && val >= 18,email: (val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),
});userValidator.name = "Alice"; // 成功
userValidator.age = 25; // 成功
// userValidator.age = '25'; // 拋出錯誤
// userValidator.gender = 'female'; // 拋出錯誤

3.2. 觀察者模式(數據變化監聽)

function createObservable(target, callback) {return new Proxy(target, {set(target, prop, value) {const oldValue = target[prop];target[prop] = value;callback(prop, oldValue, value);return true;},});
}// 使用示例
const user = { name: "Bob", age: 30 };
const observableUser = createObservable(user, (prop, oldVal, newVal) => {console.log(`Property ${prop} changed from ${oldVal} to ${newVal}`);
});observableUser.name = "Alice"; // 控制臺輸出: Property name changed from Bob to Alice
observableUser.age = 31; // 控制臺輸出: Property age changed from 30 to 31

3.3. 屬性訪問控制

const createPrivateProps = (obj, privateProps = []) => {return new Proxy(obj, {get(target, prop) {if (privateProps.includes(prop)) {throw new Error(`Property "${prop}" is private`);}return target[prop];},set(target, prop, value) {if (privateProps.includes(prop)) {throw new Error(`Cannot set private property "${prop}"`);}target[prop] = value;return true;},});
};// 使用示例
const account = createPrivateProps({username: "alice123",_password: "secret123",},["_password"]
);console.log(account.username); // 'alice123'
// console.log(account._password); // 拋出錯誤
// account._password = 'newpass'; // 拋出錯誤

3.4.?虛擬屬性(動態計算屬性)

const createVirtualProps = (obj, virtualProps = {}) => {return new Proxy(obj, {get(target, prop) {if (prop in virtualProps) {return virtualProps[prop](target);}return target[prop];},});
};// 使用示例
const person = createVirtualProps({firstName: "John",lastName: "Doe",},{fullName: (target) => `${target.firstName} ${target.lastName}`,initials: (target) => `${target.firstName[0]}${target.lastName[0]}`,}
);console.log(person.fullName); // 'John Doe'
console.log(person.initials); // 'JD'

3.5.?API封裝(簡化復雜API)

const api = {_baseUrl: "https://api.example.com",_endpoints: {users: "/users",posts: "/posts",},_makeRequest(url, options) {console.log(`Making request to ${url}`);// 實際這里會是fetch或axios調用return Promise.resolve({ data: `${url} response` });},
};const apiProxy = new Proxy(api, {get(target, prop) {if (prop in target._endpoints) {return (options = {}) => {const url = `${target._baseUrl}${target._endpoints[prop]}`;return target._makeRequest(url, options);};}return target[prop];},
});// 使用示例
apiProxy.users().then((res) => console.log(res.data));
// "Making request to https://api.example.com/users"
// → "https://api.example.com/users response"apiProxy.posts({ page: 2 }).then((res) => console.log(res.data));
// "Making request to https://api.example.com/posts"
// → "https://api.example.com/posts response"

3.6. 性能優化(延遲加載/緩存)

const createCachedProxy = (fn) => {const cache = new Map();return new Proxy(fn, {apply(target, thisArg, args) {const key = JSON.stringify(args);if (cache.has(key)) {console.log("Returning cached result");return cache.get(key);}console.log("Calculating new result");const result = target.apply(thisArg, args);cache.set(key, result);return result;},});
};// 使用示例
const expensiveCalculation = (a, b) => {console.log("Running expensive calculation...");return a * b;
};const cachedCalc = createCachedProxy(expensiveCalculation);console.log(cachedCalc(2, 3)); // "Running expensive calculation..." → 6
console.log(cachedCalc(2, 3)); // "Returning cached result" → 6
console.log(cachedCalc(4, 5)); // "Running expensive calculation..." → 20

3.7.?負索引數組(類似Python)

const createNegativeIndexArray = (arr) => {return new Proxy(arr, {get(target, prop) {const index = parseInt(prop);if (!isNaN(index)) {// 處理負索引prop = index < 0 ? target.length + index : index;}return Reflect.get(target, prop);},});
};// 使用示例
const array = createNegativeIndexArray(["a", "b", "c", "d"]);console.log(array[0]); // 'a'
console.log(array[-1]); // 'd'
console.log(array[-2]); // 'c'

3.8.?函數調用日志(調試)

const withLogging = (fn) => {return new Proxy(fn, {apply(target, thisArg, args) {console.log(`Calling ${target.name} with args:`, args);const start = performance.now();const result = target.apply(thisArg, args);const end = performance.now();console.log(`Called ${target.name}, took ${(end - start).toFixed(2)}ms`);return result;},});
};// 使用示例
function calculate(a, b, c) {// 模擬耗時操作for (let i = 0; i < 100000000; i++) {}return a + b * c;
}const loggedCalc = withLogging(calculate);
console.log(loggedCalc(2, 3, 4));
// 控制臺輸出:
// Calling calculate with args: [2, 3, 4]
// Called calculate, took 123.45ms
// → 14

3.9. 自動填充默認值

const withDefaults = (obj, defaults) => {return new Proxy(obj, {get(target, prop) {if (prop in target) {return target[prop];}if (prop in defaults) {const defaultValue = defaults[prop];// 如果默認值是函數則調用它return typeof defaultValue === "function"? defaultValue(): defaultValue;}return undefined;},});
};// 使用示例
const config = withDefaults({theme: "dark",},{theme: "light",fontSize: 14,timestamp: () => new Date().toISOString(),}
);console.log(config.theme); // 'dark' (使用已有值)
console.log(config.fontSize); // 14 (使用默認值)
console.log(config.timestamp); // 當前時間ISO字符串 (調用函數默認值)
console.log(config.nonExisting); // undefined

3.10.?數據綁定(雙向綁定)

function createBinding(sourceObj, targetObj, propertyMap) {const handler = {set(target, prop, value) {target[prop] = value;// 更新綁定的屬性if (propertyMap[prop]) {const targetProp = propertyMap[prop];targetObj[targetProp] = value;console.log(`Updated ${targetProp} to ${value}`);}return true;},};return new Proxy(sourceObj, handler);
}// 使用示例
const form = {};
const model = { firstName: "", lastName: "" };const boundForm = createBinding(form, model, {"first-name": "firstName","last-name": "lastName",
});boundForm["first-name"] = "Alice";
// 控制臺輸出: Updated firstName to Alice
boundForm["last-name"] = "Smith";
// 控制臺輸出: Updated lastName to Smithconsole.log(model);
// { firstName: 'Alice', lastName: 'Smith' }

這些示例展示了Proxy在實際開發中的強大能力。每個示例都可以根據具體需求進行擴展和組合使用,Proxy為JavaScript提供了元編程的強大工具,可以優雅地解決許多復雜問題。

4.?注意事項

1. Proxy的handler方法中應該盡量使用Reflect對象的方法來保持默認行為;

2. 不是所有操作都可以被攔截,例如嚴格相等===;

3. 過度使用Proxy可能會影響性能;

4. 某些庫可能無法正確處理Proxy對象;

5. Proxy的this綁定可能與原對象不同;

Proxy為JavaScript提供了強大的元編程能力,合理使用可以大大簡化代碼并實現復雜的功能,但也要注意不要過度使用,以免影響代碼的可讀性和性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/76931.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/76931.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/76931.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【git】VScode修改撤回文件總是出現.lh文件,在 ?所有 Git 項目 中全局忽略特定文件

VScode里面powershell被迫關閉 場景解決辦法 場景 系統&#xff1a;Windows IDE&#xff1a;Visual Studio Code 一旦修改代碼&#xff0c;就算撤回也會顯示 解決辦法 第一步&#xff1a;“C:\Users\用戶名字.gitignore_global”&#xff1a;在該路徑下新建.gitignore_glo…

為什么 LoRA 梯度是建立在全量參數 W 的梯度之上

&#x1f9e0; 首先搞清楚 LoRA 是怎么做微調的 我們原來要訓練的參數矩陣是 W W W&#xff0c;但 LoRA 說&#xff1a; 別動 W&#xff0c;我在它旁邊加一個低秩矩陣 Δ W U V \Delta W UV ΔWUV&#xff0c;只訓練這個部分&#xff01; 也就是說&#xff0c;LoRA 用一個…

Nginx負載均衡時如何為指定ip配置固定服務器

大家在用Nginx做負載均衡時&#xff0c;一般是采用默認的weight權重指定或默認的平均分配實現后端服務器的路由&#xff0c;還有一種做法是通過ip_hash來自動計算進行后端服務器的路由&#xff0c;但最近遇到一個問題&#xff0c;就是希望大部分用戶采用ip_hash自動分配后端服務…

Llama 4 家族:原生多模態 AI 創新的新時代開啟

0 要點總結 Meta發布 Llama 4 系列的首批模型&#xff0c;幫用戶打造更個性化多模態體驗Llama 4 Scout 是有 170 億激活參數、16 個專家模塊的模型&#xff0c;同類中全球最強多模態模型&#xff0c;性能超越以往所有 Llama 系列模型&#xff0c;能在一張 NVIDIA H100 GPU 上運…

【硬件開發技巧】如何通過元器件絲印反查型號

目錄 一、在線數據庫查詢 二、官方資料匹配 三、專業軟件輔助 四、實物比對與場景推斷 五、社區與人工支持 注意事項 一、在線數據庫查詢 專業元器件平臺 Digi-Key、Mouser、ICMaster等平臺支持直接輸入絲印代碼檢索&#xff0c;可獲取芯片型號、技術文檔及替代型號。例如…

【算法/c++】利用中序遍歷和后序遍歷建二叉樹

目錄 題目&#xff1a;樹的遍歷前言題目來源樹的數組存儲基本思想存儲規則示例 建樹算法關鍵思路代碼總代碼 鏈表法 題目&#xff1a;樹的遍歷 前言 如果不是完全二叉樹&#xff0c;使用數組模擬樹&#xff0c;會很浪費空間。 題目來源 本題來自 PTA 天梯賽。 題目鏈接: 樹…

李臻20242817_安全文件傳輸系統項目報告_第6周

安全文件傳輸系統項目報告&#xff08;第 1 周&#xff09; 1. 代碼鏈接 Gitee 倉庫地址&#xff1a;https://gitee.com/li-zhen1215/homework/tree/master/Secure-file 代碼結構說明&#xff1a; project-root/├── src/ # 源代碼目錄│ ├── main.c # 主程序入口│ ├…

嵌入式rodata段

在嵌入式軟件開發中&#xff0c;將數據放入只讀數據段&#xff08;.rodata&#xff09;具有以下好處及典型應用示例&#xff1a; 好處 數據保護 .rodata段的內容在程序運行時不可修改&#xff0c;防止意外或惡意篡改&#xff0c;提升系統穩定性。 節省RAM資源 只讀數據可直接…

InfoSec Prep: OSCP靶場滲透

InfoSec Prep: OSCP InfoSec Prep: OSCP ~ VulnHubInfoSec Prep: OSCP, made by FalconSpy. Download & walkthrough links are available.https://www.vulnhub.com/entry/infosec-prep-oscp,508/ 1&#xff0c;將兩臺虛擬機網絡連接都改為NAT模式 2&#xff0c;攻擊機上做…

【JavaWeb-Spring boot】學習筆記

目錄 <<回到導覽Spring boot1. http協議1.1.請求協議1.2.響應協議 2.Tomcat2.1.請求2.1.1.apifox2.1.2.簡單參數2.1.3.實體參數2.1.4.數組集合參數2.1.5.日期參數2.1.6.(重點)JSON參數2.1.7.路徑參數 2.2.響應2.3.綜合練習 3.三層架構3.1.三層拆分3.2.分層解耦3.3.補充 &…

C++的多態-上

目錄 多態的概念 多態的定義及實現 1.虛函數 2. 多態的實現 2.1.多態構成條件 2.2.虛函數重寫的兩個例外 (1)協變(基類與派生類虛函數返回值類型不同) (2)析構函數的重寫(基類與派生類析構函數的名字不同) 2.3.多態的實現 2.4.多態在析構函數中的應用 2.5.多態構成條…

網絡安全的重要性與防護措施

隨著信息技術的飛速發展&#xff0c;互聯網已經成為我們日常生活、工作和學習的必需品。無論是通過社交媒體與朋友互動&#xff0c;還是在網上進行銀行交易&#xff0c;網絡已經滲透到我們生活的方方面面。然而&#xff0c;隨之而來的是各種網絡安全問題&#xff0c;包括數據泄…

CMake學習--Window下VSCode 中 CMake C++ 代碼調試操作方法

目錄 一、背景知識二、使用方法&#xff08;一&#xff09;安裝擴展&#xff08;二&#xff09;創建 CMake 項目&#xff08;三&#xff09;編寫代碼&#xff08;四&#xff09;配置 CMakeLists.txt&#xff08;五&#xff09;生成構建文件&#xff08;六&#xff09;開始調試 …

訪問數組元素(四十四)

1. 數組下標與類型 數組的索引從 0 開始。例如&#xff0c;一個包含 10 個元素的數組&#xff0c;其合法下標范圍為 0 到 9&#xff0c;而不是 1 到 10。為了表示下標&#xff0c;通常使用 size_t 類型&#xff0c;它是一種與機器相關的無符號整型&#xff0c;足夠大以存放內存…

計算機網絡 3-1 數據鏈路層(功能+組幀+差錯控制)

【考綱內容】 &#xff08;一&#xff09;數據鏈路層的功能 &#xff08;二&#xff09;組幀 &#xff08;三&#xff09;差錯控制 檢錯編碼&#xff1b;糾錯編碼 &#xff08;四&#xff09;流量控制與可靠傳輸機制 流量控制、可靠傳輸與滑動窗口機制&#xff1b;停止-等…

Django中使用不同種類緩存的完整案例

Django中使用不同種類緩存的完整案例 推薦超級課程: 本地離線DeepSeek AI方案部署實戰教程【完全版】Docker快速入門到精通Kubernetes入門到大師通關課AWS云服務快速入門實戰目錄 Django中使用不同種類緩存的完整案例步驟1:設置Django項目步驟2:設置URL路由步驟3:視圖級別…

Spring Boot 集成Redis 的Lua腳本詳解

1. 對比Lua腳本方案與Redis自身事務 對比表格 對比維度Redis事務&#xff08;MULTI/EXEC&#xff09;Lua腳本方案原子性事務命令序列化執行&#xff0c;但中間可被其他命令打斷&#xff0c;不保證原子性Lua腳本在Redis單線程中原子執行&#xff0c;不可中斷計算能力僅支持Red…

【大模型】DeepSeek + 藍耕MaaS平臺 + 海螺AI生成高質量視頻操作詳解

目錄 一、前言 二、藍耘智能云MaaS平臺介紹 2.1 藍耘智算平臺是什么 2.2 平臺優勢 2.3 平臺核心能力 三、海螺AI視頻介紹 3.1 海螺AI視頻是什么 3.2 海螺AI視頻主要功能 3.3 海螺AI視頻應用場景 3.4 海螺AI視頻核心優勢 3.5 項目git地址 四、藍耘MaaS平臺DeepSeek海…

12-產品經理-維護模塊

需求模塊是幫助產品經理進行需求的分類和維護。 1. 維護模塊 在具體產品的“研發需求”頁面左側&#xff0c;點擊“維護模塊”。也可以在具體產品的“設置”-“模塊”下進行維護。 點擊保存后&#xff0c;返回模塊頁面。還可以點擊“子模塊”對已有模塊進行子模塊的維護。 點擊…

考研單詞筆記 2025.04.06

area n領域&#xff0c;范圍&#xff0c;方面&#xff0c;地區&#xff0c;地方&#xff0c;場地&#xff0c;面積 aspect n方面&#xff0c;層面&#xff0c;外表&#xff0c;外觀 boundary n限度&#xff0c;界限&#xff0c;分界線&#xff0c;邊界 cap n最高限額&#x…