07 - Modern JavaScript (ES6+)
Template Literals
Create strings with embedded expressions:
// Old way
const name = "Alice";
const age = 25;
const message = "Hello, " + name + "! You are " + age + " years old.";
// Template literals (ES6+)
const message = `Hello, ${name}! You are ${age} years old.`;
// Multi-line strings
const html = `
<div class="card">
<h2>${name}</h2>
<p>Age: ${age}</p>
</div>
`;
// Expressions inside ${}
const price = 19.99;
const tax = 0.08;
const total = `Total: $${(price * (1 + tax)).toFixed(2)}`;
console.log(total); // "Total: $21.59"Destructuring
Extract values from arrays and objects:
// Array destructuring
const colors = ["red", "green", "blue"];
const [first, second, third] = colors;
console.log(first); // "red"
// Object destructuring
const person = { name: "Alice", age: 25, city: "NYC" };
const { name, age } = person;
console.log(name); // "Alice"
// Rename during destructuring
const { name: personName, age: personAge } = person;
// Default values
const { name, country = "USA" } = person;
// Nested destructuring
const user = {
id: 1,
profile: {
name: "Alice",
email: "alice@example.com"
}
};
const { profile: { name, email } } = user;
console.log(name); // "Alice"
// Function parameters
function greet({ name, age }) {
console.log(`Hello ${name}, you are ${age}`);
}
greet(person); // "Hello Alice, you are 25"Spread Operator
Expand arrays and objects:
// Arrays
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
// Combine arrays
const combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4, 5, 6]
// Copy array
const copy = [...arr1];
// Add items
const extended = [0, ...arr1, 4];
console.log(extended); // [0, 1, 2, 3, 4]
// Objects
const person = { name: "Alice", age: 25 };
const address = { city: "NYC", country: "USA" };
// Merge objects
const full = { ...person, ...address };
console.log(full);
// { name: "Alice", age: 25, city: "NYC", country: "USA" }
// Override properties
const updated = { ...person, age: 26 };
console.log(updated); // { name: "Alice", age: 26 }
// Function arguments
const numbers = [1, 5, 3, 9, 2];
console.log(Math.max(...numbers)); // 9Rest Operator
Collect multiple elements into an array:
// Function parameters
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5)); // 15
// Mix with regular parameters
function introduce(greeting, ...names) {
console.log(`${greeting} ${names.join(", ")}`);
}
introduce("Hello", "Alice", "Bob", "Charlie");
// "Hello Alice, Bob, Charlie"
// Array destructuring
const numbers = [1, 2, 3, 4, 5];
const [first, second, ...rest] = numbers;
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
// Object destructuring
const person = { name: "Alice", age: 25, city: "NYC", country: "USA" };
const { name, ...details } = person;
console.log(name); // "Alice"
console.log(details); // { age: 25, city: "NYC", country: "USA" }Arrow Functions
Concise function syntax:
// Traditional function
function add(a, b) {
return a + b;
}
// Arrow function
const add = (a, b) => {
return a + b;
};
// Implicit return (no braces)
const add = (a, b) => a + b;
// Single parameter (no parentheses needed)
const double = n => n * 2;
// No parameters (parentheses required)
const greet = () => "Hello!";
// Returning object literal (wrap in parentheses)
const makePerson = (name, age) => ({ name, age });Default Parameters
// Old way
function greet(name) {
name = name || "Guest";
return `Hello, ${name}!`;
}
// Modern way
function greet(name = "Guest") {
return `Hello, ${name}!`;
}
console.log(greet()); // "Hello, Guest!"
console.log(greet("Alice")); // "Hello, Alice!"
// With expressions
function createArray(length = 10, fill = 0) {
return Array(length).fill(fill);
}
console.log(createArray()); // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
console.log(createArray(3, 5)); // [5, 5, 5]Enhanced Object Literals
const name = "Alice";
const age = 25;
// Old way
const person = {
name: name,
age: age,
greet: function() {
console.log("Hello");
}
};
// Modern way
const person = {
name,
age,
greet() {
console.log("Hello");
}
};
// Computed property names
const key = "favoriteColor";
const person = {
name: "Alice",
[key]: "blue"
};
console.log(person.favoriteColor); // "blue"Classes
Object-oriented programming in JavaScript:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, I'm ${this.name}`);
}
haveBirthday() {
this.age++;
console.log(`Happy birthday! Now ${this.age}`);
}
}
const alice = new Person("Alice", 25);
alice.greet(); // "Hello, I'm Alice"
alice.haveBirthday(); // "Happy birthday! Now 26"
// Inheritance
class Student extends Person {
constructor(name, age, major) {
super(name, age); // call parent constructor
this.major = major;
}
study() {
console.log(`${this.name} is studying ${this.major}`);
}
}
const bob = new Student("Bob", 20, "Computer Science");
bob.greet(); // "Hello, I'm Bob" (inherited)
bob.study(); // "Bob is studying Computer Science"
// Static methods
class MathUtils {
static add(a, b) {
return a + b;
}
static multiply(a, b) {
return a * b;
}
}
console.log(MathUtils.add(2, 3)); // 5
console.log(MathUtils.multiply(4, 5)); // 20
// Getters and setters
class Rectangle {
constructor(width, height) {
this.width = width;
this.height = height;
}
get area() {
return this.width * this.height;
}
set area(value) {
this.width = Math.sqrt(value);
this.height = Math.sqrt(value);
}
}
const rect = new Rectangle(10, 5);
console.log(rect.area); // 50
rect.area = 100;
console.log(rect.width); // 10Modules
Split code across files:
// math.js — export functions
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
export const PI = 3.14159;
// Default export
export default function multiply(a, b) {
return a * b;
}
// main.js — import functions
import multiply, { add, subtract, PI } from "./math.js";
console.log(add(2, 3)); // 5
console.log(multiply(2, 3)); // 6
console.log(PI); // 3.14159
// Import everything
import * as MathUtils from "./math.js";
console.log(MathUtils.add(2, 3)); // 5
console.log(MathUtils.default(2, 3)); // 6
// Rename imports
import { add as sum } from "./math.js";
console.log(sum(2, 3)); // 5Optional Chaining
Safely access nested properties:
const user = {
name: "Alice",
address: {
city: "NYC"
}
};
// Old way — manual checks
const country = user && user.address && user.address.country;
// Optional chaining
const country = user?.address?.country; // undefined (no error)
const city = user?.address?.city; // "NYC"
// With arrays
const users = [{ name: "Alice" }];
const secondUser = users?.[1]?.name; // undefined (no error)
// With functions
const result = user.someMethod?.(); // undefined if method doesn't existNullish Coalescing
Provide default values for null/undefined:
// Old way — ||
const value = someValue || "default";
// Problem: 0, "", false are all replaced
// Nullish coalescing — ??
const value = someValue ?? "default";
// Only replaces null and undefined
const count = 0;
console.log(count || 10); // 10 (0 is falsy)
console.log(count ?? 10); // 0 (0 is not null/undefined)
const name = "";
console.log(name || "Guest"); // "Guest" ("" is falsy)
console.log(name ?? "Guest"); // "" ("" is not null/undefined)Array Methods (ES6+)
const numbers = [1, 2, 3, 4, 5];
// find — first matching item
const found = numbers.find(n => n > 3);
console.log(found); // 4
// findIndex — index of first match
const index = numbers.findIndex(n => n > 3);
console.log(index); // 3
// includes — check if exists
console.log(numbers.includes(3)); // true
// flat — flatten nested arrays
const nested = [1, [2, 3], [4, [5, 6]]];
console.log(nested.flat()); // [1, 2, 3, 4, [5, 6]]
console.log(nested.flat(2)); // [1, 2, 3, 4, 5, 6]
// flatMap — map then flatten
const words = ["hello world", "foo bar"];
const letters = words.flatMap(word => word.split(" "));
console.log(letters); // ["hello", "world", "foo", "bar"]Key Takeaways
- Template literals (
`) make string interpolation easy - Destructuring extracts values from arrays and objects
- Spread (
...) expands, rest (...) collects - Arrow functions provide concise syntax
- Classes add object-oriented programming
- Modules split code across files with
import/export - Optional chaining (
?.) safely accesses nested properties - Nullish coalescing (
??) provides defaults for null/undefined only - Modern array methods make data manipulation easier