โจintermediate
Modern JavaScript Syntax
ES6 and beyond introduced template literals, destructuring, spread/rest, optional chaining, and more. These features are now essential everyday JavaScript.
Template Literals
Backtick strings support multi-line and embedded expressions:
hljs javascript
const name = "Alice";
const age = 30;
// Before ES6:
const msg1 = "Hello, " + name + "! You are " + age + " years old.";
// Template literal:
const msg2 = `Hello, ${name}! You are ${age} years old.`;
// Multi-line (no \n needed)
const html = `
<div class="user">
<h2>${name}</h2>
<p>Age: ${age}</p>
</div>
`;
// Expressions inside ${}
console.log(`${2 + 2} is four`); // "4 is four"
console.log(`${age >= 18 ? "adult" : "minor"}`); // "adult"
console.log(`${name.toUpperCase()}`); // "ALICE"
Tagged templates:
hljs javascript
function highlight(strings, ...values) {
return strings.reduce((result, str, i) => {
return result + str + (values[i] !== undefined ? `<mark>${values[i]}</mark>` : "");
}, "");
}
const product = "laptop";
const price = 999;
const output = highlight`The ${product} costs $${price}`;
// "The <mark>laptop</mark> costs $<mark>999</mark>"
Destructuring
Array Destructuring
hljs javascript
const coords = [10, 20, 30];
const [x, y, z] = coords;
console.log(x, y, z); // 10 20 30
// Skip elements
const [first, , third] = [1, 2, 3];
console.log(first, third); // 1 3
// Default values
const [a = 0, b = 0, c = 0] = [1, 2];
console.log(a, b, c); // 1 2 0
// Swap variables
let p = 1, q = 2;
[p, q] = [q, p];
console.log(p, q); // 2 1
// Rest elements
const [head, ...tail] = [1, 2, 3, 4, 5];
console.log(head, tail); // 1 [2, 3, 4, 5]
Object Destructuring
hljs javascript
const user = { name: "Bob", age: 25, city: "NYC", role: "admin" };
// Basic
const { name, age } = user;
// Rename
const { name: userName, role: userRole } = user;
console.log(userName, userRole); // "Bob" "admin"
// Defaults
const { name: n, country = "USA" } = user;
console.log(n, country); // "Bob" "USA"
// Nested
const profile = {
user: { name: "Alice", address: { city: "London" } }
};
const { user: { name: personName, address: { city } } } = profile;
console.log(personName, city); // "Alice" "London"
// In function parameters
function display({ name, age, city = "Unknown" }) {
console.log(`${name}, ${age}, ${city}`);
}
display(user); // "Bob, 25, NYC"
Spread Operator (...)
hljs javascript
// Arrays
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const merged = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
const copy = [...arr1]; // shallow copy
const withExtra = [0, ...arr1, 4]; // [0, 1, 2, 3, 4]
// Objects
const defaults = { color: "blue", size: "md", border: true };
const custom = { ...defaults, color: "red", extra: "new" };
// { color: "red", size: "md", border: true, extra: "new" }
// Function arguments
function sum(a, b, c) { return a + b + c; }
const nums = [1, 2, 3];
console.log(sum(...nums)); // 6
// Clone and merge arrays/objects
const merged2 = { ...objA, ...objB }; // later keys win
Rest Parameters
hljs javascript
function sum(...nums) {
return nums.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
// Rest after named params
function log(level, ...messages) {
console.log(`[${level}]`, ...messages);
}
log("ERROR", "Something", "went", "wrong");
// [ERROR] Something went wrong
Short-hand Object Properties and Methods
hljs javascript
const x = 1, y = 2;
// Old
const point1 = { x: x, y: y };
// Shorthand
const point2 = { x, y };
// Method shorthand
const math = {
add(a, b) { return a + b; }, // shorthand
sub: function(a, b) { return a - b; }, // old way
};
Computed Property Names
hljs javascript
const prefix = "user";
const id = 42;
const obj = {
[`${prefix}_id`]: id,
[`get${prefix.charAt(0).toUpperCase() + prefix.slice(1)}`]: function() {
return this[`${prefix}_id`];
},
};
console.log(obj.user_id); // 42
console.log(obj.getUser()); // 42
Optional Chaining (?.)
hljs javascript
const user = {
profile: {
address: { city: "Paris" }
}
};
// Without optional chaining โ error-prone
const city1 = user && user.profile && user.profile.address && user.profile.address.city;
// With optional chaining โ clean
const city2 = user?.profile?.address?.city;
console.log(city2); // "Paris"
// On methods
const len = user?.getName?.()?.length;
// On arrays
const first = arr?.[0];
// Combined with nullish coalescing
const displayCity = user?.profile?.address?.city ?? "Unknown";
Nullish Coalescing (??)
hljs javascript
const config = { timeout: 0, retries: null, host: "" };
// || problem: 0 and "" are falsy
console.log(config.timeout || 5000); // 5000 โ wrong! 0 is valid
console.log(config.host || "localhost"); // "localhost" โ wrong!
// ?? only null/undefined
console.log(config.timeout ?? 5000); // 0 โ correct!
console.log(config.host ?? "localhost"); // "" โ correct!
console.log(config.retries ?? 3); // 3 โ correct!
for...of and Iterables
hljs javascript
// Works on any iterable: arrays, strings, Maps, Sets
for (const char of "hello") {
console.log(char); // h, e, l, l, o
}
const map = new Map([["a", 1], ["b", 2]]);
for (const [key, val] of map) {
console.log(key, val);
}
const set = new Set([1, 2, 3, 2, 1]); // auto-deduplicates
for (const val of set) {
console.log(val); // 1, 2, 3
}
Symbols
Symbols are unique, primitive values โ useful as non-colliding property keys:
hljs javascript
const id = Symbol("id");
const id2 = Symbol("id");
console.log(id === id2); // false โ always unique
const user = {
[id]: 12345, // won't collide with other "id" properties
name: "Alice",
};
console.log(user[id]); // 12345
โถTry it yourself
Key Takeaways
- Template literals make string interpolation and multi-line strings easy
- Destructuring unpacks arrays and objects into variables cleanly
- Spread (
...) copies/merges arrays and objects; rest (...) collects remaining items - Optional chaining (
?.) safely navigates nested properties - Nullish coalescing (
??) provides fallbacks fornull/undefinedonly (not all falsy values)
Ready to test your knowledge?
Take a quiz on what you just learned.