Proxy是ES6中提供的新的API,可以用来定义对象各种基本操作的自定义行为 (在文档中被称为traps,我觉得可以理解为一个针对对象各种行为的钩子),拿它可以做很多有意思的事情,在我们需要对一些对象的行为进行控制 ...
![]() Proxy是什么首先,我们要清楚, 可以理解为,有一个很火的明星,开通了一个微博账号,这个账号非常活跃,回复粉丝、到处点赞之类的,但可能并不是真的由本人在维护的。 而是在背后有一个其他人 or 团队来运营,我们就可以称他们为代理人,因为他们发表的微博就代表了明星本人的意思。 P.S. 强行举例子,因为本人不追星,只是猜测可能会有这样的运营团队 这个代入到 JavaScript中的ProxyProxy是ES6中提供的新的API,可以用来定义对象各种基本操作的自定义行为 (在文档中被称为traps,我觉得可以理解为一个针对对象各种行为的钩子),拿它可以做很多有意思的事情,在我们需要对一些对象的行为进行控制时将变得非常有效。 Proxy的语法创建一个
let target = {}
let handlers = {} // do nothing
let proxy = new Proxy(target, handlers)
proxy.a = 123
console.log(target.a) // 123在第二个参数为空对象的情况下,基本可以理解为是对第一个参数做的一次浅拷贝 Traps(各种行为的代理)就像上边的示例代码一样,如果没有定义对应的 当我们写了某个 最常用的两个 早年 let obj = {
_age: 18,
get age () {
return `I'm ${this._age} years old`
},
set age (val) {
this._age = Number(val)
}
}
console.log(obj.age) // I'm 18 years old
obj.age = 19
console.log(obj.age) // I'm 19 years old就像这段代码描述的一样,我们设置了一个属性 然后我们可以直接调用 这么做有几个缺点:
let target = { age: 18, name: 'Niko Bellic' }
let handlers = {
get (target, property) {
return `${property}: ${target[property]}`
},
set (target, property, value) {
target[property] = value
}
}
let proxy = new Proxy(target, handlers)
proxy.age = 19
console.log(target.age, proxy.age) // 19, age : 19
console.log(target.name, proxy.name) // Niko Bellic, name: Niko Bellic我们通过创建 而且我们无需额外的用一个 拿Proxy来做些什么因为在使用了 在下边列出了几个简单的适用场景。 解决对象属性为undefined的问题在一些层级比较深的对象属性获取中,如何处理 (() => {
let target = {}
let handlers = {
get: (target, property) => {
target[property] = (property in target) ? target[property] : {}
if (typeof target[property] === 'object') {
return new Proxy(target[property], handlers)
}
return target[property]
}
}
let proxy = new Proxy(target, handlers)
console.log('z' in proxy.x.y) // false (其实这一步已经针对`target`创建了一个x.y的属性)
proxy.x.y.z = 'hello'
console.log('z' in proxy.x.y) // true
console.log(target.x.y.z) // hello
})()我们代理了 这样就能够保证我们的取值操作一定不会抛出 普通函数与构造函数的兼容处理如果我们提供了一个 class Test {
constructor (a, b) {
console.log('constructor', a, b)
}
}
// Test(1, 2) // throw an error
let proxyClass = new Proxy(Test, {
apply (target, thisArg, argumentsList) {
// 如果想要禁止使用非new的方式来调用函数,直接抛出异常即可
// throw new Error(`Function ${target.name} cannot be invoked without 'new'`)
return new (target.bind(thisArg, ...argumentsList))()
}
})
proxyClass(1, 2) // constructor 1 2我们使用了 以及如果我们想要对函数进行限制,禁止使用 function add (a, b) {
return a + b
}
let proxy = new Proxy(add, {
construct (target, argumentsList, newTarget) {
throw new Error(`Function ${target.name} cannot be invoked with 'new'`)
}
})
proxy(1, 2) // 3
new proxy(1, 2) // throw an error用Proxy来包装fetch在前端发送请求,我们现在经常用到的应该就是 let handlers = {
get (target, property) {
if (!target.init) {
// 初始化对象
['GET', 'POST'].forEach(method => {
target[method] = (url, params = {}) => {
return fetch(url, {
headers: {
'content-type': 'application/json'
},
mode: 'cors',
credentials: 'same-origin',
method,
...params
}).then(response => response.json())
}
})
}
return target[property]
}
}
let API = new Proxy({}, handlers)
await API.GET('XXX')
await API.POST('XXX', {
body: JSON.stringify({name: 1})
})对 实现一个简易的断言工具写过测试的各位童鞋,应该都会知道断言这个东西 let assert = new Proxy({}, {
set (target, message, value) {
if (!value) console.error(message)
}
})
assert['Isn\'t true'] = false // Error: Isn't true
assert['Less than 18'] = 18 >= 19 // Error: Less than 18统计函数调用次数在做服务端时,我们可以用 function orginFunction () {}
let proxyFunction = new Proxy(orginFunction, {
apply (target, thisArg. argumentsList) {
log(XXX)
return target.apply(thisArg, argumentsList)
}
})全部的traps这里列出了
更多编程相关知识,请访问:编程学习网站!! 以上就是详解JavaScript中的Proxy(代理)的详细内容,更多请关注模板之家(www.mb5.com.cn)其它相关文章! |
