30 Seconds of Code is a brilliant collection of JavaScript snippets, digestible in ≤ 30 seconds. Anyone looking to master JavaScript should go through the entire thing.
The list didn’t contain a function to rename multiple object keys, however, so I created a pull request that thankfully got merged!
Here’s the official entry: https://30secondsofcode.org/object#renamekeys
I’ve previously written on renaming object keys, but we only changed one key at a time.
Then Adam Rowe kindly commented, asking how we might rename multiple object keys. I replied with this code sample after some thought and research.
renameKeys = (keysMap, obj) =>
Object.keys(obj).reduce(
(acc, key) => ({
...acc,
...{ [keysMap[key] || key]: obj[key] }
}),
{}
);
This was inspired by Ramda Adjunct’s renameKeys
function.
keysMap
contains key/value pairs of your old/new object keys.obj
is the object to be changed.
You might use it like this:
keysMap = {
name: 'firstName',
job: 'passion'
};
obj = {
name: 'Bobo',
job: 'Front-End Master'
};
renameKeys(keysMap, obj);
// { firstName: 'Bobo', passion: 'Front-End Master' }
Let’s step through it! We can write an expanded, debugger
-friendly version of this function:
renameKeys = (keysMap, obj) => {
debugger;
return Object.keys(obj).reduce((acc, key) => {
debugger;
const renamedObject = {
[keysMap[key] || key]: obj[key]
};
debugger;
return {
...acc,
...renamedObject
};
}, {});
};
And we’ll use it like this:
renameKeys(
{
name: 'firstName',
job: 'passion'
},
{
name: 'Bobo',
job: 'Front-End Master'
}
);
Pausing on line 2, we see that keysMap
and obj
have been properly assigned.
Here’s where the fun begins. Move to the next debugger
.
Inspect our local variables on line 7:
acc: {}
because that’sArray.reduce()
’s initial value (line 19).key: “name”
because it’s the first key fromObject.keys(obj)
.renamedObject: undefined
Also notice that we can access keysMap
and obj
from the parent function’s scope.
Guess what renamedObject
will be. Like in my aforementioned post, we’re using computed property names to dynamically assign renamedObject
’s key.
If keysMap[key]
exists, use it. Otherwise, use the original object key. In this case, keysMap[key]
is “firstName”
.
That’s renamedObject
’s key, what about its corresponding value?
It’s obj[key]
: "Bobo"
. Hit the next debugger
and check it out.
renamedObject
is now { firstName: “Bobo” }
.
Now using the spread operator, we’ll merge acc
and renamedObject
. Remember that acc
is currently .reduce
’s initial value: an empty object.
So merging acc
and renamedObject
just results in a clone of renamedObject
.
Since we’re returning this object, however, it becomes acc
in .reduce
’s next iteration. Move to the next debugger
to see this.
We’re inside .reduce
’s again, because there’s one more key
to process. We see that acc
is now { firstName: "Bobo" }
.
The same process runs again, and renamedObject
is properly created.
This time, merging acc
and renamedObject
actually makes a difference.
Run past this debugger
to return that object, and you’re done!
Here’s the final output:
Have fun renaming all the keys, until next time!