什么是Proxy?
Proxy对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)
语法
const p = new Proxy(target, handler)
参数说明
target | 要使用Proxy包装的目标对象 |
handler | 处理器对象 |
创建一个可撤销的Proxy对象
Proxy.revocable()
基础示例
const handler = { get: function(obj, prop) { return prop in obj ? obj[prop] : 37 } } const p = new Proxy({}, handler) p.a = 1 p.b = undefined console.log(p.a, p.b) // 1, undefined console.log('c' in p, p.c) // false, 37
无操作转发代理
let target = {} let p = new Proxy(target, {}) p.a = 37 // 操作转发到目标 console.log(target.a) // 37
验证
通过代理,你可以轻松地验证向一个对象的传值。
1 let validator = { 2 set: function(obj, prop, value) { 3 if (prop === 'age') { 4 if (!Number.isInteger(value)) { 5 throw new TypeError('The age is not an integer') 6 } 7 if (value > 200) { 8 throw new RangeError('The age seems invalid') 9 } 10 } 11 12 obj[prop] = value; 13 14 return true; // 表示成功 15 } 16 } 17 18 let person = new Proxy({}, validator) 19 20 person.age = 100 21 22 console.log(person.age) 23 24 person.age = 'young' 25 person.age = 300
操作DOM节点
有时候可能需要互换两个不同元素的属性或类名,下面的代码以此为目标,展示了set handler的使用场景
let view = new Proxy({ selected: null }, { set: function(obj, prop, newval) { let objval = obj[prop] if (prop === 'selected') { if (oldval) { oldval.setAttribute('aria-selected', 'false') } if (newval) { newval.setAttribute('aria-selected', 'true') } } obj[prop] = newval return true; // 表示操作成功 } }) let i1 = view.selected = document.getElementById('item-1') console.log(i1.getAttribute('aria-selected')) // 'true' let i2 = view.selected = document.getElementById('item-2') console.log(i1.getAttribute('aria-selected')) // 'false' console.log(i2.getAttribute('aria-selected')) // 'true'
通过属性查找数组中的特定对象
以下代理为数组扩展了一些实用工具。
let products = new Proxy([{ name: 'Firefox', type: 'browser' }, { name: 'SeaMonkey', type: 'browser' }, { name: 'Thunderbird', type: 'mailer' }], { get: function(obj, prop) { // 默认行为是返回属性值,prop通常是一个整数 if (prop in obj) { return obj[prop] } if (prop === 'number') { return obj.length } let result, types = {}; for (let product of obj) { if (product.name === prop) { result = product; } if (types[product.type]) { types[product.type].push(product) } else { types[product.type] = [product] } } // 通过name获取product if (result) { return result; } // 通过type获取products if (prop in types) { return types[prop] } // 获取product type if (prop === 'types') { return Object.keys(types) } return undefined; } }) // console.log(products[0]) // console.log(products['Firefox']) console.log(products['Chrome']) // undefined console.log(products.browser) console.log(products.types) // ['browser', 'mailer'] console.log(products.number) // 3
内容摘自文档:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy