eachEntries(obj, callback, selector) - Iterate Over Object Entries
Quick Start (30 seconds)
const user = {
name: 'Alice',
age: 30,
city: 'New York'
};
// Simple iteration
eachEntries(user, (key, value, index) => {
console.log(`${key}: ${value}`);
});
// Output:
// "name: Alice"
// "age: 30"
// "city: New York"
// Generate HTML
const html = eachEntries(user, (key, value) => {
return `<li><strong>${key}:</strong> ${value}</li>`;
});
console.log(html);
// "<li><strong>name:</strong> Alice</li><li><strong>age:</strong> 30</li>..."
// Render directly to DOM
eachEntries(user, (key, value) => {
return `<div class="field">${key}: ${value}</div>`;
}, '#user-details');
// Updates element with id="user-details" ✨What just happened? You iterated over an object's properties and optionally generated/rendered HTML!
What is eachEntries(obj, callback, selector)?
eachEntries() is a function that iterates over an object's key-value pairs and optionally generates HTML output.
Simply put: it's like forEach() for objects, with built-in HTML generation and DOM rendering capabilities.
Think of it as Object.entries() + forEach() + HTML builder all in one convenient function.
Syntax
eachEntries(obj, callback, selector)Parameters:
obj(Object) - The object to iterate overcallback(Function) - Called for each entry:(key, value, index) => anykey- Property namevalue- Property valueindex- Entry index (0, 1, 2, ...)- Return HTML string to accumulate, or nothing for side effects
selector(String, optional) - CSS selector to render output
Returns:
string- Accumulated HTML if callback returns stringsundefined- If callback doesn't return anything
Why Does This Exist?
The Problem: No Built-in Object forEach
JavaScript has no native forEach for objects:
const data = { a: 1, b: 2, c: 3 };
// Must convert to entries first
Object.entries(data).forEach(([key, value]) => {
console.log(key, value);
});
// To generate HTML, need manual accumulation
let html = '';
Object.entries(data).forEach(([key, value]) => {
html += `<div>${key}: ${value}</div>`;
});
// To render, need separate DOM manipulation
document.getElementById('output').innerHTML = html;
// Multi-step, verboseWhat's the Real Issue?
Need to iterate object
|
v
Convert to entries
|
v
Call forEach
|
v
Accumulate results
|
v
Render to DOM
|
v
Multi-step process ❌Problems: ❌ No direct object iteration - Must use Object.entries()
❌ Manual HTML accumulation - Need extra variable
❌ Separate DOM update - Extra step
❌ Verbose - Too much boilerplate
The Solution with eachEntries()
const data = { a: 1, b: 2, c: 3 };
// All in one call
eachEntries(data, (key, value) => {
return `<div>${key}: ${value}</div>`;
}, '#output');
// Object iteration ✅
// HTML generation ✅
// DOM rendering ✅What Just Happened?
Call eachEntries()
|
v
Iterate entries automatically
|
v
Collect HTML from callback
|
v
Render to selector (if provided)
|
v
One-step solution ✅Benefits: ✅ Direct object iteration - No conversion needed
✅ Auto HTML accumulation - Built-in
✅ Optional DOM rendering - Integrated
✅ Concise - One function call
Mental Model
Think of eachEntries() as a conveyor belt for object properties:
Object Properties Callback Process Output
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ name: Alice │───────→│ Generate │─────→│ <div>...</div>│
│ age: 30 │───────→│ HTML for │─────→│ <div>...</div>│
│ city: NY │───────→│ each entry │─────→│ <div>...</div>│
└──────────────┘ └──────────────┘ └──────────────┘
↓
Render to DOM
(if selector)Key Insight: Combines iteration, transformation, and rendering in one step.
How It Works
The complete flow:
eachEntries(obj, callback, selector)
|
▼
Object.entries(obj)
|
▼
For each [key, value] pair
|
▼
Call callback(key, value, index)
|
▼
Callback returns HTML? ──No──→ Skip
|
Yes
▼
Accumulate HTML string
|
▼
All entries processed
|
▼
Selector provided? ──No──→ Return HTML
|
Yes
▼
Find element by selector
|
▼
Set element.innerHTML
|
▼
Return HTML stringImplementation
function eachEntries(obj, callback, selector) {
let html = '';
let isReturningHTML = false;
// Iterate over entries
Object.entries(obj).forEach(([key, value], index) => {
const result = callback(key, value, index);
// Accumulate if callback returns string
if (result !== undefined) {
html += result;
isReturningHTML = true;
}
});
const output = isReturningHTML ? html : undefined;
// Render to DOM if selector provided
if (selector) {
const element = document.querySelector(selector);
if (element) {
element.innerHTML = output || '';
}
}
return output;
}Basic Usage
Example 1: Simple Iteration
const config = {
timeout: 5000,
retries: 3,
debug: true
};
// Just iterate (no return)
eachEntries(config, (key, value) => {
console.log(`Config.${key} = ${value}`);
});
// Output:
// "Config.timeout = 5000"
// "Config.retries = 3"
// "Config.debug = true"Example 2: Generate HTML
const product = {
name: 'Laptop',
price: 999,
stock: 15
};
const html = eachEntries(product, (key, value) => {
return `<div class="detail">${key}: ${value}</div>`;
});
console.log(html);
// "<div class="detail">name: Laptop</div><div class="detail">price: 999</div>..."Example 3: Render to DOM
const user = {
email: 'alice@example.com',
role: 'admin',
status: 'active'
};
// Render directly
eachEntries(user, (key, value) => {
return `
<div class="field">
<label>${key}:</label>
<span>${value}</span>
</div>
`;
}, '#user-info');
// Updates <div id="user-info"></div> with generated HTML ✨Example 4: With Index
const items = {
apple: 5,
banana: 3,
orange: 7
};
eachEntries(items, (key, value, index) => {
console.log(`${index + 1}. ${key}: ${value} units`);
});
// Output:
// "1. apple: 5 units"
// "2. banana: 3 units"
// "3. orange: 7 units"Real-World Examples
Example 1: Display User Profile
const profile = {
name: 'John Doe',
email: 'john@example.com',
phone: '+1-555-0123',
joined: '2024-01-15'
};
eachEntries(profile, (key, value) => {
const label = key.charAt(0).toUpperCase() + key.slice(1);
return `
<div class="profile-field">
<strong>${label}:</strong> ${value}
</div>
`;
}, '#profile-details');Example 2: Configuration Display
const appSettings = {
theme: 'dark',
language: 'en',
notifications: true,
autoSave: false
};
eachEntries(appSettings, (key, value) => {
const icon = value === true ? '✓' : value === false ? '✗' : '';
return `
<li>
<span class="setting-name">${key}</span>
<span class="setting-value">${icon || value}</span>
</li>
`;
}, '#settings-list');Example 3: Shopping Cart Summary
const cart = {
subtotal: 99.99,
tax: 8.00,
shipping: 5.00,
total: 112.99
};
eachEntries(cart, (key, value) => {
const label = key === 'total'
? '<strong>Total</strong>'
: key.charAt(0).toUpperCase() + key.slice(1);
const price = key === 'total'
? `<strong>$${value.toFixed(2)}</strong>`
: `$${value.toFixed(2)}`;
return `
<div class="cart-line">
<span>${label}:</span>
<span>${price}</span>
</div>
`;
}, '#cart-summary');Example 4: Form Errors Display
const errors = {
email: 'Invalid email format',
password: 'Password too short',
confirm: 'Passwords do not match'
};
if (Object.keys(errors).length > 0) {
eachEntries(errors, (field, message) => {
return `
<div class="error-message">
<span class="field-name">${field}:</span>
<span class="error-text">${message}</span>
</div>
`;
}, '#error-container');
}Example 5: Debug Object Display
const debugData = {
requestId: 'abc-123',
timestamp: Date.now(),
status: 200,
duration: 125
};
eachEntries(debugData, (key, value, index) => {
const bgColor = index % 2 === 0 ? '#f0f0f0' : '#ffffff';
return `
<tr style="background: ${bgColor}">
<td><code>${key}</code></td>
<td>${value}</td>
</tr>
`;
}, '#debug-table tbody');Example 6: Stats Dashboard
const stats = {
users: 1247,
posts: 3891,
comments: 12459,
likes: 45203
};
eachEntries(stats, (key, value) => {
const formatted = value.toLocaleString();
return `
<div class="stat-card">
<div class="stat-label">${key}</div>
<div class="stat-value">${formatted}</div>
</div>
`;
}, '#stats-grid');Example 7: API Response Display
const response = {
success: true,
code: 200,
message: 'Data fetched successfully',
timestamp: new Date().toISOString()
};
eachEntries(response, (key, value) => {
let displayValue = value;
if (typeof value === 'boolean') {
displayValue = value ? 'Yes' : 'No';
}
return `
<div class="response-field">
<span class="key">${key}:</span>
<span class="value">${displayValue}</span>
</div>
`;
}, '#api-response');Example 8: Build Table Rows
const inventory = {
'SKU-001': 45,
'SKU-002': 12,
'SKU-003': 0,
'SKU-004': 78
};
eachEntries(inventory, (sku, quantity) => {
const stockClass = quantity === 0 ? 'out-of-stock' :
quantity < 20 ? 'low-stock' : 'in-stock';
return `
<tr class="${stockClass}">
<td>${sku}</td>
<td>${quantity}</td>
<td>${quantity === 0 ? 'Out of Stock' : 'Available'}</td>
</tr>
`;
}, '#inventory-table tbody');Example 9: Environment Variables Display
const env = {
NODE_ENV: 'development',
API_URL: 'https://api.example.com',
DEBUG: 'true',
PORT: '3000'
};
eachEntries(env, (key, value) => {
return `
<div class="env-var">
<code class="var-name">${key}</code>
<code class="var-value">${value}</code>
</div>
`;
}, '#env-vars');Example 10: Validation Results
const validationResults = {
'Email format': 'Pass',
'Password strength': 'Fail',
'Terms accepted': 'Pass',
'Age verification': 'Pass'
};
eachEntries(validationResults, (check, result) => {
const icon = result === 'Pass' ? '✓' : '✗';
const className = result === 'Pass' ? 'pass' : 'fail';
return `
<div class="validation-item ${className}">
<span class="icon">${icon}</span>
<span class="check">${check}</span>
<span class="result">${result}</span>
</div>
`;
}, '#validation-results');Common Patterns
Pattern 1: Conditional HTML
eachEntries(data, (key, value) => {
// Only show non-null values
if (value === null || value === undefined) {
return; // Return nothing to skip
}
return `<div>${key}: ${value}</div>`;
});Pattern 2: Custom Formatting
const formatters = {
price: (v) => `$${v.toFixed(2)}`,
date: (v) => new Date(v).toLocaleDateString(),
boolean: (v) => v ? 'Yes' : 'No'
};
eachEntries(product, (key, value) => {
const formatter = formatters[key] || ((v) => v);
const formatted = formatter(value);
return `<div>${key}: ${formatted}</div>`;
});Pattern 3: Grouped Output
let categoryHTML = '';
eachEntries(items, (category, count) => {
categoryHTML += `
<div class="category">
<h3>${category}</h3>
<span class="count">${count} items</span>
</div>
`;
});
document.getElementById('categories').innerHTML = categoryHTML;Pattern 4: Side Effects Only
// No HTML generation - just side effects
eachEntries(config, (key, value) => {
localStorage.setItem(`config_${key}`, value);
// Don't return anything
});Important Notes
1. Callback Return Value Matters
// Returns HTML - accumulated
eachEntries(obj, (k, v) => {
return `<div>${k}</div>`; // ✅ Accumulated
});
// No return - side effects only
eachEntries(obj, (k, v) => {
console.log(k, v); // ✅ Just logs
});2. Selector is Optional
// Without selector - returns HTML
const html = eachEntries(obj, callback);
// With selector - updates DOM and returns HTML
eachEntries(obj, callback, '#output');3. Invalid Selector Warning
// If selector not found, warns but doesn't error
eachEntries(obj, callback, '#nonexistent');
// Console: "Element not found for selector '#nonexistent'"4. Non-Object Handling
// Returns empty string for non-objects
eachEntries(null, callback); // ''
eachEntries('string', callback); // ''
eachEntries(123, callback); // ''When to Use
Use eachEntries() For:
✅ Display object properties - User profiles, configs
✅ Generate HTML from objects - Lists, tables
✅ Iterate key-value pairs - Object.entries() alternative
✅ Direct DOM rendering - With selector parameter
✅ Side effects - Save to localStorage, log, etc.
Don't Use For:
❌ Arrays - Use regular forEach() or map()
❌ Complex transformations - Use mapEntries() instead
❌ Need array output - Use mapEntries()
Summary
What is eachEntries(obj, callback, selector)?
A function that iterates over object entries, optionally generating and rendering HTML.
Why use it?
- ✅ Direct object iteration
- ✅ Built-in HTML accumulation
- ✅ Optional DOM rendering
- ✅ Cleaner than Object.entries().forEach()
- ✅ Access to key, value, and index
Key Takeaway:
Object.entries().forEach() eachEntries()
| |
Multi-step One call
| |
Manual accumulation Auto-accumulation
| |
Separate rendering Integrated ✅One-Line Rule: Use eachEntries() to iterate objects and optionally generate/render HTML in one step.
Best Practices:
- Return HTML strings to accumulate
- Return nothing for side effects only
- Use selector for direct DOM updates
- Check for null/undefined values in callback
- Format values appropriately
Remember: eachEntries() combines iteration, HTML generation, and DOM rendering! 🎉