1. エージェント
プロキシは、特定の操作のデフォルトの動作を変更するために使用されます。これは、言語レベルで変更を行うことと同等であるため、一種の「メタ プログラミング」、つまりプログラミング言語のプログラミングに属します。
プロキシは、ターゲット オブジェクトの前に「インターセプト」層を設定するものとして理解できます。オブジェクトへの外部アクセスは、まずこのインターセプト層を通過する必要があります。そのため、外部アクセスをフィルタリングして書き換えるメカニズムが提供されます。プロキシという言葉の本来の意味は代理であり、ここでは特定の操作を「代理」することを示すために使用されており、「エージェント」と訳せます。
一般的に使用される 2 つの傍受方法
// ES5
let obj = {
}
let newVal = ''
Object.defineProperty(obj, 'name', {
get () {
console.log('get')
return newVal
},
set (val) {
console.log('set')
newVal = val
}
})
obj.name = 'zz'
console.log(obj.name )
// ES6 proxy
let obj = {
}
let p = new Proxy(obj, {
})
p.name = 'zzzzz'
console.log(p, obj.name)
// get
let arr = [11,22,33]
arr = new Proxy(arr, {
get(target, key) {
console.log(target, key)
if (key in target) {
return target[key]
} else {
return 'err'
}
}
})
console.log(arr[5])
// set
let arr = []
arr = new Proxy(arr, {
set(target, key, val) {
if (typeof val === 'number') {
target[key] = val
return true
} else {
return false
}
}
})
arr.push(1)
console.log(arr, arr[0], arr[1])
// has
let range = {
min: 1,
max: 5
}
range = new Proxy(range, {
has(target, key) {
return key >= target.min && key <= target.max
}
})
console.log( 2 in range)
console.log( 6 in range)
// ownKeys
let obj = {
name: 'zz',
[Symbol('66')]: 66
}
Object.getOwnPropertyNames(obj)
Object.getOwnPropertySymbols(obj)
Object.keys(obj)
Reflect.ownKeys(obj)
let userInfo = {
name: 'zz',
age: 25,
_password: '123456'
}
userInfo = new Proxy(userInfo, {
ownKeys(target) {
return Object.keys(target).filter(key => !key.startsWith('_'))
}
})
for (let key in userInfo) {
console.log(key)
}
console.log(Object.keys(userInfo))
// apply
let sum = (...args) => {
let sum = 0
args.forEach(item => {
sum += item
})
return sum
}
sum = new Proxy(sum, {
apply(target, ctx, args) {
return target(...args) * 2
}
})
console.log(sum(1,2))
console.log(sum.call(null, 1,2,3));
// construct
let User = class {
constructor (name) {
this.name = name
}
}
User = new Proxy(User, {
construct(target, args, newTarger) {
return new target(...args)
}
})
console.log(new User('zzz'))
//
let user = {
name: 'zz',
age: 25,
_password: '123456'
}
user = new Proxy(user, {
get(target, key) {
if (key.startsWith('_')) {
throw new Error('不可访问')
} else {
return target[key]
}
},
set(target, key, val) {
if (key.startsWith('_')) {
throw new Error('不可访问')
} else {
target[key] = val
return true
}
},
deleteProperty(target, key) {
if (key.startsWith('_')) {
throw new Error('不可删除')
} else {
delete target[key]
return true
}
},
ownKeys(target) {
return Object.keys(target).filter(key => !key.startsWith('_'))
},
// apply
})
try {
console.log(user._password)
} catch(e) {
console.log(e.message)
}
console.log(user.name)
user.age = 18
console.log(user)
for (let key in user) {
console.log(key)
}