【问题标题】:Implement Proxy on a nested object在嵌套对象上实现代理
【发布时间】:2017-08-08 00:16:11
【问题描述】:

我在 ES6 中尝试使用代理,试图在一个对象上创建一个无限可链接的代理(从https://jsonplaceholder.typicode.com/users 获得),如果找不到该属性,它应该返回 empty{}

我尝试将此功能实现到第二级(例如,user.address.geo)。 编辑:更新了检查道具值类型的代码

let users = [{
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
        "street": "Kulas Light",
        "suite": "Apt. 556",
        "city": "Gwenborough",
        "zipcode": "92998-3874"
    },
    "phone": "1-770-736-8031 x56442",
    "website": "hildegard.org"
},
{
    "id": 2,
    "name": "Ervin Howell",
    "username": "Antonette",
    "email": "Shanna@melissa.tv",
    "address": {
        "street": "Victor Plains",
        "suite": "Suite 879",
        "city": "Wisokyburgh",
        "zipcode": "90566-7771"
    },
    "phone": "010-692-6593 x09125",
    "website": "anastasia.net"
}];

我想出了下面的代码

    var handler = {
    get: function (target, name) {
        return name in target ?
            target[name] : {};
    }
};

let pusers = users.map(item => {
    let pitem = new Proxy(item, handler);
    Reflect.ownKeys(pitem).map(prop => {
        pitem[prop] = (typeof pitem[prop] == 'object') ? new Proxy(pitem[prop], handler) : pitem[prop];
    })
    return pitem;
});

pusers.map(u => {
    console.log(u.address);
    console.log(u.contact.city)
});

此代码的输出不吸引人,它返回 undefined 而不是空的{} 对象

{ street: 'Kulas Light',
  suite: 'Apt. 556',
  city: 'Gwenborough',
  zipcode: '92998-3874' }
undefined

我这样做了几次,仍然得到相同的结果。我错过了什么吗?

【问题讨论】:

  • checkJSON - 什么?这看起来非常复杂,根本不清楚该函数应该做什么。
  • 检查值是否为对象类型:我从stackoverflow.com/questions/4295386/…得到的
  • 不寒而栗。不要那样做。您周围没有任何 JSON,因此您不需要对任何内容进行字符串化/解析。只需测试typeof x == "object"
  • 更新了代码,仍然无法实现所需的功能

标签: javascript proxy ecmascript-6


【解决方案1】:

您不想使用map 仅将数组的元素包装在代理中。相反,您希望您的 get 处理程序返回属性以包装所有对象:

const handler = {
    get(target, name) {
        const v = target[name];
        return typeof v == "object" ? new Proxy(v, handler) : v;
    }
};
let pusers = new Proxy(users, handler);

现在每个嵌套对象访问都将通过处理程序,包括 pusers[0].contact.city 之类的内容。

现在您只需要为不存在的属性添加默认值,我猜您会希望将它们存储在相应的目标上以允许突变:

const handler = {
    get(target, name) {
        const v = name in target ? target[name] : (target[name] = {});
        return typeof v == "object" ? new Proxy(v, handler) : v;
    }
};
let pusers = new Proxy(users, handler);

【讨论】:

  • 射击,我并没有真正考虑更改处理程序,只是将处理程序分配给 obj 数组,这显然是错误的。感谢您的详细解释。一件事,所以这里的代理将被动态应用对吗?在访问道具时。
  • 是的,完全正确。请注意,这意味着pusers[0] != pusers[0],因为它们是从不同的处理程序调用创建的不同代理实例。如果您想避免这种情况,您需要将代理自己存储在某个地方(可能是WeakMap)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-06
  • 1970-01-01
  • 2011-03-16
相关资源
最近更新 更多