// Anti-pattern inherited from Python thinking
const DEFAULT_CONFIG = { tags: [] };
function createPost(title, config = DEFAULT_CONFIG) {
config.tags.push('auto-tagged');
return { title, ...config };
}
const p1 = createPost('Hello');
const p2 = createPost('World');
console.log(p1.tags);
console.log(p2.tags);function createPost(title, config = {}) {
// Create a new config by merging defaults with provided config
const finalConfig = {
tags: [],
category: 'uncategorized',
...config,
tags: [...(config.tags || [])] // shallow copy of tags array
};
finalConfig.tags.push('auto-tagged');
return { title, ...finalConfig };
}
// Or even simpler with destructuring defaults:
function createPost(title, { tags = [], category = 'uncategorized' } = {}) {
return { title, tags: [...tags, 'auto-tagged'], category };
}Bug: DEFAULT_CONFIG is a shared mutable object. config.tags.push() mutates the shared tags array. p2 inherits all mutations from p1's call.
Explanation: Using a shared mutable object as a default value causes state to accumulate across calls. Use {} as the default and create fresh arrays/objects inside the function using spread.
Key Insight: Never use mutable objects/arrays as default parameter values if you mutate them. The default is evaluated once and shared β use {} and create new objects inside.