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.
Match the if object has any key similar to it. and then return the matched key. but got true false
can't destructure dynamic prop. but in this we know a pattern
traverse through the object with dynamic property and get the value.
expecting to write a similar function like
hasOwn()
orhasOwnProperty
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.)