在访问使用Proxy不存在的属性时,我编写了一个小包装来返回undefined来代替typeError。这是代码:
function proxify(event) {
var proxy = new Proxy(event, {
get: function (target, property) {
if (property in target) {
return target[property];
} else {
return '';
}
}
}
});
return proxy;
}
当属性缺少1级深度时,此方法有效。 例如,假设obj.something不存在:
obj.something.else
将返回undefined
但是如果object属性是深层嵌套的
obj.something.else.deeper
我收到了一个typeError
我的问题是如何扩展上面的函数来处理深层嵌套对象?
THX
答案 0 :(得分:4)
您需要将返回值包装在proxify函数中:
function proxify(event) {
return isPrimitive(event) ? event : new Proxy(event, { get: getProp });
}
function isPrimitive(v) {
return v == null || (typeof v !== 'function' && typeof v !== 'object');
}
function getProp (target, property) {
if (property in target) {
return proxify(target[property]);
} else {
return proxify({});
}
}
说实话,你最好使用lodash's _.get()
或ramda's R.path()
之类的东西。从第一个getProp()
调用开始,无法知道评估将要进行多少深层,因此它必须始终返回原始值或“truthy”Proxy
实例,以便下一个属性访问可以被拦截(如果发生)。另一方面,_.get()
方法接受一个字符串,因此它可以立即从初始调用中知道您只是尝试访问这么多级别。
答案 1 :(得分:2)
正如idbehold所说,你必须返回原始值或新代理。 我认为你不需要loDash这样做,是的,你可以管理嵌套代理的深度! (见我的最后一点,deepProxy。 但是,由于我不确定你想做什么,我想把你的注意力集中在这几点上:
function proxify(event){
return isPrimitive(event) ? event : new Proxy(event,{ get: getProp });
}
function isPrimitive(v){
return v == null || (typeof v !== 'function' && typeof v !== 'object');
}
function getProp(target, property){
return (property in target)
? proxify(target[property])
: proxify({});
}
这个代码,它将模拟嵌套属性, 但不赋予任何成员依赖(因为没有赋值,那么没有保留)。
obj.something.else = 99;
console.log(obj.something.else) // returning a new Proxy()
IMO,它没有意义,或者保留给非常具体的案例。 同样,这取决于你的目的是什么。
基本不可扩展的作业
function proxify(defprop={})
{
return new Proxy(defprop, handler);
};
var handler =
{
get: function(target, property, receiver)
{
if(!(property in target))
target[property] = proxify();
return Reflect.get(target, property, receiver);
},
};
obj.something.else = 99;
console.log(obj.something.else) // returning 99
可分配
通过使用基本的可链接代理,如果尝试设置新对象(或嵌套对象),则只会捕获此新属性的根。 没有更多可能的链接,这是不合适的,也不安全。
请记住以下情况:
Cyph: 但是如果object属性是深层嵌套的
obj.something.else.deeper
(糟糕的方式)假设这个任务:
var deeper = {toto: "titi"};
obj.something.else = deeper;
console.log(obj.something.else.toto)
// will return "titi"
obj.something.else.toto.something.else = {tutu: "tata"};
// will return a typeError Again
(好方法)传播连锁能力 您需要在setter陷阱中检查值的类型作为真实对象,并代理每个根属性。剩下的深度将由吸气剂陷阱自然转换。
var handler =
{
get: function(target, property, receiver)
{
if(!(property in target))
target[property] = proxify();
return Reflect.get(target, property, receiver);
},
set: function(target, property, value, receiver)
{
// extend proxify to appended nested object
if(({}).toString.call(value) === "[object Object]")
value = deepApply(receiver, property, value);
return Reflect.set(target, property, value, receiver);
},
};
var deepApply = function(receiver,property, data)
{
var proxy = proxify();
var props = Object.keys(data);
var size = props.length;
for(var i = 0; i < size; i++)
{
property = props[i];
proxy[property] = data[property];
}
return proxy;
};
我邀请您阅读我的实际解决方案:deepProxy
答案 2 :(得分:0)
我在GitHub上发布了一个库( Observable Slim ),使您可以代理对象和该对象的任何嵌套子代。它还有一些额外的功能:
请随意看看,希望也有所贡献!