I spent 2 hours debugging a form handler because I didn't know how to use variable keys properly in JavaScript objects.
The form field names came from an API, but I kept hard-coding object properties. Every time the API changed, my code broke.
What you'll learn: 5 different ways to use variables as object keys Time needed: 20 minutes Difficulty: Beginner-friendly with real examples
Here's the exact techniques that saved me from rewriting object code every time requirements changed.
Why I Needed This
My situation:
- Building dynamic forms where field names come from API responses
- User preferences stored with keys I don't know at compile time
- Shopping cart items with SKUs as property names
My setup:
- JavaScript ES6+ (works in all modern browsers)
- Real-world examples from e-commerce projects
- Tested in production for 2+ years
What didn't work:
- Hard-coding every possible key name (unmaintainable)
- String concatenation hacks (error-prone and ugly)
- Trying to modify object literals after creation (confusing)
Method 1: Bracket Notation (The Foundation)
The problem: You have a variable containing a key name, but dot notation won't work.
My solution: Use square brackets to access/create properties dynamically.
Time this saves: Eliminates need for switch statements or if/else chains.
Basic Bracket Notation
The simplest way to use a variable as an object key:
// Instead of this broken approach
const fieldName = 'email';
const user = {};
user.fieldName = 'john@example.com'; // Creates 'fieldName', not 'email'!
// Use brackets for variable keys
const fieldName = 'email';
const user = {};
user[fieldName] = 'john@example.com'; // Creates 'email' property ✅
console.log(user);
// Output: { email: 'john@example.com' }
What this does: The brackets tell JavaScript to evaluate the variable first, then use its value as the property name.
Expected output: An object with 'email' as the actual property name.
Personal tip: I use this pattern for every dynamic form handler. The brackets are your friend when the property name isn't known until runtime.
Real-World Example: Form Field Mapping
// API returns field configuration
const fieldConfig = {
firstName: { type: 'text', required: true },
email: { type: 'email', required: true },
phoneNumber: { type: 'tel', required: false }
};
// User submits form data
const formData = new FormData(document.getElementById('myForm'));
const userData = {};
// Map form fields to user object dynamically
for (const [fieldName, config] of Object.entries(fieldConfig)) {
if (formData.has(fieldName)) {
userData[fieldName] = formData.get(fieldName);
}
}
console.log(userData);
// Output: { firstName: 'John', email: 'john@example.com', phoneNumber: '555-0123' }
Personal tip: This approach scales perfectly. Add new fields to your API config, and the form handler automatically supports them without code changes.
Method 2: Computed Property Names (ES6 Magic)
The problem: You want to create objects with variable keys in object literals.
My solution: Use computed property names with square brackets inside object literals.
Time this saves: No need to create empty objects and add properties later.
Object Literal with Variable Keys
// The old way (still works, but verbose)
const keyName = 'productId';
const value = 'ABC123';
const oldWay = {};
oldWay[keyName] = value;
// ES6 computed property names (cleaner)
const keyName = 'productId';
const value = 'ABC123';
const newWay = {
[keyName]: value,
quantity: 2,
price: 29.99
};
console.log(newWay);
// Output: { productId: 'ABC123', quantity: 2, price: 29.99 }
What this does: The brackets inside the object literal evaluate the variable and use its value as the property name.
Expected output: A complete object created in one statement.
Dynamic Shopping Cart Example
// Building a shopping cart with dynamic SKU keys
const addToCart = (sku, quantity, price) => {
return {
[sku]: {
quantity: quantity,
price: price,
total: quantity * price
},
cartUpdated: new Date().toISOString()
};
};
// Usage with real product data
const cartItem = addToCart('LAPTOP-001', 1, 999.99);
console.log(cartItem);
// Output: {
// 'LAPTOP-001': { quantity: 1, price: 999.99, total: 999.99 },
// cartUpdated: '2025-09-04T10:30:00.000Z'
// }
Personal tip: I use this pattern for building API response objects where the key names come from database values or user input.
Method 3: Template Literals for Complex Keys
The problem: Your variable key needs formatting or combines multiple values.
My solution: Use template literals inside computed property names.
Time this saves: No string concatenation bugs or formatting errors.
Building Complex Object Keys
// Creating cache keys with multiple components
const buildCacheKey = (userId, action, timestamp) => {
const cacheData = {
[`user_${userId}_${action}_${timestamp}`]: {
data: 'expensive_computation_result',
expires: Date.now() + 3600000 // 1 hour
}
};
return cacheData;
};
// Usage
const cache = buildCacheKey(123, 'profile_fetch', Date.now());
console.log(Object.keys(cache)[0]);
// Output: "user_123_profile_fetch_1725448200000"
What this does: Template literals let you build formatted keys from multiple variables in a readable way.
Expected output: Objects with descriptive, formatted property names.
API Response Grouping
// Group API data by formatted keys
const groupOrdersByMonth = (orders) => {
return orders.reduce((grouped, order) => {
const orderDate = new Date(order.createdAt);
const monthKey = `${orderDate.getFullYear()}-${String(orderDate.getMonth() + 1).padStart(2, '0')}`;
return {
...grouped,
[monthKey]: [
...(grouped[monthKey] || []),
order
]
};
}, {});
};
// Sample data
const orders = [
{ id: 1, total: 99.99, createdAt: '2025-08-15T10:00:00Z' },
{ id: 2, total: 149.99, createdAt: '2025-08-20T14:30:00Z' },
{ id: 3, total: 79.99, createdAt: '2025-09-02T09:15:00Z' }
];
const groupedOrders = groupOrdersByMonth(orders);
console.log(groupedOrders);
// Output: {
// '2025-08': [{ id: 1, ...}, { id: 2, ...}],
// '2025-09': [{ id: 3, ...}]
// }
Personal tip: Template literals in computed properties are perfect for building cache keys, database indexes, or any formatted identifiers.
Method 4: Object.assign() for Multiple Variable Keys
The problem: You have multiple variables that need to become object keys.
My solution: Use Object.assign() to merge objects with computed properties.
Time this saves: No repetitive bracket notation assignments.
Merging Objects with Dynamic Keys
// Building user preferences from multiple sources
const buildUserPreferences = (theme, language, timezone, currency) => {
const preferences = Object.assign(
{},
{ [theme + 'Theme']: true },
{ [language + 'Language']: true },
{ [timezone + 'Timezone']: true },
{ [currency + 'Currency']: true },
{
lastUpdated: new Date().toISOString(),
version: '1.0'
}
);
return preferences;
};
// Usage
const userPrefs = buildUserPreferences('dark', 'english', 'EST', 'USD');
console.log(userPrefs);
// Output: {
// darkTheme: true,
// englishLanguage: true,
// ESTTimezone: true,
// USDCurrency: true,
// lastUpdated: '2025-09-04T10:30:00.000Z',
// version: '1.0'
// }
What this does: Object.assign() merges multiple objects, each with computed property names, into one final object.
Expected output: A single object with all your dynamic properties combined.
Configuration Builder
// Build configuration objects from environment variables
const buildConfig = () => {
const env = process.env.NODE_ENV || 'development';
const port = process.env.PORT || 3000;
const dbName = process.env.DB_NAME || 'myapp_dev';
return Object.assign(
{},
{ [`${env}Mode`]: true },
{ [`port${port}`]: 'active' },
{ [`database${dbName}`]: 'connected' },
{
// Static properties
startTime: new Date().toISOString(),
version: '2.1.0'
}
);
};
// Usage
const config = buildConfig();
console.log(config);
// Output: {
// developmentMode: true,
// port3000: 'active',
// databaseMyapp_dev: 'connected',
// startTime: '2025-09-04T10:30:00.000Z',
// version: '2.1.0'
// }
Personal tip: Object.assign() is my go-to when building configuration objects or combining user settings from multiple sources.
Method 5: Map Objects for Complex Key Operations
The problem: You need to perform operations on objects where the keys are variables.
My solution: Use Map objects for advanced key manipulation with full variable support.
Time this saves: No conversion between strings and other data types for keys.
Advanced Key Operations with Map
// Using non-string keys (objects, numbers, etc.)
const createAdvancedCache = () => {
const cache = new Map();
// Objects as keys
const userQuery = { userId: 123, includeProfile: true };
const productQuery = { category: 'electronics', minPrice: 100 };
// Store data with object keys
cache.set(userQuery, {
data: { name: 'John Doe', email: 'john@example.com' },
timestamp: Date.now()
});
cache.set(productQuery, {
data: [{ id: 1, name: 'Laptop' }, { id: 2, name: 'Phone' }],
timestamp: Date.now()
});
return cache;
};
// Usage
const cache = createAdvancedCache();
// Retrieve using object keys
const userQuery = { userId: 123, includeProfile: true };
const userData = cache.get(userQuery);
console.log(userData);
// Output: undefined (different object reference!)
// Better approach: Use JSON strings as keys
const betterCache = new Map();
const queryKey = JSON.stringify({ userId: 123, includeProfile: true });
betterCache.set(queryKey, { name: 'John Doe', email: 'john@example.com' });
const retrieved = betterCache.get(JSON.stringify({ userId: 123, includeProfile: true }));
console.log(retrieved);
// Output: { name: 'John Doe', email: 'john@example.com' }
What this does: Map objects allow any data type as keys, not just strings like regular objects.
Expected output: More flexible key-value storage for complex scenarios.
Dynamic Property Management
// Managing object properties dynamically
class DynamicObject {
constructor() {
this.properties = new Map();
}
// Set property with variable key
setProp(key, value) {
this.properties.set(key, value);
return this;
}
// Get property with variable key
getProp(key) {
return this.properties.get(key);
}
// Check if variable key exists
hasProp(key) {
return this.properties.has(key);
}
// Convert to regular object
toObject() {
const obj = {};
for (const [key, value] of this.properties) {
obj[key] = value;
}
return obj;
}
}
// Usage
const dynamicObj = new DynamicObject();
// Keys from variables
const fieldName = 'email';
const settingName = 'darkMode';
const apiKey = 'user_preferences_v2';
dynamicObj
.setProp(fieldName, 'john@example.com')
.setProp(settingName, true)
.setProp(apiKey, { theme: 'dark', notifications: true });
console.log(dynamicObj.toObject());
// Output: {
// email: 'john@example.com',
// darkMode: true,
// user_preferences_v2: { theme: 'dark', notifications: true }
// }
Personal tip: I use Maps when I need to store metadata about object keys or when the keys might be complex data types.
Common Mistakes I Made (So You Don't Have To)
Mistake 1: Forgetting Quotes in Bracket Notation
// Wrong - this looks for a variable named myKey
const obj = {};
obj[myKey] = 'value'; // ReferenceError: myKey is not defined
// Right - use quotes for literal strings
const obj = {};
obj['myKey'] = 'value'; // ✅
// Right - use variables without quotes
const keyName = 'myKey';
obj[keyName] = 'value'; // ✅
Mistake 2: Mixing Dot and Bracket Notation
// Wrong - creates 'keyName' property instead of using the variable
const keyName = 'email';
const user = {};
user.keyName = 'john@example.com'; // Creates { keyName: 'john@example.com' }
// Right - use brackets for variable keys
const keyName = 'email';
const user = {};
user[keyName] = 'john@example.com'; // Creates { email: 'john@example.com' } ✅
Mistake 3: Forgetting to Handle Undefined Variables
// Dangerous - undefined variable creates 'undefined' property
let dynamicKey; // undefined
const obj = {
[dynamicKey]: 'some value'
};
console.log(obj); // { undefined: 'some value' }
// Better - provide defaults
const dynamicKey = userInput || 'defaultKey';
const obj = {
[dynamicKey]: 'some value'
};
Personal tip: Always validate your variable keys before using them. I've debugged objects with 'undefined' and 'null' properties more times than I care to admit.
What You Just Built
You now know 5 different ways to use variables as object keys in JavaScript:
- Bracket notation for basic dynamic property access
- Computed property names for cleaner object literals
- Template literals for formatted, complex keys
- Object.assign() for merging multiple dynamic properties
- Map objects for advanced key operations
Key Takeaways (Save These)
- Always use brackets: Variable keys require square bracket notation, never dot notation
- Validate your keys: Check for undefined variables before using them as property names
- ES6 computed properties: Use
{ [variableKey]: value }for cleaner object creation - Template literals work: Perfect for building formatted keys like
cache_${userId}_${action} - Maps for complex keys: When you need non-string keys or advanced key operations
Your Next Steps
Pick one based on your experience:
- Beginner: Practice bracket notation with a simple form handler
- Intermediate: Build a dynamic settings object using computed property names
- Advanced: Create a caching system using Maps with complex keys
Tools I Actually Use
- VS Code: With JavaScript intellisense for catching key-related errors early
- Chrome DevTools: Console for testing dynamic object creation patterns
- ESLint: Catches common mistakes like undefined variables in bracket notation
- MDN Documentation: Object property accessors reference