How to Increment a Value in an Object or Map in JavaScript
A common task in programming is to keep a running count of items, such as the frequency of words in a text or the number of votes for different options. This often involves incrementing a value associated with a key in an object or a Map. The main challenge is handling the first time you encounter a key, where the value needs to be initialized to 1 instead of being incremented.
This guide will teach you the modern, concise, and robust methods for incrementing values in both plain objects and Map objects, using the nullish coalescing operator (??).
The Core Problem: Initializing vs. Incrementing
When you're counting items, your code must handle two different scenarios for any given key:
- If the key does not exist yet: You need to add it to your object or
Mapand initialize its value to1. - If the key already exists: You need to retrieve its current value, add
1to it, and update the value.
A naive if/else block can solve this, but modern JavaScript offers a much more elegant one-liner.
Incrementing a Value in an Object
The most robust and modern way to handle this is with the nullish coalescing operator (??). This operator provides a default value (0) only if the existing value is null or undefined.
For example, you have an object and want to increment the value for a key, or initialize it if it doesn't exist.
// Problem: How to increment 'apples' and initialize 'bananas'?
const fruitCounts = {
apples: 2,
};
Solution:
const fruitCounts = {
apples: 2,
};
// Increment the value for 'apples'
fruitCounts['apples'] = (fruitCounts['apples'] ?? 0) + 1;
console.log(fruitCounts.apples); // Output: 3
// Initialize the value for 'bananas'
fruitCounts['bananas'] = (fruitCounts['bananas'] ?? 0) + 1;
console.log(fruitCounts.bananas); // Output: 1
console.log(fruitCounts); // Output: { apples: 3, bananas: 1 }
How it works:
fruitCounts['apples'] ?? 0: The??operator checks the value offruitCounts['apples'].- Since it exists and is
2(which is notnullorundefined), the expression evaluates to2. The line becomesfruitCounts['apples'] = 2 + 1.
- Since it exists and is
fruitCounts['bananas'] ?? 0: The??operator checks the value offruitCounts['bananas'].- Since it doesn't exist, its value is
undefined. The??operator then returns the fallback value on the right,0. The line becomesfruitCounts['bananas'] = 0 + 1.
- Since it doesn't exist, its value is
Incrementing a Value in a Map
The logic is identical for a Map, but you use the .get() and .set() methods.
For example, you have a Map and want to increment a value or initialize it.
// Problem: Increment 'apples' and initialize 'bananas' in a Map.
const fruitMap = new Map([['apples', 2]]);
Solution:
const fruitMap = new Map([['apples', 2]]);
// Increment the value for 'apples'
fruitMap.set('apples', (fruitMap.get('apples') ?? 0) + 1);
console.log(fruitMap.get('apples')); // Output: 3
// Initialize the value for 'bananas'
fruitMap.set('bananas', (fruitMap.get('bananas') ?? 0) + 1);
console.log(fruitMap.get('bananas')); // Output: 1
console.log(fruitMap); // Output: Map(2) { 'apples' => 3, 'bananas' => 1 }
A Common Pitfall: Using the Logical OR (||) Operator
A common but flawed approach is to use the logical OR operator (||) instead of the nullish coalescing operator (??).
Here we have a problem of incorrect logic:
- The
||operator returns the right-hand side if the left-hand side is any falsy value (0,'',false,null,undefined). - The number
0is a valid count, but||will incorrectly treat it as a "missing" value.
// Problem: What happens when a count is 0?
const scores = {
'player1': 0
};
// INCORRECT: Using the || operator
scores['player1'] = scores['player1'] || 0;
scores['player1'] += 1; // This is now 0 + 1
console.log(scores['player1']); // Output: 1 (This seems to work...)
// But what if we try the one-liner?
scores['player1'] = (scores['player1'] || 0) + 1;
// This becomes: scores['player1'] = (0 || 0) + 1 => (0) + 1 => 1
// It works here, but it's a dangerous habit.
const scores2 = { player1: 0 };
scores2['player1'] = scores2['player1'] + 1 || 1;
// This becomes: scores2['player1'] = 0 + 1 || 1 => 1 || 1 => 1
console.log(scores2['player1']); // It still seems to work.
The nullish coalescing operator (??) does not have this bug. It only provides the fallback for null or undefined, correctly treating 0 as a valid, existing value.
Always use the nullish coalescing operator (??) for this pattern. It is safer and more explicit about what you are trying to achieve.
Conclusion
Incrementing a value in an object or Map is a simple task with modern JavaScript syntax.
- The recommended best practice is to use the nullish coalescing operator (
??) to provide a default value of0before adding1.- For objects:
obj[key] = (obj[key] ?? 0) + 1; - For Maps:
myMap.set(key, (myMap.get(key) ?? 0) + 1);
- For objects:
- Avoid using the logical OR (
||) operator for this pattern, as it can lead to bugs by incorrectly handling a count of0.
This modern approach is concise, readable, and robustly handles both initializing and incrementing values in a single line.