Proxy
-代理,在JS里就是对数据进行代理。
用proxy代理json数据
let data = { a: 100 };
let p = new Proxy(data, {
has() {},
get() {},
set() {},
deleteProperty() {},
});
上面建立的Proxy
实例p
就是给data
创建了一个数据代理,我列出来了4个常用的方法:
has
:调用in
的时候就会触发该方法,例如'a' in p
get
:获取属性的时候就会触发该方法,例如p.a
set
:设置属性的时候就会触发该方法,例如p.a = 200
deleteProperty
:删除属性的时候就会触发该方法,例如delete(p.a)
注意,这里和defineProperty
使用上有一点不同的是,我们在新建了Proxy
对象之后,需要对实例进行操作才会进行相应的拦截,而对原数据操作是不会触发这些方法的。
下面我们来把这些方法填充一下,对一个json数据做一个简单的拦截:
let data = { a: 100 };
let p = new Proxy(data, {
has(data, name) {
return name in data;
},
get(data, name) {
if (name in data) {
return data[name];
} else {
throw new Error(`${name} is not defined.`);
}
},
set(data, name, val) {
data[name] = val;
},
deleteProperty(data, name) {
if (name in data) {
return delete data[name];
} else {
throw new Error(`${name} is not defined.`);
}
},
});
可以看到,这些方法都接收原始数据做为第一个参数,然后就是key
,也就是上面写的name。
用proxy代理function
let _fn = function (a, b) {
console.log(a + b);
};
let sum = new Proxy(_fn, {
apply(fn, thisArgs, args) {
if (args.length < 2) {
throw new Error(`参数太少!`);
} else {
fn(...args);
}
},
});
sum(1000, 2999);
在使用Proxy
代理函数的时候,有一个apply
会被调用,该方法第一个参数fn
就是所代理的目标函数,第二个thisArgs
是调用该代理函数时的this
,第三个args
就是调用代理函数时所传过来的参数。
上面代码的执行结果很明显了:
用proxy代理class
new Proxy(class {},{
construct(cls,args){ ... }
})
当我们使用Proxy
来代理一个类的时候,我们在对这个代理对象进行实例化的时候就会调用construct
方法,在这里面我们可以将代理的目标类变成一个响应类:
let A = new Proxy(
class {
render() {
console.log("rendered~");
}
},
{
construct(cls, args) {
let obj = new cls();
return new Proxy(obj, {
set(data, name, val) {
data[name] = val;
obj.render();
},
});
},
}
);
上面,我们代理的目标类里面有一个render
方法,在construct
里面,我们将原类进行了实例化,但这个实例本身并不是一个可响应的对象(obj
),所以我们在里面还要给它加一个代理之后再进行返回。
现在如果进行new A()
并且设置属性就会看到:
我在设置a.username
的时候,那么就会触发render
,其实也就是被set
进行了拦截,拦截的过程中想做什么就看我们自己了。