0

I'm experimenting with Proxies in ES6, was trying to create an infinitely chainable Proxy on an object(got from https://jsonplaceholder.typicode.com/users) which should return empty{} if the prop is not found.

I tried to implement this functionality up to 2nd level(e.g, user.address.geo). EDIT: Updated code for check type of prop value

let users = [{
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "[email protected]",
    "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": "[email protected]",
    "address": {
        "street": "Victor Plains",
        "suite": "Suite 879",
        "city": "Wisokyburgh",
        "zipcode": "90566-7771"
    },
    "phone": "010-692-6593 x09125",
    "website": "anastasia.net"
}];

I came up with below code

    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)
});

Output for this code is not appealing, it is returning undefined instead of an empty{} object

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

I did this few times and still getting the same result. Am I missing something?

5
  • 1
    There is no such thing as a "JSON Object" Commented Mar 16, 2017 at 17:27
  • checkJSON - what? That looks horribly convoluted and it's not clear at all what the function is supposed to do. Commented Mar 16, 2017 at 17:38
  • to Check whether the value is of type object: I got that from stackoverflow.com/questions/4295386/… Commented Mar 16, 2017 at 17:59
  • Shudder. Don't do that. You don't have any JSON around, so you don't need to stringify/parse anything. Just test typeof x == "object". Commented Mar 16, 2017 at 18:03
  • Updated the code, still not able to acheive the required functionality Commented Mar 17, 2017 at 11:32

1 Answer 1

4

You don't want to use map to wrap only the elements of your array in proxies. Instead, you want your get handler that returns properties to wrap all objects:

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

Every nested object access will go through the handler now, including things like pusers[0].contact.city.

Now you just need to add the default values for non-existing properties, and I guess you will want to store them on the respective target to allow mutations:

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);
Sign up to request clarification or add additional context in comments.

2 Comments

Shoot, I did not really look into changing the handler, just worked on assigning the handler to the obj array instead which is obviously wrong. thanks for the detailed explanation. One thing, So here the proxy will be applied dynamically right? while accessing the prop.
Yes, exactly. Notice that this implies pusers[0] != pusers[0] as they are different proxy instances created from different handler calls. If you want to avoid that, you'll need to store the proxies themselves somewhere (maybe a WeakMap).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.