proxy
Proxy
概述
ES6提供原生Proxy构造函数,用来生成proxy实例
let proxy = new Proxy(target , handler)
上面 target表示要拦截的对象 , handler用来定制拦截行为
拦截读取属性的例子
let proxy = new Proxy({} , {
get: function(target , propKey){
console.log(target); // {}
console.log(propKey); //
return 33
}
})
console.log(proxy.title) // 33
console.log(proxy.name) // 33
Proxy支持的拦截操作
get()
get(target , propKey , receiver)
用于拦截某个属性的读取操作
接受三个参数,目标对象 , 属性名 , 可选的 proxy实例本身(严格来说是操作行为所针对的对象)
let person = {
name: '张三'
}
let proxy = new Proxy(person , {
get: function(target , propKey , receiver){
console.log(target , propKey , receiver);
if(propKey in person){
return person[propKey]
} else {
throw new ReferenceError(propKey + " is no found")
}
}
})
console.log(proxy.name)
console.log(proxy.title)
set
用来拦截某个属性的赋值操作
接受四个参数: 目标对象 属性名 属性值 proxy对象
拦截表单输入,表单验证抛出错误
<style>
.input{
width: 100px;
height: 20px;
}
.border{
border: 1px solid black;
}
.red-border{
border: 1px solid red;
}
</style>
<input type="text" class="input border" placeholder="年龄" oninput="inputAge(this.value)">
// 拦截的行为
let validator = {
set: function(target , porpKey , value , reveiver){
if(porpKey == 'age'){
// 大于20 异常
assert(value > 20 , 'more 20');
// 小于10 异常
assert(value < 10 , 'less 10');
}
target[porpKey] = value;
},
get: function(target , porpKey , receiver){
return target[porpKey];
}
}
let data = new Proxy({} , validator);
// 防抖
let throttle = {
wait: 1000 ,
timeoutId: null ,
process: function(func , ...nums){
if(typeof func == 'function'){
clearTimeout(this.timeoutId);
this.timeoutId = setTimeout(()=>{
func(...nums)
} , this.wait)
}
}
}
function inputAge(val){
let age = Number(val);
throttle.process(validAge , age)
}
let ageInput = document.querySelector("#ageInput")
function validAge(age){
try {
data.age = age;
console.log(data.age)
ageInput.classList.add("border")
ageInput.classList.remove("red-border")
} catch (error) {
// 异常的情况下边框要变红
ageInput.classList.remove("border")
ageInput.classList.add("red-border")
console.log(error.message)
}
}
// 自定义的抛异常的函数
function assert(condition , msg){
if(condition){
throw new Error(msg)
}
}
有时我们会定义一些内部属性,通常用 _name 这种形式 , 表示这些属性不应该被外部使用。
// 拦截的行为
let handler = {
get: function(target , propKey , proxy){
invariant(propKey , 'get');
return target[propKey]
},
set: function(target , propKey , value , proxy){
invariant(propKey , 'set');
target[propKey] = value
}
}
function invariant(key , action){
if(key[0] === '_'){
throw new Error( key + '' + action + '')
}
}
let proxy = new Proxy({} , handler);
proxy.name = 'www';
console.log(proxy.name);
proxy._name = '_nn';
console.log(proxy._name); //error
set方法的第四个参数
// 拦截的行为
let handler = {
set: function(target , propKey , value , proxy){
target[propKey] = proxy
}
}
let proxy = new Proxy({} , handler);
proxy.foo = 'xxx';
console.log(proxy.foo === proxy) // true
严格模式下,set不返回true的话就会报错
has
deleteProperty
待续。。。。