1. get() 用于拦截某个属性的读取操作
let person = {
name: '张三'
}
let proxy = new Proxy(person, {
get: function(target, key) {
if(key in target) {
return target[key]
}else {
throw new ReferenceError(`${key} does not exist`)
}
}
})
console.log(proxy.name) // 张三
proxy.age // 报错
get拦截实现数组读取负数索引
function createArray(...elements) {
let handler = {
get(target, propKey, receiver) {
let index = Number(propKey)
if(index < 0) {
propKey = String(target.length + index)
}
return Reflect.get(target, propKey, receiver)
}
}
let target = []
target.push(...elements)
return new Proxy(target, handler)
}
let arr = createArray('a','b','c')
console.log(arr[-1]) // c
利用Proxy,可以将读取属性的操作(get)转变为执行某个函数,从而实现属性的链式操作。
2. set() 用于拦截某个属性的赋值操作
let validator = {
set: function(obj, prop, value) {
if(prop === 'age') {
if(!Number.isInteger(value)) {
throw new TypeError('The age is not an integer')
}
if(value > 200) {
throw new RangeError('The age seems invalid')
}
}
obj[prop] = value
}
}
let preson = new Proxy({}, validator)
preson.age = 100
console.log(preson.age) // 100
preson.age = 'young' //报错
preson.age = 300 //报错
3. apply() 拦截函数的调用、call和apply操作
接受3个参数,分别是目标对象、目标对象的上下文对象(this)和目标对象的参数数组
let target = function() {return 'I am the target'}
let handler = {
apply: function() {
return 'I am the proxy'
}
}
let p = new Proxy(target, handler)
console.log(p()) // I am the proxy
4. has() 可以隐藏某些属性,不被in操作符发现. {对for...in循环无效)
let handler = {
has(target, key) {
if(key[0] === '_') {
return false
}
return key in target
}
}
let target = {_prop: 'foo', prop: 'foo'}
let proxy = new Proxy(target, handler)
console.log('_prop' in proxy) // false
5. construct() 用于拦截new命令
let p = new Proxy(function() {}, {
construct: function(target, args) {
console.log('called:' + args.join(','))
return {value: args[0]*10}
}
})
console.log(new p(1).value)
6. deleteProperty() 用于拦截delete操作,如果这个方法抛出错误或者返回false,当前属性就无法被delete命令删除
let handler = {
deleteProperty(target, key) {
invariant(key, 'delete')
return true
}
}
function invariant(key, action) {
if(key[0] === '_') {
return false
}
}
let target = {_prop: 'foo'}
let proxy = new Proxy(target, handler)
delete proxy._prop
console.log(proxy)
7. defineProperty() 拦截Object.defineProperty操作
defineProperty方法返回false,导致添加新属性会抛出错误。
let handler = {
defineProperty (target, key, descriptor) {
return false
}
}
let target = {}
let proxy = new Proxy(target, handler)
proxy.foo = 'bar'
8.enumerate() 用于拦截for...in循环
9. getOwnPropertyDescriptor() 拦截Object.getOwnPropertyDescriptor,返回一个属性描述对象或者undefined
10. getPrototypeOf() getPrototypeOf方法主要用于拦截Object.getPrototypeOf()运算符,以及其他一些操作。
11. isExtensible()
12. ownKeys() 用于拦截Object.keys()操作
13. preventExtensions() 拦截Object.preventExtensions()。该方法必须返回一个布尔值。
14. setPrototypeOf() 用于拦截Object.setPrototypeOf方法