Topic 11: JavaScript Misc
📖 5 min read · 🎯 advanced · 🧭 Prerequisites: javascript-object, javascript-map-object
Why this matters
Up until now, you've been writing JavaScript that works — but modern JS gives you tools that make your code cleaner, shorter, and far easier to read. Things like template literals, destructuring, spread and rest operators, promises, and async/await aren't fancy extras — they're what every real project uses today. Once you see how much simpler these features make your code, you'll wonder how you managed without them. This lesson is where your JavaScript starts looking like the code you see in professional projects.
What You'll Learn
- Embed variables and multiline text cleanly using template literals
- Extract values from arrays and objects using destructuring syntax
- Expand and collect data with the spread and rest operators
- Model asynchronous work using Promises with
.then()and.catch() - Write cleaner async code using the
async/awaitsyntax over Promises - Fetch live API data and render it to the DOM in a complete practical example
The Analogy
Think of template literals as a mail-merge system: instead of cutting and taping snippets of paper to a letter ("Dear " + name + ", you owe " + amount), you write a template with named slots and let the system fill them in automatically — readable, clean, and hard to misformat. Destructuring is like unpacking a delivery box and immediately labeling each item as it comes out, rather than reaching back into the box every time you need something. And async/await is the difference between a waiter who stands frozen at the kitchen window until your steak is ready versus one who takes other orders and comes back the moment your plate is up.
Chapter 1: Template Literals
Template literals let you embed variables and expressions directly inside strings — no concatenation operators needed.
Basic Syntax
Wrap the string in backticks (`) instead of single or double quotes, and use ${} to interpolate any expression.
let name = "Alice";
let age = 25;
let message = `Hello, my name is ${name} and I am ${age} years old.`;
console.log(message); // Output: Hello, my name is Alice and I am 25 years old.
Multiline Strings
Backtick strings preserve actual newlines — no \n escape sequences required.
let multiline = `This is a string
that spans across
multiple lines.`;
console.log(multiline);
The output retains every line break exactly where you typed it, making long blocks of text or HTML fragments far easier to read and maintain.
Chapter 2: Destructuring
Destructuring is a concise syntax for pulling values out of arrays or properties out of objects and binding them to named variables in a single statement.
Array Destructuring
Position in the array determines which variable receives which value.
let colors = ["red", "green", "blue"];
let [firstColor, secondColor, thirdColor] = colors;
console.log(firstColor); // Output: red
console.log(secondColor); // Output: green
console.log(thirdColor); // Output: blue
Object Destructuring
Variable names must match the property keys (or you can alias them with :).
let person = {
name: "Alice",
age: 25,
city: "Vizag"
};
let { name, age, city } = person;
console.log(name); // Output: Alice
console.log(age); // Output: 25
console.log(city); // Output: Vizag
Both forms are common in function parameters — you'll see function render({ name, age }) throughout modern React and Vue code.
Chapter 3: Spread and Rest Operators
Both operators are written as ... but serve opposite purposes: spread expands an iterable outward; rest collapses multiple values inward.
Spread Operator
Use spread to merge arrays, copy objects, or pass array elements as individual function arguments.
let array1 = [1, 2, 3];
let array2 = [4, 5, 6];
let combinedArray = [...array1, ...array2];
console.log(combinedArray); // Output: [1, 2, 3, 4, 5, 6]
let person = { name: "Alice", age: 25 };
let extendedPerson = { ...person, city: "Vizag" };
console.log(extendedPerson); // Output: { name: "Alice", age: 25, city: "Vizag" }
Spreading an object creates a shallow copy — a critical point when working with state in React.
Rest Operator
Use rest in a function signature to capture any number of trailing arguments into a single array.
function sum(...numbers) {
return numbers.reduce((acc, curr) => acc + curr, 0);
}
console.log(sum(1, 2, 3, 4)); // Output: 10
numbers inside the function is a real array, so all array methods (map, filter, reduce) work on it.
Chapter 4: Promises
A Promise is an object that represents the eventual completion or failure of an asynchronous operation. It can be in one of three states: pending, fulfilled, or rejected.
Creating a Promise
let promise = new Promise((resolve, reject) => {
let isSuccessful = true;
if (isSuccessful) {
resolve("Operation was successful!");
} else {
reject("Operation failed!");
}
});
promise.then((message) => {
console.log(message);
}).catch((error) => {
console.log(error);
});
resolve(value)transitions the promise to fulfilled and passesvalueto.then().reject(reason)transitions it to rejected and passesreasonto.catch().- Chain multiple
.then()calls to sequence async steps; a single.catch()at the end handles any failure in the chain.
Chapter 5: Async/Await
async/await is syntactic sugar built on top of Promises. It lets you write asynchronous code that reads like synchronous code — no chained .then() callbacks needed.
Using Async/Await
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("Data fetched");
}, 2000);
});
}
async function getData() {
console.log("Fetching data...");
let data = await fetchData();
console.log(data); // Output: Data fetched
}
getData();
- Marking a function
asyncmakes it always return a Promise. awaitpauses execution of that function until the awaited Promise settles — but the rest of the JavaScript event loop keeps running.- Wrap
awaitcalls intry/catchto handle rejections cleanly.
Chapter 6: Putting It Together — Fetching Data from an API
The class combined every concept above into a working page that fetches a real post from the JSONPlaceholder API when a button is clicked.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>API Data Fetch Example</title>
</head>
<body>
<h1>API Data Fetch Example</h1>
<button id="fetchButton">Fetch Data</button>
<pre id="dataDisplay"></pre>
<script src="app.js"></script>
</body>
</html>
JavaScript — app.js
document.getElementById("fetchButton").addEventListener("click", async () => {
let dataDisplay = document.getElementById("dataDisplay");
dataDisplay.textContent = "Fetching data...";
try {
let response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
let data = await response.json();
dataDisplay.textContent = JSON.stringify(data, null, 2);
} catch (error) {
dataDisplay.textContent = "Error fetching data";
}
});
What's happening step by step:
- The click handler is declared
async— soawaitis legal inside it. fetch()returns a Promise;awaitpauses until the HTTP response arrives.response.json()is itself async — a secondawaitparses the body.JSON.stringify(data, null, 2)pretty-prints the result with 2-space indentation.- The
try/catchblock ensures any network error surfaces as a user-visible message rather than a silent failure.
sequenceDiagram
participant User
participant DOM
participant fetch
participant API as jsonplaceholder API
User->>DOM: clicks "Fetch Data"
DOM->>DOM: display "Fetching data..."
DOM->>fetch: await fetch(url)
fetch->>API: GET /posts/1
API-->>fetch: 200 OK { id, title, body, userId }
fetch-->>DOM: response object
DOM->>DOM: await response.json()
DOM->>DOM: display pretty-printed JSON
🧪 Try It Yourself
Task: Extend the example above to fetch all posts (/posts instead of /posts/1) and display only the title of each post as a bulleted list in the DOM.
Success criterion: Clicking the button should render a <ul> with one <li> per post title — 100 items from the API.
Starter snippet:
document.getElementById("fetchButton").addEventListener("click", async () => {
let dataDisplay = document.getElementById("dataDisplay");
dataDisplay.textContent = "Fetching...";
try {
let response = await fetch("https://jsonplaceholder.typicode.com/posts");
let posts = await response.json();
// TODO: build a <ul> where each <li> shows post.title
// Hint: use posts.map(...) and template literals
dataDisplay.textContent = ""; // clear the <pre>
// append your <ul> to dataDisplay or document.body
} catch (error) {
dataDisplay.textContent = "Error: " + error.message;
}
});
🔍 Checkpoint Quiz
Q1. What is the key syntactic difference between a template literal and a regular string, and what does ${} do inside one?
Q2. Given this code, what is logged to the console?
let coords = [40.7128, -74.0060];
let [lat, lng] = coords;
console.log(`Lat: ${lat}, Lng: ${lng}`);
A) Lat: undefined, Lng: undefined
B) Lat: 40.7128, Lng: -74.006
C) Lat: -74.006, Lng: 40.7128
D) A syntax error is thrown
Q3. What is the bug in the following code?
function getUser() {
return new Promise((resolve) => {
resolve({ name: "Alice", role: "admin" });
});
}
function showUser() {
let user = getUser();
console.log(user.name);
}
showUser();
A) getUser should use reject instead of resolve
B) showUser is missing async and await, so user is a Promise, not the resolved object
C) Object destructuring is required before accessing .name
D) console.log cannot print object properties
Q4. You need to merge two configuration objects without mutating either original. Which approach is correct?
A) let merged = config1 + config2;
B) let merged = Object.push(config1, config2);
C) let merged = { ...config1, ...config2 };
D) let merged = config1.concat(config2);
A1. Template literals use backtick characters (`) instead of quotes. ${} is an interpolation slot — the JavaScript expression inside the braces is evaluated and its result is coerced to a string and embedded at that position.
A2. B) Lat: 40.7128, Lng: -74.006 — array destructuring assigns values by position: lat gets index 0, lng gets index 1, then both are interpolated into the template literal.
A3. B) showUser is missing async and await — getUser() returns a Promise object; without await, user holds the Promise itself (not the resolved { name, role } object), so user.name is undefined.
A4. C) let merged = { ...config1, ...config2 }; — the object spread operator copies all enumerable own properties of both objects into a new object literal, leaving the originals untouched. Properties in config2 overwrite same-named properties from config1.
🪞 Recap
- Template literals use backticks and
${}to embed expressions in strings and support real multiline text natively. - Destructuring lets you unpack arrays by position and objects by key into named variables in one concise statement.
- The spread operator (
...) expands iterables and objects; the rest operator (...) collects variadic arguments into an array — same syntax, opposite directions. - A Promise models an async operation with three states (pending, fulfilled, rejected) and chains work through
.then()/.catch(). async/awaitis Promise-based code written to read synchronously; always usetry/catcharoundawaitto handle rejections gracefully.
📚 Further Reading
- MDN: Template literals — the source of truth on backtick strings and tagged templates
- MDN: Destructuring assignment — full coverage of array and object destructuring patterns
- MDN: Spread syntax — spread in function calls, array literals, and object literals
- MDN: Using Promises — chaining, error handling, and common pitfalls
- MDN: async function — async/await semantics and return behavior
- ⬅️ Previous: JavaScript Map Object
- ➡️ Next: None