| Feature | Old Syntax | New Syntax (ES6+) |
|---|---|---|
| Variable Declaration | var name = 'John'; | const name = 'John'; |
| Arrow Function | function(x) { return x * 2; } | (x) => x * 2 |
| String Interpolation | name + ' is ' + age + ' years old' | `${name} is ${age} years old` |
| Destructuring | const name = obj.name; | const { name } = obj; |
| Rest Parameters | function(...args) {} | (...args) => {} |
| Default Parameters | function(x) { x = x || 10; } | const fn = (x = 10) => {} |
| Promise Chain | .then().then() | async/await |
| Object Shorthand | { name: name, age: age } | { name, age } |
| Spread Operator | [...arr1, ...arr2] | const arr = [...arr1, ...arr2] |
| Nullish Coalescing | x || 'default' | x ?? 'default' |
JavaScript ES6+ Cheat Sheet
Comprehensive reference guide for modern JavaScript (ES6 and beyond) including destructuring, async/await, functional programming, and professional development best practices.
Quick Reference
Most commonly used ES6+ features at a glance
Variable Declarations
const, let, and var with best practices
// ✓ BEST: Use const by default
const name = 'John';
const age = 30;
// ✓ GOOD: Use let when reassignment needed
let counter = 0;
counter++;
// ✗ AVOID: var has function scope issues
var oldVar = 'value'; // Don't use!
// Block scope demonstration
if (true) {
const blockScoped = 'only in block';
let alsoBlockScoped = 'also in block';
var functionScoped = 'leaks out'; // Bad!
}
// Const doesn't prevent mutation
const user = { name: 'John' };
user.name = 'Jane'; // ✓ Allowed
user = {}; // ✗ Error: reassignment not allowed
// const with arrays
const numbers = [1, 2, 3];
numbers.push(4); // ✓ Allowed
numbers = []; // ✗ Errorconst by default. Use let only when you need reassignment. Never use var in modern JavaScript.Arrow Functions
Modern function syntax
// Basic arrow function
const add = (a, b) => a + b;
add(2, 3); // 5
// Single parameter (parentheses optional)
const square = x => x * x;
square(4); // 16
// No parameters
const greeting = () => 'Hello';
// Multi-line body (need braces and return)
const calculate = (a, b) => {
const sum = a + b;
const product = a * b;
return sum + product;
};
// Implicit return of object
const createUser = (name, age) => ({ name, age });
// Array methods with arrows
const numbers = [1, 2, 3, 4, 5];
numbers.map(n => n * 2); // [2, 4, 6, 8, 10]
numbers.filter(n => n > 2); // [3, 4, 5]
// Lexical this binding
const person = {
name: 'John',
greet: function() {
const arrow = () => {
console.log(this.name); // 'John' ✓
};
arrow();
}
};this refers to the object, not the parent scope.Destructuring
Extract values from arrays and objects
// Basic destructuring
const user = { name: 'John', age: 30, city: 'NYC' };
const { name, age } = user;
// Rename variables
const { name: fullName, age: years } = user;
// Default values
const { name, role = 'user' } = user;
// role = 'user' if not in object
// Nested destructuring
const person = {
name: 'John',
address: { city: 'NYC', zip: '10001' }
};
const { name, address: { city, zip } } = person;
// Rest operator (remaining properties)
const { name, ...rest } = user;
// rest = { age: 30, city: 'NYC' }
// In function parameters
function displayUser({ name, age }) {
console.log(`${name} is ${age}`);
}
displayUser(user);
// Computed property names
const key = 'email';
const { [key]: userEmail } = { email: 'john@example.com' };// Basic array destructuring
const colors = ['red', 'green', 'blue'];
const [first, second] = colors;
// first = 'red', second = 'green'
// Skip elements
const [, , third] = colors;
// third = 'blue'
// Rest operator
const [primary, ...others] = colors;
// primary = 'red', others = ['green', 'blue']
// Default values
const [a, b, c, d = 'yellow'] = colors;
// d = 'yellow'
// Swapping variables
let x = 1, y = 2;
[x, y] = [y, x];
// x = 2, y = 1
// Destructuring in loops
const users = [
{ name: 'John', age: 30 },
{ name: 'Jane', age: 25 }
];
for (const { name, age } of users) {
console.log(`${name}: ${age}`);
}
// Nested array destructuring
const nested = [1, [2, 3], 4];
const [a, [b, c], d] = nested;
// a=1, b=2, c=3, d=4Template Literals & String Methods
Modern string handling
// Basic interpolation
const name = 'John';
const age = 30;
const greeting = `Hello, ${name}! You are ${age} years old.`;
// Expressions in templates
const result = `Total: ${10 + 20}`;
const formatted = `${name.toUpperCase()} is ${age > 25 ? 'adult' : 'young'}`;
// Multi-line strings
const html = `
<div>
<h1>${title}</h1>
<p>${description}</p>
</div>
`;
// Tagged template literals (advanced)
function highlight(strings, ...values) {
return strings.reduce((acc, str, i) =>
acc + str + (values[i] ? `<mark>${values[i]}</mark>` : ''), '');
}
const result = highlight`Hello ${name}, you have ${count} messages`;
// Returns: Hello <mark>John</mark>, you have <mark>5</mark> messages
// String methods
const text = ' Hello World ';
text.trim(); // 'Hello World'
text.toUpperCase(); // ' HELLO WORLD '
text.includes('World'); // true
text.startsWith(' '); // true
text.replace(/o/g, '0'); // ' Hell0 W0rld '
text.split(' '); // ['', '', 'Hello', 'World', '', '']
text.padStart(20, '*'); // '*** Hello World 'Spread & Rest Operators
... for spreading and collecting values
// Spread with arrays
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];
// [1, 2, 3, 4, 5, 6]
// Insert in middle
const result = [1, 2, ...arr1, 3];
// [1, 2, 1, 2, 3, 3]
// Copy arrays
const copy = [...arr1]; // Shallow copy
// Spread with objects
const user = { name: 'John', age: 30 };
const updated = { ...user, age: 31 };
// { name: 'John', age: 31 }
// Merge objects
const defaults = { theme: 'light' };
const config = { ...defaults, ...userSettings };
// Remove property while copying
const { age, ...rest } = user;
const newUser = { ...rest }; // Without age
// Spread in function calls
const numbers = [1, 2, 3];
Math.max(...numbers); // 3
// Spread strings
const chars = [...'hello'];
// ['h', 'e', 'l', 'l', 'o']Rest Parameters
Collect remaining arguments
// Rest parameters
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4, 5); // 15
// Mix regular and rest params
function greet(greeting, ...names) {
names.forEach(name =>
console.log(`${greeting}, ${name}!`));
}
greet('Hello', 'John', 'Jane', 'Bob');
// Rest must be last parameter
function process(first, second, ...rest) {
console.log(first, second, rest);
}
process(1, 2, 3, 4, 5);
// Output: 1 2 [3, 4, 5]
// In destructuring
const [first, ...rest] = [1, 2, 3, 4];
// first = 1, rest = [2, 3, 4]
const { name, ...others } = user;
// Collects all properties except name
// Rest in arrow functions
const multiply = (...nums) =>
nums.reduce((a, b) => a * b, 1);
multiply(2, 3, 4); // 24Default & Computed Parameters
Smart parameter handling
// Default parameters
function greet(name = 'Guest', greeting = 'Hello') {
console.log(`${greeting}, ${name}!`);
}
greet(); // Hello, Guest!
greet('John'); // Hello, John!
greet('Jane', 'Hi'); // Hi, Jane!
// Computed defaults
function createConfig(env = process.env.NODE_ENV || 'development') {
// ...
}
// Function as default
function withCallback(data, callback = (x) => console.log(x)) {
callback(data);
}
// Destructuring with defaults
function displayUser({
name = 'Anonymous',
age = 0,
role = 'user'
} = {}) {
console.log(`${name} (${age}) - ${role}`);
}
displayUser(); // Anonymous (0) - user
displayUser({ name: 'John', age: 30 });
// Default with conditional logic
const config = {
timeout: options?.timeout ?? 5000,
retries: options?.retries ?? 3,
debug: options?.debug ?? false
};
// Using nullish coalescing
const port = process.env.PORT ?? 3000;
const theme = userSettings?.theme ?? 'light';?? (nullish coalescing) for defaults instead of ||to avoid false positives with falsy values like 0 or empty string.Modern Operators
Optional chaining and nullish coalescing
// Optional chaining for properties
const user = { name: 'John', address: { city: 'NYC' } };
user?.name; // 'John'
user?.address?.city; // 'NYC'
user?.contact?.phone; // undefined (no error!)
// With arrays
const items = null;
items?.[0]; // undefined (no error)
// With functions
const callback = null;
callback?.(); // undefined (no error)
// In conditional checks
if (user?.profile?.verified) {
// Safe to proceed
}
// With method calls
const result = user?.getData?.();
// Combining with nullish coalescing
const city = user?.address?.city ?? 'Unknown';
// Short-circuit evaluation
const depth = obj?.level1?.level2?.level3 ?? 'default';
// In loops
users?.forEach(user => {
console.log(user.name);
});Nullish Coalescing (??)
Provide defaults for null/undefined
// Nullish coalescing
const port = process.env.PORT ?? 3000;
// 8080 (if set), 3000 (if not set)
// Difference from OR operator
const value1 = 0 || 10; // 10 (0 is falsy)
const value2 = 0 ?? 10; // 0 (0 is not nullish)
const name1 = '' || 'Anonymous'; // 'Anonymous'
const name2 = '' ?? 'Anonymous'; // '' (empty is not nullish)
// When to use ??
const config = {
timeout: userSettings?.timeout ?? 5000,
retries: userSettings?.retries ?? 3,
debug: userSettings?.debug ?? false
};
// Chaining nullish coalescing
const result = val1 ?? val2 ?? val3 ?? 'default';
// In destructuring
const { name = 'Guest' } = user; // Default value
const { name = user?.name ?? 'Anonymous' } = options;
// NOT with logical AND
const result = condition && (value ?? 'default');
// Safe API responses
const data = response?.data ?? {};
const items = response?.items ?? [];
const status = response?.status ?? 'unknown';Object Methods & Shorthand
Modern object creation and manipulation
// Property shorthand
const name = 'John';
const age = 30;
const email = 'john@example.com';
// Old way
const user1 = {
name: name,
age: age,
email: email
};
// Shorthand
const user2 = { name, age, email };
// Method shorthand
const obj = {
// Old way
oldMethod: function() {
return 'result';
},
// Shorthand
newMethod() {
return 'result';
},
// Arrow function (use sparingly)
arrowMethod: () => {
// Note: this won't refer to obj
}
};
// Computed property names
const propName = 'dynamicKey';
const dynamic = {
[propName]: 'value',
[Math.random()]: 'random',
[`key_${id}`]: 'computed'
};
// Getters and setters
const person = {
_age: 0,
get age() {
return this._age;
},
set age(value) {
if (value >= 0) this._age = value;
}
};
person.age = 25; // Calls setter// Object.keys() - get property names
const user = { name: 'John', age: 30 };
Object.keys(user); // ['name', 'age']
// Object.values() - get property values
Object.values(user); // ['John', 30]
// Object.entries() - get [key, value] pairs
Object.entries(user);
// [['name', 'John'], ['age', 30]]
// Iterate entries
for (const [key, value] of Object.entries(user)) {
console.log(`${key}: ${value}`);
}
// Object.assign() - merge objects
const defaults = { theme: 'light', lang: 'en' };
const config = Object.assign({}, defaults, userSettings);
// Or use spread: { ...defaults, ...userSettings }
// Object.freeze() - make immutable
const frozen = Object.freeze({ x: 1 });
frozen.x = 2; // Silent fail
// Object.seal() - prevent adding/removing
const sealed = Object.seal({ x: 1 });
sealed.y = 2; // Fails
sealed.x = 2; // OK
// Object.create() - set prototype
const parent = { greet() { return 'hi'; } };
const child = Object.create(parent);
// Object.defineProperty() - define properties
Object.defineProperty(obj, 'prop', {
value: 'test',
writable: false,
enumerable: true
});Array Methods
Functional array operations
// map() - transform elements
const numbers = [1, 2, 3, 4, 5];
numbers.map(n => n * 2);
// [2, 4, 6, 8, 10]
// filter() - select elements
numbers.filter(n => n > 2);
// [3, 4, 5]
// reduce() - accumulate value
numbers.reduce((sum, n) => sum + n, 0);
// 15
// Complex reduce - group by property
const users = [
{ role: 'admin', name: 'John' },
{ role: 'user', name: 'Jane' },
{ role: 'admin', name: 'Bob' }
];
const byRole = users.reduce((groups, user) => {
groups[user.role] = groups[user.role] || [];
groups[user.role].push(user.name);
return groups;
}, {});
// find() - get first match
users.find(u => u.role === 'admin');
// findIndex() - get index of match
users.findIndex(u => u.name === 'Jane');
// some() - check if any match
users.some(u => u.role === 'admin'); // true
// every() - check if all match
numbers.every(n => n > 0); // true
// includes() - simple existence check
numbers.includes(3); // true// flat() - flatten nested arrays
const nested = [1, [2, 3], [4, [5, 6]]];
nested.flat(); // [1, 2, 3, 4, [5, 6]]
nested.flat(2); // [1, 2, 3, 4, 5, 6]
// flatMap() - map then flatten
const sentences = ['hello world', 'foo bar'];
sentences.flatMap(s => s.split(' '));
// ['hello', 'world', 'foo', 'bar']
// sort() - sort array in place
const words = ['zebra', 'apple', 'banana'];
words.sort(); // ['apple', 'banana', 'zebra']
// Numeric sort (ascending)
numbers.sort((a, b) => a - b);
// Sort objects by property
users.sort((a, b) =>
a.name.localeCompare(b.name));
// reverse() - reverse order
numbers.reverse();
// join() - convert to string
numbers.join(', '); // '1, 2, 3, 4, 5'
// slice() - create copy/subset
numbers.slice(1, 3); // [2, 3]
// concat() - combine arrays
[1, 2].concat([3, 4]);
// or use spread: [...[1,2], ...[3,4]]
// indexOf() & lastIndexOf()
numbers.indexOf(3); // 2
numbers.lastIndexOf(3); // 2Promises
Handle asynchronous operations
// Create a promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Success!');
}, 1000);
});
// Handle promise
promise
.then(result => console.log(result))
.catch(error => console.error(error))
.finally(() => console.log('Complete'));
// Promise methods
Promise.all([p1, p2, p3])
.then(results => {
// All promises resolved
});
Promise.race([p1, p2])
.then(result => {
// First promise resolved
});
Promise.allSettled([p1, p2])
.then(results => {
// All settled (resolved or rejected)
});
// Promise.any() - first successful
Promise.any([p1, p2])
.then(result => {
// First successful promise
});
// Chaining promises
fetch('/api/user')
.then(res => res.json())
.then(data => {
console.log(data);
return fetch(`/api/posts/${data.id}`);
})
.then(res => res.json())
.then(posts => console.log(posts))
.catch(err => console.error(err));Async/Await
Cleaner promise handling
// Basic async function
async function fetchData() {
try {
const response = await fetch('/api/data');
const data = await response.json();
return data;
} catch (error) {
console.error('Error:', error);
throw error;
}
}
// Arrow function async
const getData = async () => {
const response = await fetch('/api/data');
return response.json();
};
// Multiple awaits
async function processUser(id) {
try {
const user = await getUser(id);
const posts = await getPosts(user.id);
const comments = await getComments(posts[0].id);
return { user, posts, comments };
} catch (error) {
console.error(error);
}
}
// Parallel execution (don't wait sequentially)
async function parallel() {
// Bad - sequential (slow)
const user = await getUser();
const posts = await getPosts();
// Good - parallel (fast)
const [user, posts] = await Promise.all([
getUser(),
getPosts()
]);
}
// Using in loops
async function processAll(items) {
for (const item of items) {
await processItem(item);
}
}
// Map with async
const results = await Promise.all(
items.map(item => processItem(item))
);Classes & OOP
Object-oriented programming with classes
// Basic class
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, I'm ${this.name}`);
}
// Getter
get isAdult() {
return this.age >= 18;
}
// Setter
set age(value) {
if (value >= 0) {
this._age = value;
}
}
// Static method
static compare(user1, user2) {
return user1.age - user2.age;
}
// Private field (with #)
#secret = 'private';
// Private method
#privateMethod() {
return this.#secret;
}
}
// Create instance
const user = new User('John', 30);
user.greet(); // Hello, I'm John
// Inheritance
class Admin extends User {
constructor(name, age, role) {
super(name, age);
this.role = role;
}
// Override method
greet() {
super.greet();
console.log(`I'm an ${this.role}`);
}
}
// Check instance
user instanceof User; // true
// Static method call
User.compare(user1, user2);Modules (Import/Export)
Code organization and reusability
// Default export
export default class Calculator {
add(a, b) { return a + b; }
}
// or
const config = { API_URL: '...' };
export default config;
// Named exports
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export class Utils {
static capitalize(str) {
return str[0].toUpperCase() + str.slice(1);
}
}
// Export all from module
export * from './utils';
// Export with alias
export { add as sum, subtract as minus };
// Mixed default + named
export default Database;
export { User, Post };// Default import
import Calculator from './calculator';
const calc = new Calculator();
// Named imports
import { add, subtract } from './math';
// Import everything
import * as math from './math';
math.add(1, 2);
// Mix default and named
import Database, { User, Post } from './db';
// Import with alias
import { add as sum } from './math';
sum(1, 2);
// Dynamic import (runtime)
const module = await import('./utils');
const result = module.doSomething();
// Conditional imports
if (isDevelopment) {
const debug = await import('./debug');
}
// Side-effect imports (run code)
import './styles.css';
import './setup'; // Runs setup.js codeDOM Manipulation
Work with the DOM efficiently
// Select elements
const element = document.getElementById('my-id');
const elements = document.querySelectorAll('.my-class');
const first = document.querySelector('.my-class');
// Iterate selections
elements.forEach(el => {
el.textContent = 'New text';
el.style.color = 'red';
});
// Modify attributes
element.setAttribute('data-id', '123');
element.getAttribute('data-id'); // '123'
element.removeAttribute('disabled');
// Class operations
element.classList.add('active');
element.classList.remove('disabled');
element.classList.toggle('hidden');
element.classList.contains('active'); // true
// Create elements
const div = document.createElement('div');
div.textContent = 'Hello';
div.className = 'container';
// Add to DOM
element.appendChild(div);
element.insertBefore(div, element.firstChild);
element.replaceChild(newEl, oldEl);
// Remove from DOM
element.remove();
element.parentElement?.removeChild(element);
// Get parent/siblings
const parent = element.parentElement;
const prev = element.previousElementSibling;
const next = element.nextElementSibling;// Add event listener
button.addEventListener('click', (event) => {
console.log('Clicked!');
});
// Multiple events
['click', 'touchend'].forEach(event => {
button.addEventListener(event, handleClick);
});
// Event delegation (efficient)
document.addEventListener('click', (event) => {
if (event.target.matches('.delete-btn')) {
deleteItem(event.target.dataset.id);
}
});
// Remove listener
button.removeEventListener('click', handler);
// Event object properties
button.addEventListener('click', (e) => {
e.preventDefault(); // Stop default
e.stopPropagation(); // Stop bubbling
e.target; // Element clicked
e.currentTarget; // Element with listener
e.type; // 'click'
e.key; // Key pressed (keyboard)
e.clientX; // Mouse position
});
// Common events
// - click, dblclick, mousedown, mouseup
// - focus, blur, input, change
// - keydown, keyup, keypress
// - submit, reset
// - load, unload, beforeunload
// - scroll, resize
// - dragstart, drop, dragoverModern Best Practices
Write professional, maintainable code
| Practice | Description | Example |
|---|---|---|
| Use const by default | Prevent accidental reassignment | const value = 10; |
| Prefer const over let | Signal immutability | const user = { name: 'John' }; |
| Use async/await | Cleaner than .then() chains | const data = await fetch(url).then(r => r.json()); |
| Destructure parameters | Make dependencies clear | function({ name, age }) {} |
| Use optional chaining | Safe property access | user?.address?.city |
| Use nullish coalescing | Better defaults | value ?? 'default' |
| Arrow functions | Concise syntax, lexical this | const sum = (a, b) => a + b; |
| Template literals | Readable string interpolation | `Hello, ${name}!` |
| Avoid callbacks | Use promises or async/await | await fetchData() |
| Error handling | Always use try/catch with async | try {} catch {} finally {} |
| Use Array methods | Functional programming | array.map().filter().reduce() |
| Pure functions | No side effects | const add = (a, b) => a + b; |
Code Style:
// ✓ Consistent formatting
const calculateTotal = (items) => {
return items.reduce((sum, item) =>
sum + item.price * item.quantity, 0);
};
// ✓ Clear variable names
const getUserByEmail = (email) => {
return users.find(u => u.email === email);
};
// ✓ Single responsibility
const validateEmail = (email) =>
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
// ✗ Avoid inline complexity
const x = a.filter(i=>i>0).map(i=>i*2);
// ✓ Extract to named function
const positive = (num) => num > 0;
const double = (num) => num * 2;
const result = a.filter(positive).map(double);Error Handling:
// ✓ Try-catch with async
async function fetchUser(id) {
try {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
return await res.json();
} catch (error) {
console.error('Failed to fetch user:', error);
throw error;
}
}
// ✓ Error handling in promises
fetchUser(1)
.then(user => processUser(user))
.catch(error => handleError(error))
.finally(() => cleanup());
// ✓ Graceful fallbacks
const data = await fetchData().catch(() =>
getDefaultData());Performance Tips
Optimize JavaScript execution
| Issue | Problem | Solution |
|---|---|---|
| Large loops | Slow DOM updates | Use batch updates, requestAnimationFrame |
| Memory leaks | Event listeners not removed | Always removeEventListener |
| Callback hell | Unreadable nested code | Use async/await or promises |
| Blocking operations | UI freezes | Use Web Workers for heavy computation |
| Bundle size | Large JavaScript files | Tree-shaking, code splitting, minification |
| Inefficient queries | Multiple DOM traversals | Cache selectors, use event delegation |
| Synchronous I/O | Blocks execution | Use async/await, promises |
| Memory allocation | Too many object creations | Reuse objects, object pooling |
| Regex in loops | Recompile every iteration | Move regex outside loop |
| Array searches | Linear search is slow | Use Set or Map for lookups |
Common Pitfalls & Solutions
Avoid these JavaScript gotchas
| Pitfall | Problem | Solution |
|---|---|---|
| Type coercion | '5' + 3 === '53' | Use strict equality (===), CONV/typeof checks |
| this binding | Arrow functions lose context | Use regular function for methods |
| Callback hell | Deep nesting in callbacks | Use async/await or promises |
| var hoisting | Unexpected global scope | Use const/let instead |
| Array mutation | .sort() modifies original | Use [...arr].sort() |
| Shallow copy | Spread doesn't deep copy | Use structuredClone() for deep copy |
| NaN comparison | NaN === NaN is false | Use Number.isNaN() instead |
| Promise then return | Forgot to return in .then() | Always return or await |
| Async loop | Awaiting in forEach | Use for...of loop instead |
| Race conditions | Multiple async updates | Use locks or Promise.all() |
Modern ES2024 Features
Latest JavaScript additions
// Array grouping (ES2024)
const items = [
{ category: 'A', value: 10 },
{ category: 'B', value: 20 },
{ category: 'A', value: 30 }
];
const grouped = Object.groupBy(items, item =>
item.category);
// { A: [...], B: [...] }
// findLast() and findLastIndex()
const lastEven = numbers.findLast(n =>
n % 2 === 0);
const lastIdx = numbers.findLastIndex(n =>
n % 2 === 0);
// Array.from with mapping
const range = Array.from({ length: 5 },
(_, i) => i + 1);
// [1, 2, 3, 4, 5]
// at() for array access
const last = arr.at(-1); // Last element
const first = arr.at(0); // First element
// Promise.withResolvers() (ES2024)
const { promise, resolve, reject } =
Promise.withResolvers();
// Cleaner promise creation// Using ?? and ?. together
const city = user?.address?.city ?? 'Unknown';
// Logical assignment operators
let timeout = 0;
timeout ||= 5000; // Assign if falsy
let data = null;
data ??= getDefaultData(); // Assign if nullish
let config = {};
config &&= mergeConfig(config); // Assign if truthy
// replaceAll() for strings
const safe = userInput.replaceAll('<', '<');
// structuredClone() for deep copy
const deepCopy = structuredClone(obj);
// Using Promise.allSettled()
const results = await Promise.allSettled([
fetch1(), fetch2(), fetch3()
]);
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log(result.value);
} else {
console.error(result.reason);
}
});
// WeakMap for private data
const privateData = new WeakMap();
privateData.set(obj, 'secret');Migration Checklist
Converting legacy code to modern JavaScript
Replace These Patterns:
✗ var name = 'John';
✓ const name = 'John';
✗ function(x) { return x * 2; }
✓ (x) => x * 2;
✗ 'Hello ' + name
✓ `Hello ${name}`;
✗ READ TABLE ... then use work area
✓ const item = items[ key ];
✗ .then().then().then()
✓ async/await
✗ if (!user) user = {};
✓ const user = userInput ?? {};
✗ setTimeout(cb, 1000)
✓ await new Promise(r =>
setTimeout(r, 1000));
✗ Regular functions as methods
✓ Arrow functions for callbacksKey Improvements:
- 30-40% less code with modern syntax
- Better readability and clarity
- Improved type safety with strict equality
- Safer property access with optional chaining
- Cleaner async code with async/await
- Functional programming patterns
- Built-in error handling
- Modern tooling support (linters, formatters)
Quick Debugging Tips
Troubleshoot JavaScript issues quickly
// Console methods
console.log('Message'); // Standard log
console.error('Error:'); // Error message
console.warn('Warning:'); // Warning message
console.table(data); // Tabular format
console.group('Section'); // Group logs
console.groupEnd();
// Conditional logging
console.assert(value > 0, 'Value must be positive');
// Performance timing
console.time('myTimer');
expensiveOperation();
console.timeEnd('myTimer');
// Debugger statement
debugger; // Pauses execution in DevTools
// Breakpoints in DevTools
// Click line number to set breakpoint
// Conditional breakpoint: right-click line number
// Inspect element
const element = document.querySelector('#my-id');
console.log(element);
console.dir(element); // All properties
// Stack trace
console.trace('Here');
// Debug async
async function debug() {
const result = await fetchData();
console.log('Result:', result);
}
// Logging with context
const logger = {
info: (msg) => console.log(`[INFO] ${msg}`),
error: (msg) => console.error(`[ERROR] ${msg}`),
warn: (msg) => console.warn(`[WARN] ${msg}`)
};