Question
How to Map Over Object Properties in JavaScript
Question
I have a JavaScript object:
const myObject = { a: 1, b: 2, c: 3 };
I want a native method similar to Array.prototype.map() that I could use like this:
const newObject = myObject.map(function (value, key) {
return value * value;
});
// newObject should become: { a: 1, b: 4, c: 9 }
Does JavaScript provide a built-in map() function for plain objects? I am using Node.js, so browser compatibility is not a concern.
Short Answer
By the end of this page, you will understand why plain JavaScript objects do not have a built-in map() method, and how developers typically achieve the same result using Object.keys(), Object.entries(), Object.fromEntries(), loops, or small helper functions. You will also learn when to use an object versus an array for transformations.
Concept
Plain JavaScript objects and arrays are different data structures.
- Arrays are ordered collections and come with array methods like
map(),filter(), andreduce(). - Objects are key-value collections and do not have a built-in
map()method.
So the direct answer is: No, JavaScript does not provide a native map() method for plain objects.
However, you can still "map over" an object's properties by converting the object into something iterable, transforming it, and then turning it back into an object.
A common modern pattern is:
- Get the object's entries with
Object.entries(obj) - Use array methods like
map() - Rebuild an object with
Object.fromEntries()
Example:
const myObject = { a: 1, b: 2, c: 3 };
const newObject = Object.fromEntries(
Object.entries(myObject).map(([key, value]) => [key, value * value])
);
console.log(newObject); // { a: 1, b: 4, c: 9 }
This matters in real programming because object transformation is common when:
- formatting API responses
- converting configuration values
- normalizing data
- applying validation or cleanup logic
- renaming or recalculating fields
Understanding this pattern helps you work cleanly with JavaScript data structures instead of trying to force array methods onto objects.
Mental Model
Think of an array as a row of numbered boxes:
- box 0
- box 1
- box 2
Because arrays are ordered, JavaScript gives them tools like map() to process each box in sequence.
Think of an object as a set of labeled drawers:
- drawer
a - drawer
b - drawer
c
Objects are organized by keys, not by numeric positions. Since they are not arrays, they do not automatically get array methods like map().
So when you want to "map an object," you usually:
- open all the labeled drawers (
Object.entries()) - transform each drawer's contents (
map()) - rebuild the cabinet (
Object.fromEntries())
That is the core idea.
Syntax and Examples
The most common ways to transform object values are shown below.
1. Using Object.entries() and Object.fromEntries()
const myObject = { a: 1, b: 2, c: 3 };
const squared = Object.fromEntries(
Object.entries(myObject).map(([key, value]) => [key, value * value])
);
console.log(squared); // { a: 1, b: 4, c: 9 }
How it works
Object.entries(myObject)returns:
[['a', 1], ['b', 2], ['c', 3]]
- Then
.map()transforms each[key, value] Object.fromEntries()builds a new object from the transformed pairs
2. Using Object.keys()
const myObject = { a: 1, b: 2, c: 3 };
const result = {};
Object.keys(myObject).forEach((key) => {
result[key] = myObject[key] * myObject[key];
});
console.log(result); // { a: 1, b: 4, c: 9 }
This is slightly more manual, but very readable.
3. Creating a reusable helper
function mapObject(obj, callback) {
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key, callback(value, key)])
);
}
const myObject = { a: 1, b: 2, c: 3 };
const newObject = mapObject(myObject, (value, key) => value * value);
console.log(newObject); // { a: 1, b: 4, c: 9 }
This gives you a function that feels similar to array map().
4. Using a for...of loop
const myObject = { a: 1, b: 2, c: 3 };
const newObject = {};
for (const [key, value] of Object.entries(myObject)) {
newObject[key] = value * value;
}
console.log(newObject); // { a: 1, b: 4, c: 9 }
This is a good option when you want simple, explicit code.
Step by Step Execution
Consider this example:
const myObject = { a: 1, b: 2, c: 3 };
const result = Object.fromEntries(
Object.entries(myObject).map(([key, value]) => [key, value * 2])
);
console.log(result);
Here is what happens step by step.
Step 1: Start with the original object
{ a: 1, b: 2, c: 3 }
Step 2: Convert the object into entries
Object.entries(myObject)
Result:
[['a', 1], ['b', 2], ['c', 3]]
Now the data is in an array, so array methods like map() can be used.
Step 3: Map each entry
.map(([key, value]) => [key, value * 2])
Each entry is transformed:
['a', 1]becomes['a', 2]['b', 2]becomes['b', 4]['c', 3]becomes['c', 6]
Now we have:
[['a', 2], ['b', 4], ['c', 6]]
Step 4: Convert the mapped entries back into an object
Object.fromEntries(...)
Result:
{ a: 2, b: 4, c: 6 }
Step 5: Print the final object
console.log(result);
Output:
{ a: 2, b: 4, c: 6 }
Real World Use Cases
Object mapping is useful whenever you need to transform values while keeping the same keys.
Common examples
1. Formatting API response data
const prices = { apple: 1.2, banana: 0.8 };
const formatted = Object.fromEntries(
Object.entries(prices).map(([key, value]) => [key, `$${value.toFixed(2)}`])
);
console.log(formatted); // { apple: '$1.20', banana: '$0.80' }
2. Converting configuration values
const envConfig = { port: '3000', debug: 'true' };
const parsed = {
port: Number(envConfig.port),
debug: envConfig.debug === 'true'
};
Or with a helper when rules are consistent.
3. Normalizing imported data
const scores = { alice: 10, bob: 20 };
const normalized = Object.fromEntries(
Object.entries(scores).map(([name, score]) => [name, score / 10])
);
4. Cleaning user input
const input = { firstName: ' Alice ', city: ' London ' };
const cleaned = Object.fromEntries(
Object.entries(input).map(([key, value]) => [key, value.trim()])
);
5. Preparing data before saving to a database
const flags = { emailVerified: 1, isAdmin: 0 };
const booleans = Object.fromEntries(
Object.entries(flags).map(([key, value]) => [key, Boolean(value)])
);
Real Codebase Usage
In real projects, developers usually do not try to add map() directly to all objects. Instead, they use one of these patterns.
1. Small utility function
A reusable helper keeps code clean.
function mapObjectValues(obj, transform) {
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key, transform(value, key)])
);
}
This is common in service layers, data formatting utilities, and validation modules.
2. Guard clauses before transformation
Real code often validates input first.
function mapObjectValues(obj, transform) {
if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) {
throw new TypeError('Expected a plain object');
}
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key, transform(value, key)])
);
}
This avoids unexpected errors.
3. Early returns for empty objects
function doubleValues(obj) {
if (Object.keys(obj).length === 0) {
return {};
}
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key, value * 2])
);
}
4. Combining map with filtering
Sometimes developers first remove unwanted keys, then transform.
const settings = { theme: 'dark', cache: null, language: 'en' };
const cleaned = Object.fromEntries(
Object.entries(settings)
.filter(([, value]) => value !== null)
.map(([key, value]) => [key, String(value)])
);
5. Error handling during transformation
function safeParseNumbers(obj) {
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => {
const num = Number(value);
if (Number.isNaN(num)) {
throw new Error(`Invalid number for key: ${key}`);
}
return [key, num];
})
);
}
These are the kinds of patterns you see in production code.
Common Mistakes
1. Trying to call .map() directly on an object
This does not work:
const obj = { a: 1, b: 2 };
obj.map((value) => value * 2);
Why it fails:
- plain objects do not have a
map()method
Use this instead:
const result = Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key, value * 2])
);
2. Using Object.keys() but forgetting to build a new object
Broken idea:
const obj = { a: 1, b: 2 };
const result = Object.keys(obj).map((key) => obj[key] * 2);
console.log(result); // [2, 4]
This returns an array, not an object.
If you want an object, rebuild it:
const result = Object.fromEntries(
Object.keys(obj).map((key) => [key, obj[key] * 2])
);
3. Mutating the original object by accident
const obj = { a: 1, b: 2 };
Object.keys(obj).forEach((key) => {
obj[key] = obj[key] * 2;
});
console.log(obj); // original object changed
If you want a new object, assign into a separate object.
4. Confusing arrays and objects
const data = { 0: 'a', 1: 'b' };
This may look array-like, but it is still an object. It does not get array methods.
5. Ignoring inherited properties when using for...in
for (const key in obj) {
// may include inherited properties
}
Safer for most transformations:
Object.keys(obj)Object.entries(obj)Object.hasOwn(obj, key)when needed
6. Forgetting that keys are strings
Object keys are typically strings, even if they look numeric.
const obj = { 1: 'one', 2: 'two' };
console.log(Object.keys(obj)); // ['1', '2']
Comparisons
| Approach | Works on | Returns | Best for | Example |
|---|---|---|---|---|
Array.prototype.map() | Arrays | New array | Ordered lists | [1, 2, 3].map(x => x * 2) |
Object.keys() + loop | Objects | Whatever you build | Simple object transformations | build result manually |
Object.entries() + map() + Object.fromEntries() | Objects | New object | Clean value/key transformation | transform key-value pairs |
for...in | Objects | Whatever you build | Older or manual iteration | must check own properties |
reduce() on entries | Arrays or converted object entries | Any structure | Flexible accumulation | advanced but powerful |
Object.keys() vs Object.entries()
| Method | Output | Best when |
|---|---|---|
Object.keys(obj) | Array of keys | You only need keys |
Object.values(obj) | Array of values | You only need values |
Object.entries(obj) | Array of [key, value] pairs | You need both key and value |
Object vs Array
| Feature | Object | Array |
|---|---|---|
| Structure | Key-value pairs | Ordered list |
Has native map() | No | Yes |
| Good for | Named fields, dictionaries | Sequences of items |
| Common access | obj.name or obj['name'] | arr[0] |
Cheat Sheet
// No native object.map() exists for plain objects
Common pattern
const result = Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key, transform(value, key)])
);
Reusable helper
function mapObject(obj, fn) {
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key, fn(value, key)])
);
}
Alternatives
Using Object.keys()
const result = {};
Object.keys(obj).forEach((key) => {
result[key] = fn(obj[key], key);
});
Using for...of
const result = {};
for (const [key, value] of Object.entries(obj)) {
result[key] = fn(value, key);
}
Important rules
- Plain objects do not have
.map() Object.entries(obj)gives[[key, value], ...]Object.fromEntries(entries)turns entries back into an objectObject.keys(obj).map(...)returns an array unless you rebuild an object- Use arrays when you need array methods directly
Edge cases
nullis not a valid object to map over- Arrays are objects, but should usually be handled with array methods instead
for...inmay include inherited properties- Object keys are usually strings
FAQ
Is there a native map() for JavaScript objects?
No. Plain objects do not have a built-in map() method.
What is the modern way to map over an object in JavaScript?
The most common modern approach is:
Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key, transform(value, key)])
)
Can I use Object.keys() instead of Object.entries()?
Yes. Object.keys() works well if you only need the keys and can access values with obj[key].
Why does Object.keys(obj).map(...) return an array?
Because Object.keys(obj) returns an array, and array map() always returns a new array.
Should I add map() to Object.prototype?
Usually no. Modifying built-in prototypes can cause confusion and bugs in real projects.
Is for...in a good way to map an object?
It can work, but you must be careful about inherited properties. Object.keys() or Object.entries() are usually safer.
What if I only want to transform values and keep the same keys?
Use Object.entries() with Object.fromEntries(), or a helper function that wraps that pattern.
Mini Project
Description
Build a small utility that transforms the values of a settings object while keeping the same keys. This demonstrates the standard JavaScript pattern for object mapping and mirrors how developers normalize configuration or API data in real projects.
Goal
Create a reusable mapObjectValues() function and use it to transform an object's values into a new object.
Requirements
- Create a function named
mapObjectValuesthat accepts an object and a callback. - Return a new object instead of mutating the original one.
- Pass both
valueandkeyto the callback. - Use the function to transform a sample object of numeric values.
- Print both the original object and the transformed object.
Keep learning
Related questions
Abort Ajax Requests with jQuery jqXHR.abort()
Learn how to cancel an in-progress jQuery Ajax request with jqXHR.abort(), handle abort status safely, and avoid stale UI updates.
Access the Correct this Inside a JavaScript Callback
Learn why JavaScript this changes in callbacks and how to preserve an object context using bind, arrow functions, and event handler patterns.
Add Key-Value Pairs to JavaScript Objects
Learn how to add key-value pairs to JavaScript objects with dot and bracket notation, dynamic keys, examples, and common mistakes.