JavaScript is full of hidden gems that can elevate your coding game. For instance, destructuring with aliasing lets you extract values from objects and rename them on-the-fly, making your code cleaner and more readable. Currying transforms a function into a series of functions that take one argument each, promoting reusability. Techniques like debouncing and throttling help control function execution frequency, improving performance for event-heavy applications. You can also efficiently cache expensive function call results using memoization. Other nifty tricks include optional chaining for safe property access, object cloning with the spread operator, and even using Sets to eliminate duplicate array values—making your JavaScript experience richer!
1. Destructuring with Aliasing for Better Variables

Destructuring allows you to unpack values from arrays or properties from objects into distinct variables. Aliasing enables you to rename the variables during this process, which is particularly useful when dealing with data from external sources like APIs.
Example:
javascript
const apiResponse = { first_name: 'John', user_age: 30 };
const { first_name: firstName, user_age: age } = apiResponse;
console.log(firstName); // John
console.log(age); // 30
Why Use It: Improves code readability and maintainability by allowing meaningful names for variables.
2. Currying for Flexible Functions

Currying is a technique in JavaScript that changes a function with multiple arguments into a sequence of functions, each taking a single argument. This method allows you to create more flexible and reusable functions. For instance, consider a function that applies a discount to a price. Using currying, you can create a function that first takes the discount percentage and then returns another function that takes the price. This way, you can easily create several discount functions with different rates without repeating code.
Example:
javascript
const applyDiscount = (discount) => (price) => price - (price * discount / 100);
const tenPercentOff = applyDiscount(10);
console.log(tenPercentOff(100)); // 90
In this example, applyDiscount takes a discount percentage and returns a new function that calculates the final price after applying the discount. This approach allows you to define specific discount functions like tenPercentOff, which you can use multiple times throughout your code. Currying promotes cleaner and more modular code, making your functions easier to manage and maintain.
3. Debouncing and Throttling for Performance

Debouncing and throttling are techniques used to control how often a function is executed, particularly in response to events like scrolling or resizing. Debouncing ensures that a function is only called after a certain period of inactivity. This is useful for scenarios like search input, where you want to wait for the user to stop typing before sending a query.
For example, consider a situation where a user types in a search box. Instead of sending a request on every keystroke, you can debounce the input to wait for a specified delay:
javascript
function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func.apply(this, args), delay);
};
}
Throttling, on the other hand, limits how often a function can be called over time. This is useful when you want to ensure that a function is executed at regular intervals, preventing it from being called too frequently. For example, you might want to throttle a scroll event handler:
javascript
function throttle(func, interval) {
let lastCall = 0;
return function(...args) {
const now = Date.now();
if (now - lastCall >= interval) {
lastCall = now;
func.apply(this, args);
}
};
}
Using these techniques can significantly enhance performance and user experience, especially in applications with heavy user interactions.
| Technique | Description | Example |
|---|---|---|
| Debouncing | Ensures a function is only called after a specified delay from the last event. | function debounce(func, delay) { let timeoutId; return function(…args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; } |
| Throttling | Limits the number of times a function can be called over time, allowing it to fire at regular intervals. | function throttle(func, interval) { let lastCall = 0; return function(…args) { const now = Date.now(); if (now – lastCall >= interval) { lastCall = now; func.apply(this, args); } }; } |
4. Memoization to Enhance Performance
Memoization is a powerful technique used to speed up expensive function calls by caching the results. When a function is called with the same arguments, it returns the cached result instead of recalculating it. This is especially useful for functions that are computationally intensive or frequently called with the same inputs.
For example, consider a function that calculates Fibonacci numbers. Without memoization, the function would repeatedly compute the same values, leading to poor performance.
Example:
javascript
const fibonacci = (n) => {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
};
This naive implementation has exponential time complexity. Now, let’s apply memoization to optimize it:
“`javascript
const memoize = (fn) => {
const cache = {};
return (…args) => {
const key = JSON.stringify(args);
if (!cache[key]) {
cache[key] = fn(…args);
}
return cache[key];
};
};
const memoizedFibonacci = memoize(fibonacci);
“`
With this memoized version, the function will only compute each Fibonacci number once, significantly improving performance, especially for larger inputs. Memoization is a simple yet effective way to optimize functions that involve repeated calculations.
- Caches results of expensive function calls
- Avoids redundant calculations
- Improves performance in recursive functions
- Increases efficiency for algorithms like Fibonacci
- Can be implemented with simple objects or Maps
- Useful in functional programming patterns
5. Optional Chaining for Safe Property Access

Optional chaining (?.) is a powerful feature in JavaScript that allows developers to safely access properties of an object without worrying about whether the object is null or undefined. This is particularly useful when dealing with deeply nested objects, where each level might not exist. By using optional chaining, you can avoid runtime errors that typically occur when trying to access a property of an undefined object.
For example, consider an object that represents a user with multiple nested properties:
javascript
const user = { profile: { name: 'Alice', address: { city: 'Wonderland' } } };
const cityName = user.profile?.address?.city; // 'Wonderland'
In this case, if any part of the chain (like profile or address) is missing, cityName will simply be undefined instead of throwing an error.
This feature streamlines your code and makes it cleaner by reducing the need for extensive null checks. Instead of writing:
javascript
const cityName = user && user.profile && user.profile.address ? user.profile.address.city : undefined;
You can simply use:
javascript
const cityName = user?.profile?.address?.city;
Overall, optional chaining enhances code readability and reduces the chances of bugs in your application.
6. Nullish Coalescing Operator for Default Values
The nullish coalescing operator (??) is a handy tool in JavaScript that allows you to provide a default value for variables that might be null or undefined. Unlike the logical OR operator (||), which treats falsy values like 0 or an empty string as trigger points for defaulting, the nullish coalescing operator only considers null and undefined. This makes it particularly useful for scenarios where 0 or an empty string are valid values.
Example:
javascript
const count = 0;
const defaultCount = count ?? 10; // 0
In this example, defaultCount will be 0 instead of 10, because while count is falsy, it is not null or undefined. This operator simplifies your code and prevents unexpected behavior when setting default values.
7. Spread Operator for Object Cloning

The spread operator (...) is a concise and elegant way to create a shallow copy of an object. By using this operator, you can clone an object without having to use methods like Object.assign() or looping through properties manually. This is particularly useful when you want to avoid modifying the original object accidentally.
Example:
javascript
const original = { a: 1, b: 2 };
const clone = { ...original };
console.log(clone); // { a: 1, b: 2 }
In this example, clone is a new object that contains the same properties as original. Changes made to clone will not affect original, preserving its state.
Why Use It: Using the spread operator for cloning helps maintain immutability in your code, which is a key principle in functional programming and can help reduce bugs caused by unintended side effects.
8. Using Sets for Unique Arrays

Sets in JavaScript are a powerful feature that can help you easily manage unique values in an array. When you create a Set, it automatically removes any duplicate entries. This makes it a great tool for filtering out duplicates from an array without needing to write complex logic.
For instance, if you have an array like const numbers = [1, 2, 2, 3, 4, 4, 5];, you can convert it into a Set and then back to an array to get only the unique values. The code would look like this:
javascript
const uniqueNumbers = [...new Set(numbers)];
console.log(uniqueNumbers); // [1, 2, 3, 4, 5]
This method is concise and leverages the built-in capabilities of JavaScript, enhancing both performance and readability. Using Sets not only simplifies the process of removing duplicates but also improves your code’s efficiency, especially when working with large datasets.
9. Self-Invoking Functions for Encapsulation
Self-invoking functions, also known as Immediately Invoked Function Expressions (IIFE), are a powerful feature in JavaScript. They are functions that execute automatically right after they are defined. This technique is particularly useful for encapsulating code, creating private variables, and avoiding variable hoisting issues.
By using an IIFE, you can create a private scope for your variables, preventing them from polluting the global namespace. This is especially helpful in larger applications where you want to avoid conflicts between different parts of your code.
Example:
javascript
(function() {
const privateVar = 'This is private';
console.log('Self-invoking function runs immediately');
})();
In this example, privateVar is not accessible outside the IIFE, keeping your code clean and organized. This approach is a great way to protect your variables and functions from being accessed or modified by other scripts.
10. Tagged Template Literals for Custom Processing
Tagged template literals provide a way to process template literals through a custom function. This allows you to manipulate the strings and their values in a more controlled manner. One common use case is sanitizing user input to prevent issues like cross-site scripting (XSS). By defining a tagged template literal, you can ensure that any potentially harmful characters are escaped before being rendered in the HTML.
For example, consider a function that sanitizes input:
javascript
function sanitize(strings, ...values) {
return strings.reduce((result, string, i) => {
let value = values[i - 1];
if (typeof value === 'string') {
value = value.replace(/&/g, '&').replace(/</g, '<');
}
return result + value + string;
});
}
You can use it like this:
javascript
const userInput = '<script>alert("xss")</script>';
const message = sanitize`User input: ${userInput}`;
console.log(message); // User input: <script>alert("xss")</script>
This approach makes your code cleaner and helps protect against common security vulnerabilities.
Generate Image for Every Section
Using JavaScript to dynamically generate images for different sections of your web application can enhance user experience and engagement. This can be achieved by manipulating the DOM or using libraries like Canvas or SVG. For instance, you can create an image element and set its source based on certain conditions or user interactions.
Example:
``javascriptimages/${section}.png
function generateImage(section) {
const img = document.createElement('img');
img.src =; // Assuming images are named after sections${section} image`;
img.alt =
document.body.appendChild(img);
}
generateImage(‘section1’);
``generateImage` is called with a section name, it creates an image element and appends it to the body. This method allows you to dynamically load images, making your web application more interactive.
In this example, when the function
Frequently Asked Questions
1. What are some hidden features of JavaScript that many people don’t know?
JavaScript has several hidden features like template literals, destructuring, and default parameters that can make coding easier.
2. How can I use JavaScript tricks to write more efficient code?
By using tricks like arrow functions and closures, you can write cleaner and more efficient code.
3. Are these JavaScript tricks applicable to all browsers?
Most JavaScript tricks work in all modern browsers, but some older browsers might not support the latest features.
4. Do these JavaScript tricks require advanced programming skills?
No, many of these tricks are simple enough for beginners to learn and use in their projects.
5. Can I find examples of these JavaScript tricks in action?
Yes, many coding websites and forums provide examples and explanations for these tricks.
TL;DR Discover 10 powerful JavaScript tricks to enhance your coding skills: 1) Use destructuring with aliasing for better variable names, 2) Implement currying for flexible function creation, 3) Improve performance with debouncing and throttling, 4) Utilize memoization to cache function results, 5) Employ optional chaining for safer property access, 6) Apply the nullish coalescing operator for setting default values, 7) Use the spread operator for easy object cloning, 8) Leverage sets to create unique arrays, 9) Take advantage of self-invoking functions for encapsulation, and 10) Explore tagged template literals for custom processing.


