JavaScript is full of hidden gems that can make your code cleaner, faster, and more expressive Tech Blog. While beginners stick to the basics—loops, conditionals, and DOM manipulation—seasoned developers leverage advanced tricks to solve complex problems and write more maintainable code. In this article, I’ll share ten lesser‑known JavaScript techniques that have served me well over the years. Whether you’re working on front‑end frameworks or server‑side applications, these tips will help you level up your skill set.
1. Using Tagged Template Literals for Safe HTML
Tagged templates let you process template literals with a function before rendering. A common use is escaping user input to prevent XSS:
js
Copy
function escapeHTML(strings, …values) {
return strings.reduce((result, str, i) => {
const safeValue = values[i – 1]
.replace(/&/g, “&”)
.replace(/</g, “<“)
.replace(/>/g, “>”);
return result + safeValue + str;
});
}
const userInput = “alert(‘hi’)”;
const safeHTML = escapeHTML`
`;
console.log(safeHTML);
// ”
”
This ensures any dynamic content is properly escaped before being inserted into the page.
2. Deep Cloning with Structured Clone
Copying objects deeply—especially ones with nested arrays, maps, or typed arrays—can be tricky. Rather than writing custom recursion or relying on JSON (which fails on Dates, Maps, and functions), use the built‑in structuredClone:
js
Copy
const original = {
arr: [1, 2, 3],
date: new Date(),
map: new Map([[“key”, “value”]]),
};
const clone = structuredClone(original);
console.log(clone);
// Fully independent copy of original, including Map and Date
This native method handles almost any data type without manual work.
3. Optional Chaining with Default Values
Optional chaining (?.) prevents “cannot read property of undefined” errors, but when you need a fallback, combine it with the nullish coalescing operator (??):
js
Copy
const settings = {
theme: { color: “dark” },
};
const primary = settings.theme?.primaryColor ?? “#ffffff”;
console.log(primary);
// “#ffffff” because primaryColor doesn’t exist
This pattern keeps your code concise and safe.
4. Dynamic Imports for Conditional Loading
Instead of bundling every module upfront, dynamically load code only when needed:
js
Copy
async function loadChart() {
const { default: Chart } = await import(“chart.js”);
const ctx = document.getElementById(“myChart”);
new Chart(ctx, { /* config */ });
}
button.addEventListener(“click”, loadChart);
This reduces initial bundle size and speeds up page load times.
5. Function Currying with bind
Currying transforms a function with multiple arguments into a chain of functions that each take one argument. You can quickly curry with Function.prototype.bind:
js
Copy
function multiply(a, b) {
return a * b;
}
const double = multiply.bind(null, 2);
console.log(double(5)); // 10
This is a lightweight way to create specialized functions on the fly.
6. Proxy for Data Binding and Validation
The Proxy object can intercept property access or assignment. You can use it for reactive data binding or enforcing rules:
js
Copy
const user = new Proxy(
{ name: “Alice”, age: 25 },
{
set(target, prop, value) {
if (prop === “age” && typeof value !== “number”) {
throw new TypeError(“Age must be a number”);
}
target[prop] = value;
console.log(`Set ${prop} to ${value}`);
return true;
},
}
);
user.age = 26; // logs “Set age to 26”
user.age = “30”; // throws TypeError
Proxies unlock powerful metaprogramming possibilities.
7. Tail Recursion Optimization
Some JavaScript engines support tail call optimization, which lets recursive functions run without growing the call stack:
js
Copy
function factorial(n, acc = 1) {
if (n <= 1) return acc;
return factorial(n – 1, n * acc); // tail call
}
By returning the recursive call directly, you hint to the engine that it can reuse the same stack frame.
8. Bulk Operations with Array.from
Creating or transforming arrays can be more concise with Array.from:
js
Copy
// Generate [0, 1, 2, …, 9]
const nums = Array.from({ length: 10 }, (_, i) => i);
// Convert NodeList to array and map text content
const texts = Array.from(document.querySelectorAll(“p”), p => p.textContent);
This single method covers array creation, conversion, and mapping in one go.
9. Using Intl for Localization
Rather than rolling your own number and date formatting, rely on the Intl API:
js
Copy
const price = 12345.678;
console.log(new Intl.NumberFormat(“de-DE”, {
style: “currency”,
currency: “EUR”
}).format(price));
// “12.345,68 €”
console.log(new Intl.DateTimeFormat(“en-GB”).format(new Date()));
// “17/04/2025”
It handles thousands separators, currency symbols, and locale‑specific date styles automatically.
10. Wrapped Async Iteration with for await…of
When you have an async data source—such as streams or paginated API calls—you can loop over it cleanly:
js
Copy
async function* fetchPages(url) {
let next = url;
while (next) {
const response = await fetch(next);
const { data, nextPage } = await response.json();
yield data;
next = nextPage;
}
}
(async () => {
for await (const pageData of fetchPages(“/api/items?page=1”)) {
console.log(“Received page with”, pageData.length, “items”);
}
})();
This syntax makes handling asynchronous streams as natural as synchronous loops.
Wrapping Up
These ten tricks scratch the surface of what modern JavaScript can do. By mastering features like tagged templates, Proxy, dynamic imports, and the Intl API, you’ll write code that’s not only more powerful but also easier to maintain and scale. Whenever you hit a roadblock—whether it’s performance, safety, or code clarity—ask yourself: is there a lesser‑known feature or pattern that can simplify the solution? With each new project, you’ll uncover even more hidden gems that only experienced developers wield every day. Happy coding!