proxy對象在JavaScript中主要用于攔截和自定義對目標對象的操作。1. proxy能做什么?它可實現屬性訪問控制、數據驗證、自動更新視圖、攔截函數調用等。2. 基本用法是通過new proxy(target, handler)創建,handler中定義get、set、apply等陷阱方法。3. 實際應用場景包括表單輸入自動綁定和緩存函數結果。4. 注意事項有兼容性問題、性能開銷及不可變性破壞。掌握proxy的常見陷阱方法可靈活應用于狀態管理、表單校驗等場景。
Proxy對象在JavaScript中主要用來“攔截”對目標對象的操作,比如讀取屬性、賦值、函數調用等行為。它像是一個中間層,允許你自定義這些操作的行為,而不改變原始對象本身。
1. Proxy能做什么?
Proxy的核心作用是代理對象行為,也就是說,你可以通過它來監聽并控制對某個對象的訪問和修改。常見的用途包括:
舉個簡單的例子:你想在訪問一個對象的屬性時做一些額外處理,比如記錄日志或者返回默認值。
const target = { name: 'Tom' }; const proxy = new Proxy(target, { get(obj, prop) { if (prop in obj) { console.log(`訪問了屬性 ${prop}`); return obj[prop]; } else { return '默認值'; } } }); console.log(proxy.name); // 輸出:訪問了屬性 name n Tom console.log(proxy.age); // 輸出:默認值
2. 基本用法:怎么創建一個Proxy?
創建Proxy的基本語法是:
const proxy = new Proxy(target, handler);
- target 是你要代理的目標對象
- handler 是一個對象,里面可以定義各種“陷阱”方法(trap),比如 get、set、apply 等
常用陷阱包括:
- get(target, prop, receiver):攔截屬性讀取
- set(target, prop, value, receiver):攔截屬性賦值
- has(target, prop):攔截 in 運算符
- deleteProperty(target, prop):攔截 delete 操作
- apply(target, thisArg, args):攔截函數調用
舉個數據驗證的例子:
const person = { age: 0 }; const proxy = new Proxy(person, { set(target, prop, value) { if (prop === 'age' && typeof value !== 'number') { console.error('年齡必須是數字'); return true; // 不拋錯但也不更新 } target[prop] = value; return true; } }); proxy.age = 'twenty'; // 輸出錯誤信息,但不會真正賦值
3. 實際應用場景舉例
表單輸入自動綁定
有時候你會希望把用戶輸入自動綁定到一個對象上,并做一些格式化處理。例如,把字符串轉成數字、去空格等。
const form = {}; const formProxy = new Proxy(form, { set(target, prop, value) { if (prop === 'email') { value = value.trim().toLowerCase(); } target[prop] = value; return true; } });
這樣,每次給 formProxy.email 賦值時都會自動清理格式。
緩存函數結果(Memoization)
如果你有一個計算密集型的函數,可以用Proxy來緩存它的執行結果,避免重復計算。
function expensiveFunc(n) { console.log('計算中...'); return n * n; } const handler = { apply(target, thisArg, args) { const key = args.join(','); if (!this.cache) this.cache = {}; if (key in this.cache) { return this.cache[key]; } return this.cache[key] = Reflect.apply(...arguments); } }; const cachedFunc = new Proxy(expensiveFunc, handler); cachedFunc(5); // 計算中... 返回25 cachedFunc(5); // 直接返回緩存結果25
4. 注意事項
雖然Proxy很強大,但也有幾個需要注意的地方:
- 兼容性問題:IE不支持Proxy,如果需要兼容舊瀏覽器,可能需要用Object.defineProperty替代
- 性能開銷:頻繁使用Proxy可能會帶來一定性能損耗,尤其在大量數據操作時要謹慎使用
- 不可變性破壞:Proxy是對原對象的包裝,但不是深拷貝,修改Proxy會影響原對象
基本上就這些。掌握好Proxy的幾個常見陷阱方法,就能靈活應用在很多場景里,比如狀態管理、表單校驗、懶加載等。用得多了你會發現,它讓代碼更清晰、邏輯更容易封裝。