javascript
exercises
exercises.js⚡javascript
/**
* ============================================
* 3.4 Assignment Operators - Exercises
* ============================================
*
* Practice assignment operations in JavaScript.
* Solutions are at the bottom.
*/
// ============================================
// EXERCISE 1: Compound Assignment
// ============================================
// Calculate final values without running code:
let a = 10;
a += 5; // a = _____
a *= 2; // a = _____
a -= 10; // a = _____
a /= 4; // a = _____
a %= 3; // a = _____
// ============================================
// EXERCISE 2: String Building
// ============================================
// Use += to build this string: "Hello, World! How are you?"
let greeting = '';
// YOUR CODE (use multiple += operations):
// ============================================
// EXERCISE 3: Logical Assignment Predictions
// ============================================
// Predict the final values:
let b1 = 5;
b1 &&= 10; // b1 = _____
let b2 = 0;
b2 &&= 10; // b2 = _____
let b3 = '';
b3 ||= 'default'; // b3 = _____
let b4 = 'hello';
b4 ||= 'default'; // b4 = _____
let b5 = null;
b5 ??= 'fallback'; // b5 = _____
let b6 = 0;
b6 ??= 100; // b6 = _____
// ============================================
// EXERCISE 4: Array Destructuring
// ============================================
// Extract values from this array:
const colors = ['red', 'green', 'blue', 'yellow', 'purple'];
// Extract first color into 'primary'
// Extract second and third into 'secondary1' and 'secondary2'
// Extract remaining into 'others'
// YOUR CODE:
// ============================================
// EXERCISE 5: Object Destructuring
// ============================================
// Extract from this object:
const person = {
name: 'Alice',
age: 28,
address: {
city: 'Boston',
zip: '02101',
},
hobbies: ['reading', 'hiking'],
};
// Extract name (rename to personName)
// Extract age with default of 0
// Extract city from nested address
// Extract hobbies
// YOUR CODE:
// ============================================
// EXERCISE 6: Swap Variables
// ============================================
// Swap the values of x and y using destructuring (no temp variable)
let x = 100;
let y = 200;
// YOUR CODE:
// After: x should be 200, y should be 100
// ============================================
// EXERCISE 7: Function with Destructured Parameters
// ============================================
// Create a function that accepts config object with defaults
function createServer(/* YOUR PARAMETERS */) {
// Default port: 3000
// Default host: "localhost"
// Default secure: false
// Return formatted string: "http://localhost:3000" or "https://..."
// YOUR CODE:
}
// Tests:
// createServer({}) → "http://localhost:3000"
// createServer({ port: 8080 }) → "http://localhost:8080"
// createServer({ host: "example.com", secure: true }) → "https://example.com:3000"
// ============================================
// EXERCISE 8: Counter Class
// ============================================
// Create a counter using compound assignment
function createCounter(initial = 0) {
// Return object with:
// - value: current count
// - increment(n = 1): add n to count
// - decrement(n = 1): subtract n from count
// - reset(): reset to initial value
// - double(): multiply count by 2
// YOUR CODE:
}
// Tests:
// const c = createCounter(10);
// c.increment(); // value: 11
// c.increment(5); // value: 16
// c.double(); // value: 32
// c.decrement(2); // value: 30
// c.reset(); // value: 10
// ============================================
// EXERCISE 9: Config Merger
// ============================================
// Create a function that merges configs using ??=
function mergeWithDefaults(config) {
// Defaults:
// - timeout: 5000
// - retries: 3
// - debug: false
// - maxConnections: 10
// Use ??= to set defaults without overwriting valid falsy values
// YOUR CODE:
}
// Tests:
// mergeWithDefaults({})
// → { timeout: 5000, retries: 3, debug: false, maxConnections: 10 }
// mergeWithDefaults({ timeout: 1000, retries: 0 })
// → { timeout: 1000, retries: 0, debug: false, maxConnections: 10 }
// mergeWithDefaults({ debug: true })
// → { timeout: 5000, retries: 3, debug: true, maxConnections: 10 }
// ============================================
// EXERCISE 10: Multiple Return Values
// ============================================
// Create a function that returns statistics about an array
// Use destructuring to extract the results
function getStats(numbers) {
// Return object with: min, max, sum, average, count
// YOUR CODE:
}
// Usage:
// const { min, max, average } = getStats([1, 2, 3, 4, 5]);
// ============================================
// EXERCISE 11: Deep Destructuring
// ============================================
// Extract deeply nested values
const data = {
users: [
{ id: 1, profile: { name: 'Alice', email: 'alice@test.com' } },
{ id: 2, profile: { name: 'Bob', email: 'bob@test.com' } },
],
metadata: {
total: 2,
page: 1,
},
};
// Extract:
// - First user's name (as 'firstUserName')
// - Second user's email (as 'secondUserEmail')
// - Total count (as 'totalUsers')
// YOUR CODE:
// ============================================
// EXERCISE 12: Chained Updates
// ============================================
// Rewrite using compound assignment operators
let value = 100;
// Rewrite these using compound operators:
// value = value + 50;
// value = value * 2;
// value = value - 100;
// value = value / 5;
// value = value % 30;
// YOUR CODE:
// ============================================
// EXERCISE 13: Safe Property Update
// ============================================
// Create a function that safely updates nested object properties
function safeUpdate(obj, path, value) {
// path is a string like "user.address.city"
// Create intermediate objects if they don't exist
// Set the final value
// YOUR CODE:
}
// Tests:
// let obj = {};
// safeUpdate(obj, "user.address.city", "NYC");
// // obj = { user: { address: { city: "NYC" } } }
// ============================================
// EXERCISE 14: Accumulator Patterns
// ============================================
// Use compound assignment to calculate:
const transactions = [
{ type: 'credit', amount: 100 },
{ type: 'debit', amount: 50 },
{ type: 'credit', amount: 200 },
{ type: 'debit', amount: 75 },
];
// Calculate:
// - totalCredits
// - totalDebits
// - balance (credits - debits)
// YOUR CODE:
// ============================================
// EXERCISE 15: Rest and Spread Assignment
// ============================================
// Use destructuring with rest to separate data
const fullRecord = {
id: 123,
createdAt: '2024-01-01',
updatedAt: '2024-06-15',
name: 'Widget',
price: 29.99,
category: 'Electronics',
inStock: true,
};
// Separate into:
// - metadata (id, createdAt, updatedAt)
// - productData (everything else)
// YOUR CODE:
// ============================================
// ============================================
// SOLUTIONS
// ============================================
// ============================================
/*
// SOLUTION 1: Compound Assignment
let a = 10;
a += 5; // a = 15
a *= 2; // a = 30
a -= 10; // a = 20
a /= 4; // a = 5
a %= 3; // a = 2
// SOLUTION 2: String Building
let greeting = "";
greeting += "Hello";
greeting += ", ";
greeting += "World";
greeting += "! ";
greeting += "How are you?";
// or: greeting += "Hello" + ", " + "World" + "! " + "How are you?";
// SOLUTION 3: Logical Assignment Predictions
// b1 = 10 (5 is truthy, so assign 10)
// b2 = 0 (0 is falsy, so don't assign)
// b3 = "default" ("" is falsy, so assign)
// b4 = "hello" ("hello" is truthy, so don't assign)
// b5 = "fallback" (null, so assign)
// b6 = 0 (0 is not nullish, so don't assign)
// SOLUTION 4: Array Destructuring
const [primary, secondary1, secondary2, ...others] = colors;
// SOLUTION 5: Object Destructuring
const {
name: personName,
age = 0,
address: { city },
hobbies
} = person;
// SOLUTION 6: Swap Variables
[x, y] = [y, x];
// SOLUTION 7: Function with Destructured Parameters
function createServer({ port = 3000, host = "localhost", secure = false } = {}) {
const protocol = secure ? "https" : "http";
return `${protocol}://${host}:${port}`;
}
// SOLUTION 8: Counter Class
function createCounter(initial = 0) {
let count = initial;
return {
get value() { return count; },
increment(n = 1) { count += n; },
decrement(n = 1) { count -= n; },
reset() { count = initial; },
double() { count *= 2; }
};
}
// SOLUTION 9: Config Merger
function mergeWithDefaults(config) {
config.timeout ??= 5000;
config.retries ??= 3;
config.debug ??= false;
config.maxConnections ??= 10;
return config;
}
// SOLUTION 10: Multiple Return Values
function getStats(numbers) {
if (!numbers.length) {
return { min: 0, max: 0, sum: 0, average: 0, count: 0 };
}
const sum = numbers.reduce((a, b) => a + b, 0);
return {
min: Math.min(...numbers),
max: Math.max(...numbers),
sum,
average: sum / numbers.length,
count: numbers.length
};
}
// SOLUTION 11: Deep Destructuring
const {
users: [
{ profile: { name: firstUserName } },
{ profile: { email: secondUserEmail } }
],
metadata: { total: totalUsers }
} = data;
// SOLUTION 12: Chained Updates
let value = 100;
value += 50; // 150
value *= 2; // 300
value -= 100; // 200
value /= 5; // 40
value %= 30; // 10
// SOLUTION 13: Safe Property Update
function safeUpdate(obj, path, value) {
const keys = path.split('.');
let current = obj;
for (let i = 0; i < keys.length - 1; i++) {
current[keys[i]] ??= {};
current = current[keys[i]];
}
current[keys[keys.length - 1]] = value;
return obj;
}
// SOLUTION 14: Accumulator Patterns
let totalCredits = 0;
let totalDebits = 0;
for (const t of transactions) {
if (t.type === "credit") {
totalCredits += t.amount;
} else {
totalDebits += t.amount;
}
}
let balance = totalCredits - totalDebits;
// totalCredits = 300, totalDebits = 125, balance = 175
// SOLUTION 15: Rest and Spread Assignment
const { id, createdAt, updatedAt, ...productData } = fullRecord;
const metadata = { id, createdAt, updatedAt };
// metadata = { id: 123, createdAt: "2024-01-01", updatedAt: "2024-06-15" }
// productData = { name: "Widget", price: 29.99, category: "Electronics", inStock: true }
*/