These are really useful, easy-to-read tips that take advantage of modern JavaScript features to solve common problems. So whether you’re cleaning up your code or just starting a new project, these tricks can help you write more elegant and maintainable code.
Here are 9 such handy tricks that you can start using today. Let’s see what they are!
Have you ever tried flattening a deeply nested array? Previously, it meant lots of complicated loops, temporary arrays, and way too much code. But now it’s done very neatly in one powerful line of code:
function flattenTheHardWay(arr) {
let result = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flattenTheHardWay(arr[i]));
} else {
result.push(arr[i]);
}
}
return result;
}
// Result: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const flattenArray = arr => arr.flat(Infinity);
const nestedArray = [1, [2, 3, [4, 5, [6, 7]]], 8, [9, 10]];
const cleanArray = flattenArray(nestedArray);
// Result: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
All the hard work is handled by flat(), and adding Infinity tells it to go down any level. Simple, clean, and it actually works.
Need a true deep copy of an object without using lodash? Here's a library-less solution that handles nested objects, arrays, and even dates:
function manualDeepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
if (obj instanceof Date) return new Date(obj);
const clone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (Object[.]prototype[.]hasOwnProperty[.]call(obj, key)) {
clone[key] = manualDeepClone(obj[key]);
}
}
return clone;
}
const deepClone = obj => JSON.parse(JSON.stringify(obj));
const complexObj = {
user: { name: 'Alex', date: new Date() },
scores: [1, 2, [3, 4]],
active: true
};
const cloned = deepClone(complexObj);
This command line has a few limitations - it won't handle functions, symbols, or circular references. But for 90% of use cases, it's pretty accurate.
Here's a neat little command line to take CSV data and output an array of manipulable objects, ideal for use in API responses or reading data:
function convertCSVTheHardWay(csv) {
const lines = csv.split('\n');
const headers = lines[0].split(',');
const result = [];
for (let i = 1; i < lines.length; i++) {
const obj = {};
const currentLine = lines[i].split(',');
for (let j = 0; j < headers.length; j++) {
obj[headers[j]] = currentLine[j];
}
result.push(obj);
}
return result;
}
const csvToObjects = csv => csv.split('\n').map(row => Object.fromEntries(row.split(',').map((value, i, arr) => [arr[0].split(',')[i], value])));
const csvData = `name,age,city
Peboy,30,New York
Peace,25,San Francisco
Lara,35,Chicago`;
const parsed = csvToObjects(csvData);
// Result: [
// { name: 'Peboy', age: '30', city: 'New York' },
// { name: 'Peace', age: '25', city: 'San Francisco' },
// { name: 'Lara', age: '35', city: 'Chicago' }
// ]
It's an efficient way to do data transformations with a command line, but add some error handling before putting it into production.
Here is a shorthand command to remove duplicate elements and sort your array at the same time, perfect for cleaning up a dataset:
function cleanArrayManually(arr) {
const unique = [];
for (let i = 0; i < arr.length; i++) {
if (unique.indexOf(arr[i]) === -1) {
unique.push(arr[i]);
}
}
return unique.sort((a, b) => a - b);
}
const uniqueSorted = arr => [...new Set(arr)].sort((a, b) => a - b);
const messyArray = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
const cleaned = uniqueSorted(messyArray);
// Result: [1, 2, 3, 4, 5, 6, 9]
const messyStrings = ['banana', 'apple', 'apple', 'cherry', 'banana'];
const cleanedStrings = [...new Set(messyStrings)].sort();
// Result: ['apple', 'banana', 'cherry']
The Set will take care of removing duplicates perfectly, and then the spread operator will turn it back into an array. And you just need to call sort() afterwards!
This is a powerful command line that allows you to query and transform multiple DOM elements at once:
function updateElementsManually(selector) {
const elements = document.querySelectorAll(selector);
for (let i = 0; i < elements.length; i++) {
const el = elements[i];
el.style.backgroundColor = '[#]007bff';
el.style.color = 'white';
el.style.padding = '10px 20px';
}
}
const modifyElements = selector => Array[.]from(document.querySelectorAll(selector)).forEach(el => el[.]style);
// Use it like this:
const updateButtons = modifyElements('.btn')
.map(style => Object.assign(style, {
backgroundColor: '[#]007bff',
color: 'white',
padding: '10px 20px'
}));
// Or even simpler for class updates:
const toggleAll = selector => document.querySelectorAll(selector).forEach(el => el.classList.toggle('active'));
This works in all modern browsers and saves you from writing repetitive DOM manipulation code.
Here's another neat line of code that makes parallel calls to the API and handles errors very cleanly.
async function fetchDataManually(urls) {
const results = [];
for (const url of urls) {
try {
const response = await fetch(url);
const data = await response.json();
results.push({ status: 'fulfilled', value: data });
} catch (error) {
results.push({ status: 'rejected', reason: error });
}
}
return results;
}
const parallelCalls = urls => Promise[.]allSettled(urls[.]map(url => fetch(url)[.]then(r => r[.]json())));
const urls = [
'https://api[.]example[.]com/users',
'https://api[.]example[.]com/posts',
'https://api[.]example[.]com/comments'
];
const getData = async () => {
const results = await parallelCalls(urls);
const [users, posts, comments] = results[.]map(r => r[.]status === 'fulfilled' ? r[.]value : null);
};
Promise.allSettled is the hero here; it doesn't fail if a request fails, and it returns explicit state information for each call.
Here's a great command line that converts dates into clean, readable strings without any external libraries:
function formatDateManually(date) {
const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const dayName = days[date.getDay()];
const monthName = months[date.getMonth()];
const day = date.getDate();
const year = date.getFullYear();
const hours = date.getHours();
const minutes = date.getMinutes();
const ampm = hours >= 12 ? 'PM' : 'AM';
return ${dayName}, ${monthName} ${day}, ${year} at ${hours % 12}:${minutes.toString().padStart(2, '0')} ${ampm};
}
const formatDate = date => new Intl.DateTimeFormat('en-US', { dateStyle: 'full', timeStyle: 'short' }).format(date);
const now = new Date();
console.log(formatDate(now));
// Output: "Thursday, December 9, 2024 at 2:30 PM"
const shortDate = date => new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' }).format(date);
// Output: "Dec 9, 2024"
Intl.DateTimeFormat handles all the heavy lifting, including localization. No more manually building date strings!
Here's a neat command line to create a debounce version of any function - perfect for handling search input or resizing windows:
function createDebounce(fn, delay) {
let timeoutId;
return function debounced(...args) {
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
fn.apply(this, args);
timeoutId = null;
}, delay);
};
}
const debounce=(fn,ms)=>{let timeout;return(...args)=>{clearTimeout(timeout);timeout=setTimeout(()=>fn(...args),ms);};};
const expensiveSearch=query=>console.log('Searching for:',query);
const debouncedSearch=debounce(expensiveSearch,300);
// Use it in your event listener:
searchInput.addEventListener('input',e=>debouncedSearch(e.target.value));
This command line covers all the basic debounce use cases and saves you from calling unnecessary functions, especially when inputs are generated continuously like typing or resizing.
Here's just another neat line of code to handle storing objects in localStorage with built-in validation and error handling:
function handleLocalStorage(key) {
return {
get: function() {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : null;
} catch (e) {
console.error('Error reading from localStorage', e);
return null;
}
},
set: function(data) {
try {
localStorage.setItem(key, JSON.stringify(data));
} catch (e) {
console.error('Error writing to localStorage', e);
}
},
remove: function() {
try {
localStorage.removeItem(key);
} catch (e) {
console.error('Error removing from localStorage', e);
}
}
};
}
const store = key => ({ get: () => JSON.parse(localStorage.getItem(key)), set: data => localStorage.setItem(key, JSON.stringify(data)), remove: () => localStorage.removeItem(key) });
const userStore = store('user');
// Save data
userStore.set({ id: 1, name: 'John', preferences: { theme: 'dark' } });
// Get data
const userData = userStore.get();
// Remove data
userStore.remove();
This wrapper gives you a clean API for localStorage operations and automatically handles all the JSON parsing/serialization.
These snippets aren’t just about writing less code – they’re about writing smarter code. Each one solves a common JavaScript challenge in a clean, maintainable way. While these snippets are powerful, remember that readability should always come first. If a single line of code makes your code harder to understand, split it into multiple lines.