Welcome to the world of advanced JavaScript! Whether you're a seasoned developer looking to sharpen your skills or an enthusiast eager to dive deeper into the intricacies of JavaScript, this blog is designed to inspire and educate. Let's explore 20 advanced JavaScript tricks that will not only enhance your coding prowess but also bring a smile to your face as you discover new and exciting ways to optimize your code.
1. Destructuring Assignment
Destructuring assignment is a powerful feature that allows you to unpack values from arrays or properties from objects into distinct variables. This can make your code more readable and concise.
const [first, second] = [10, 20];
const { name, age } = { name: 'Alice', age: 30 };
2. Default Parameters
Default parameters allow you to set default values for function arguments, making your functions more flexible and easier to use.
function greet(name = 'Guest') {
console.log(`Hello, ${name}!`);
}
greet(); // Output: Hello, Guest!
3. Template Literals
Template literals provide a way to embed expressions within strings, making string interpolation a breeze.
const name = 'Bob';
console.log(`Hello, ${name}!`);
4. Arrow Functions
Arrow functions offer a concise syntax for writing function expressions and automatically bind the this
value to the surrounding context.
const add = (a, b) => a + b;
5. Spread and Rest Operators
The spread operator (...
) allows you to expand an iterable (like an array) into individual elements, while the rest operator collects multiple elements into an array.
const numbers = [1, 2, 3];
const newNumbers = [...numbers, 4, 5];
function sum(...args) {
return args.reduce((acc, val) => acc + val, 0);
}
6. Promises and Async/Await
Promises and the async/await
syntax make asynchronous code easier to write and understand.
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
7. Optional Chaining
Optional chaining (?.
) allows you to safely access deeply nested properties without having to explicitly check each level.
const user = { name: 'Alice', address: { city: 'Wonderland' } };
const city = user?.address?.city;
8. Nullish Coalescing
The nullish coalescing operator (??
) provides a default value when dealing with null
or undefined
.
const value = null ?? 'default';
console.log(value); // Output: default
9. Dynamic Imports
Dynamic imports allow you to load modules on demand, improving performance by splitting your code.
import('./module.js').then(module => {
module.doSomething();
});
10. Proxy Objects
Proxies enable you to create objects with custom behavior for fundamental operations (e.g., property lookup, assignment).
const handler = {
get: (obj, prop) => {
if (prop in obj) {
return obj[prop];
} else {
return 'Property not found';
}
}
};
const proxy = new Proxy({ name: 'Alice' }, handler);
console.log(proxy.name); // Output: Alice
console.log(proxy.age); // Output: Property not found
11. Memoization
Memoization is a technique to optimize expensive function calls by caching their results.
function memoize(fn) {
const cache = {};
return function (...args) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
} else {
const result = fn(...args);
cache[key] = result;
return result;
}
};
}
12. Currying
Currying is a functional programming technique where a function with multiple arguments is transformed into a sequence of unary functions.
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function (...args2) {
return curried.apply(this, args.concat(args2));
};
}
};
}
13. Higher-Order Functions
Higher-order functions are functions that take other functions as arguments or return them as results.
function higherOrder(fn) {
return function (...args) {
console.log('Before function call');
const result = fn(...args);
console.log('After function call');
return result;
};
}
14. Event Delegation
Event delegation is a technique to handle events efficiently by adding a single event listener to a parent element.
document.querySelector('#parent').addEventListener('click', function (event) {
if (event.target.tagName === 'BUTTON') {
console.log('Button clicked:', event.target.textContent);
}
});
15. Debouncing and Throttling
Debouncing and throttling are techniques to control the rate at which a function is invoked, useful for optimizing performance in scenarios like scroll events or input changes.
function debounce(fn, delay) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => fn(...args), delay);
};
}
function throttle(fn, limit) {
let inThrottle;
return function (...args) {
if (!inThrottle) {
fn(...args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
}
16. Custom Hooks in React
Custom hooks in React allow you to encapsulate and reuse stateful logic across components.
function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = React.useState(() => {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
});
const setValue = value => {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
};
return [storedValue, setValue];
}
17. Web Workers
Web Workers enable you to run scripts in background threads, keeping the user interface responsive.
const worker = new Worker('worker.js');
worker.postMessage('Hello, Worker!');
worker.onmessage = function (event) {
console.log('Message from worker:', event.data);
};
18. Service Workers
Service Workers act as network proxies, allowing you to create effective offline experiences and improve performance.
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js').then(function (registration) {
console.log('Service Worker registered with scope:', registration.scope);
});
}
19. Intersection Observer API
The Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or the top-level document's viewport.
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log('Element is in view:', entry.target);
}
});
});
observer.observe(document.querySelector('#target'));
20. Custom Elements and Shadow DOM
Custom elements and the Shadow DOM allow you to create reusable components with encapsulated styles and behavior.
class MyElement extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `<style>:host { color: blue; }</style><p>Hello, World!</p>`;
}
}
customElements.define('my-element', MyElement);
Conclusion
Exploring these advanced JavaScript tricks can significantly enhance your development skills and make your coding journey more enjoyable. Whether you're optimizing performance, improving code readability, or creating more dynamic user experiences, these techniques offer a wealth of possibilities. Happy coding, and may your JavaScript adventures be filled with discovery and delight! ππ»
Follow me on GitHub:
If you found this blog helpful and want to stay updated with more advanced JavaScript tips and tricks, feel free to follow me on GitHub:
If you enjoy my content and find it helpful, you can support my work by buying me a coffee! Your support helps me keep sharing valuable knowledge. ββ€οΈ buymeacoffee.com/sovannaro
Top comments (10)
Not quite sure about how "advance-level" those tricks are actually - but nevertheless, it's a good list and I really like the simple and clean examples . Those are really to the point without any unnecessary overload!
Good post but I have three points.
1, #16 is very specific to the Reach JS framework and not a general JS feature, so has limited use.
2, #11 Memorisation can be simplified to:
Further, the
if
condition could be reduced to the following one-liner, but the code is more difficult to read.However, it should be mentioned there are limitations with using
JSON.stringify
to encode the arguments as not all data types can be encoded (BigInt) and there are illegal conditions (circular references.)3, #20 Custom Elements and Shadow DOM are two of the trio of technologies that comprise Web Components, the third being HTML Templates.
This is an amazing collection of advanced JavaScript tricks. I love how each technique is explained clearly with examples. Features like destructuring, async/await, and the Intersection Observer API are game-changers for writing clean and efficient code. Also, the event delegation and debouncing/throttling tips are super useful for performance optimization. Thanks for sharing these insights, definitely bookmarking this.
A couple of these advanced JavaScript tricks appear more like pointless hacks than best practices, but several are unquestionably helpful. In fact, would experienced developers use this in production code? Additionally, if a company wants to do more than merely use JavaScript, it might be wiser to invest in custom software development services in the long run.
Helped !
I think, you've accidentally concluded twice.
As others have said, the list starts off pretty beginner-level for something touted as "Advanced JavaScript Tricks for Experienced Developers", but some of the later entries live up to the hype.
Some could use a bit more discussion regarding pros and cons, though. For example, use of Shadow DOM can be a bit controversial because, IIUC, Shadow DOM elements can't be styled with client-side CSS. That may sound like a good thing (web devs maintain full control over their site's presentation), but it defeats the open web's promise of accessibility and customization.
There are plenty of good reasons for end-users to apply custom style rules to online content, and few situations where it's justifiable to include elements which are immune to downstream customization.
Hello this is X.com/BLACKROCKMEMEZ and this MEME TRADING AI AGENT WILL ENTER THE VC CAPITAL GAINS GAME
Some comments may only be visible to logged-in visitors. Sign in to view all comments.