是什么?
Proxy 对象,是ES6引入的一个强大特性,用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
1. 基本语法
const proxy = new Proxy(target, handler)
// target: 要包装的目标对象
// handler: 一个对象,包含各种"陷阱"(trap)方法
2. 常用陷阱方法
get 拦截
const obj = { name: '张三' }
const proxy = new Proxy(obj, {
get(target, property) {
console.log(`读取属性: ${property}`)
return target[property] || '默认值'
}
})
console.log(proxy.name) // 读取属性: name \n 张三
console.log(proxy.age) // 读取属性: age \n 默认值
set 拦截
const validator = {
set(target, key, value) {
if (key === 'age') {
if (!Number.isInteger(value) || value < 0) {
throw new TypeError('年龄必须是正整数')
}
}
target[key] = value
return true // 表示设置成功
}
}
const person = new Proxy({}, validator)
person.age = 25 // 正常
person.age = -5 // 报错: 年龄必须是正整数
apply 拦截函数调用
function sum(a, b) {
return a + b
}
const proxy = new Proxy(sum, {
apply(target, thisArg, argumentsList) {
console.log(`调用函数,参数: ${argumentsList}`)
return target(...argumentsList) * 2
}
})
console.log(proxy(1, 2)) // 调用函数,参数: 1,2 \n 6
has 拦截 in 操作符
const obj = { _secret: 'secret', public: 'public' }
const proxy = new Proxy(obj, {
has(target, key) {
if (key[0] === '_') return false
return key in target
}
})
console.log('_secret' in proxy) // false
console.log('public' in proxy) // true
3. 其他常用陷阱方法
deleteProperty
const obj = { name: '张三', _id: 123 }
const proxy = new Proxy(obj, {
deleteProperty(target, key) {
if (key[0] === '_') {
throw new Error('不能删除私有属性')
}
delete target[key]
return true
}
})
delete proxy.name // 成功
delete proxy._id // 报错: 不能删除私有属性
ownKeys
const obj = { name: '张三', age: 25, _secret: '123' }
const proxy = new Proxy(obj, {
ownKeys(target) {
return Object.keys(target).filter(key => key[0] !== '_')
}
})
console.log(Object.keys(proxy)) // ['name', 'age']
4. 可撤销的Proxy
const target = { name: '张三' }
const { proxy, revoke } = Proxy.revocable(target, {
get(target, key) {
return target[key] || '默认值'
}
})
console.log(proxy.name) // 张三
revoke() // 撤销代理
console.log(proxy.name) // TypeError: Cannot perform 'get' on a proxy that has been revoked
5. 实际应用场景
- 数据验证
- 数据绑定和响应式系统(如Vue 3的响应式实现)
- 函数参数验证
- 实现私有属性
- 性能优化(延迟加载属性)
- 日志记录和调试
Proxy的这些核心用法使得它在现代JavaScript开发中非常强大,特别是在构建框架和库时