Home > Blockchain >  Pulling dynamic values from JavaScript object
Pulling dynamic values from JavaScript object

Time:01-16

I want to destructure a dynamic key from a object, where `key` is some pattern. There is counter appended to key.

var obj = {
 "key2":{"left":{"content": "This data to be pulled"}},
 "hasErrorcharges2":false,
 "hasErrorcharges2_Card":""
}
const {key2: {left: content }} = obj;

Here key2 is dynamic. So we know that it will always start with key and the other values can be key0, key1, key3 and hence forth. How do we traverse in this case?

Things tried.

  1. Match the if object has any key similar to it. and then return the matched key. but got true false

  2. can't destructure dynamic prop. but in this we know a pattern

  3. traverse through the object with dynamic property and get the value.

  4. expecting to write a similar function like hasOwn() or hasOwnProperty

CodePudding user response:

You can't do the destructuring until you know the name of the property. You can find it by using find on Object.keys. Then you can use computed property notation to specify that name in the destructuring expression. (There's also a small error in that expression, see the highlighted bit below.)

const keyName = Object.keys(obj).find((key) => key.startsWith("key"));
if (keyName) {
    const {
//      vvvvvvvvv−−−−−−−−−−−−−−−−−−−−−−−−−− computed property notation
        [keyName]: { left: { content } },
//                         ^−−−−−−−−−^−−−−− minor correction to destructuring
    } = obj;
    // ...
}

There I've just checked that the property name starts with key — you might want to beef up the condition in the find callback, but that's the general idea.

Live Example:

const obj = {
    key2: { left: { content: "This data to be pulled" } },
    hasErrorcharges2: false,
    hasErrorcharges2_Card: "",
};
const keyName = Object.keys(obj).find((key) => key.startsWith("key"));
if (keyName) {
    const {
        [keyName]: { left: { content } },
    } = obj;
    console.log(`content = ${content}`);
}


That said, if you need to loop through the object properties anyway, it may not be worth setting yourself up for destructuring vs. just grabbing the property in a loop and breaking when you find it:

let content = null;
for (const key in obj) {
    if (key.startsWith("key")) {
        content = obj[key].left.content;
        break;
    }
}
if (content !== null) { // Valid only if we know content won't be `null` in the object
    // ...
}

Live Example:

const obj = {
    key2: { left: { content: "This data to be pulled" } },
    hasErrorcharges2: false,
    hasErrorcharges2_Card: "",
};
let content = null;
for (const key in obj) {
    if (key.startsWith("key")) {
        content = obj[key].left.content;
        break;
    }
}
if (content !== null) { // Valid only if we know content won't be `null` in the object
    console.log(`content = ${content}`);
}

If you like, this:

content = obj[key].left.content;

could be:

({ content } = obj[key].left);

...which avoid repeating the identifier content. Or even:

({left: { content }} = obj[key]);

...though there's really no need to use the nested destructuring, it doesn't save you anything. :-)

(We need the () around it because otherwise the { at the beginning looks like the beginning of a block to the JavaScript parser.)

  • Related