javascript
exercises
exercises.js⚡javascript
/**
* =====================================================
* 5.2 FUNCTION EXPRESSIONS - EXERCISES
* =====================================================
* Practice function expressions
*/
/**
* Exercise 1: Basic Function Expression
*
* Convert this function declaration to a function expression.
* function multiply(a, b) { return a * b; }
*/
// TODO: Create function expression
const multiply = undefined;
// Test cases:
console.log('Exercise 1:');
// console.log(multiply(4, 5)); // 20
// console.log(multiply(3, 7)); // 21
/**
* Exercise 2: Named Function Expression
*
* Create a named function expression called 'countdown'
* that recursively counts down from n to 0.
* Use the internal name for recursion.
*/
const countdown = undefined;
// Test cases:
console.log('\nExercise 2:');
// countdown(5); // Should log: 5, 4, 3, 2, 1, 0
/**
* Exercise 3: IIFE
*
* Create an IIFE that returns the sum of 1 to 10.
*/
const sumOneToTen = undefined;
// Test cases:
console.log('\nExercise 3:');
// console.log(sumOneToTen); // 55
/**
* Exercise 4: Counter Module
*
* Create a counter module using IIFE that has:
* - Private count variable starting at 0
* - increment() method
* - decrement() method
* - getCount() method
* - reset() method
*/
const myCounter = undefined;
// Test cases:
console.log('\nExercise 4:');
// console.log(myCounter.getCount()); // 0
// myCounter.increment();
// myCounter.increment();
// console.log(myCounter.getCount()); // 2
// myCounter.decrement();
// console.log(myCounter.getCount()); // 1
// myCounter.reset();
// console.log(myCounter.getCount()); // 0
/**
* Exercise 5: Create Multiplier
*
* Create a function expression that returns another function.
* The returned function multiplies its argument by the original factor.
*/
const createMultiplier = undefined;
// Test cases:
console.log('\nExercise 5:');
// const double = createMultiplier(2);
// const triple = createMultiplier(3);
// console.log(double(5)); // 10
// console.log(triple(5)); // 15
/**
* Exercise 6: Callback Processor
*
* Create a function expression that takes an array and a callback.
* Apply the callback to each element and return the new array.
*/
const processArray = undefined;
// Test cases:
console.log('\nExercise 6:');
// const nums = [1, 2, 3, 4, 5];
// const squared = processArray(nums, function(x) { return x * x; });
// console.log(squared); // [1, 4, 9, 16, 25]
/**
* Exercise 7: Conditional Formatter
*
* Create a function that returns different formatter functions
* based on the format type: "upper", "lower", "title", "reverse"
*/
const createFormatter = undefined;
// Test cases:
console.log('\nExercise 7:');
// const upper = createFormatter("upper");
// const lower = createFormatter("lower");
// const title = createFormatter("title");
// const reverse = createFormatter("reverse");
// console.log(upper("hello")); // "HELLO"
// console.log(lower("HELLO")); // "hello"
// console.log(title("hello world")); // "Hello World"
// console.log(reverse("hello")); // "olleh"
/**
* Exercise 8: Once Function
*
* Create a function expression that returns a function
* that can only be called once. Subsequent calls return
* the same result from the first call.
*/
const once = undefined;
// Test cases:
console.log('\nExercise 8:');
// const initialize = once(function() {
// console.log("Initializing...");
// return { status: "ready" };
// });
// console.log(initialize()); // logs "Initializing...", returns { status: "ready" }
// console.log(initialize()); // just returns { status: "ready" }, no log
/**
* Exercise 9: Compose Functions
*
* Create a compose function that takes two functions
* and returns a new function that applies them right-to-left.
* compose(f, g)(x) = f(g(x))
*/
const compose = undefined;
// Test cases:
console.log('\nExercise 9:');
// const addOne = function(x) { return x + 1; };
// const double = function(x) { return x * 2; };
// const addOneThenDouble = compose(double, addOne);
// console.log(addOneThenDouble(5)); // 12 (5+1=6, 6*2=12)
/**
* Exercise 10: Simple Event Emitter
*
* Create an event emitter using IIFE with:
* - on(event, handler) - register handler
* - emit(event, data) - call all handlers for event
* - off(event, handler) - remove specific handler
*/
const eventEmitter = undefined;
// Test cases:
console.log('\nExercise 10:');
// const handler1 = function(data) { console.log("Handler 1:", data); };
// const handler2 = function(data) { console.log("Handler 2:", data); };
// eventEmitter.on("test", handler1);
// eventEmitter.on("test", handler2);
// eventEmitter.emit("test", "Hello!"); // Both handlers called
// eventEmitter.off("test", handler1);
// eventEmitter.emit("test", "Goodbye!"); // Only handler2 called
// =====================================================
// INTERMEDIATE EXERCISES
// =====================================================
/**
* Exercise 11: Memoize
*
* Create a memoize function expression that caches
* results of function calls.
*/
const memoize = undefined;
// Test cases:
console.log('\nExercise 11:');
// let callCount = 0;
// const expensiveOperation = function(n) {
// callCount++;
// return n * n;
// };
// const memoizedOp = memoize(expensiveOperation);
// console.log(memoizedOp(5)); // 25, callCount = 1
// console.log(memoizedOp(5)); // 25, callCount = 1 (cached)
// console.log(memoizedOp(6)); // 36, callCount = 2
/**
* Exercise 12: Debounce
*
* Create a debounce function that delays invoking a function
* until after X milliseconds have passed since the last call.
*/
const debounce = undefined;
// Test cases:
console.log('\nExercise 12:');
// const log = debounce(function(msg) {
// console.log("Debounced:", msg);
// }, 100);
// log("a"); log("b"); log("c");
// // Only "c" should be logged after 100ms
/**
* Exercise 13: Pipe
*
* Create a pipe function that takes multiple functions
* and applies them left-to-right (opposite of compose).
* pipe(f, g, h)(x) = h(g(f(x)))
*/
const pipe = undefined;
// Test cases:
console.log('\nExercise 13:');
// const addTwo = function(x) { return x + 2; };
// const multiplyThree = function(x) { return x * 3; };
// const subtractOne = function(x) { return x - 1; };
// const piped = pipe(addTwo, multiplyThree, subtractOne);
// console.log(piped(5)); // 20 ((5+2)*3-1)
/**
* Exercise 14: Partial Application
*
* Create a partial function that pre-fills some arguments.
*/
const partial = undefined;
// Test cases:
console.log('\nExercise 14:');
// const greet = function(greeting, name) {
// return greeting + ", " + name + "!";
// };
// const sayHello = partial(greet, "Hello");
// console.log(sayHello("Alice")); // "Hello, Alice!"
/**
* Exercise 15: Create Store
*
* Create a simple state store using IIFE with:
* - getState() - returns current state
* - setState(newState) - updates state
* - subscribe(listener) - adds change listener
* - unsubscribe(listener) - removes listener
*/
const createStore = undefined;
// Test cases:
console.log('\nExercise 15:');
// const store = createStore({ count: 0 });
// const listener = function(state) { console.log("State changed:", state); };
// store.subscribe(listener);
// store.setState({ count: 1 }); // Should log state change
// console.log(store.getState()); // { count: 1 }
// store.unsubscribe(listener);
// store.setState({ count: 2 }); // No log (unsubscribed)
// =====================================================
// SOLUTIONS (Uncomment to check your answers)
// =====================================================
/*
// Exercise 1 Solution:
const multiply = function(a, b) {
return a * b;
};
// Exercise 2 Solution:
const countdown = function countdownRecursive(n) {
console.log(n);
if (n > 0) {
countdownRecursive(n - 1);
}
};
// Exercise 3 Solution:
const sumOneToTen = (function() {
let sum = 0;
for (let i = 1; i <= 10; i++) {
sum += i;
}
return sum;
})();
// Exercise 4 Solution:
const myCounter = (function() {
let count = 0;
return {
increment: function() { count++; return this; },
decrement: function() { count--; return this; },
getCount: function() { return count; },
reset: function() { count = 0; return this; }
};
})();
// Exercise 5 Solution:
const createMultiplier = function(factor) {
return function(number) {
return number * factor;
};
};
// Exercise 6 Solution:
const processArray = function(arr, callback) {
const result = [];
for (const item of arr) {
result.push(callback(item));
}
return result;
};
// Exercise 7 Solution:
const createFormatter = function(type) {
switch (type) {
case "upper":
return function(str) { return str.toUpperCase(); };
case "lower":
return function(str) { return str.toLowerCase(); };
case "title":
return function(str) {
return str.split(" ").map(function(word) {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
}).join(" ");
};
case "reverse":
return function(str) { return str.split("").reverse().join(""); };
default:
return function(str) { return str; };
}
};
// Exercise 8 Solution:
const once = function(fn) {
let called = false;
let result;
return function(...args) {
if (!called) {
called = true;
result = fn(...args);
}
return result;
};
};
// Exercise 9 Solution:
const compose = function(f, g) {
return function(x) {
return f(g(x));
};
};
// Exercise 10 Solution:
const eventEmitter = (function() {
const events = {};
return {
on: function(event, handler) {
if (!events[event]) events[event] = [];
events[event].push(handler);
},
emit: function(event, data) {
if (events[event]) {
events[event].forEach(function(h) { h(data); });
}
},
off: function(event, handler) {
if (events[event]) {
events[event] = events[event].filter(function(h) {
return h !== handler;
});
}
}
};
})();
// Exercise 11 Solution:
const memoize = function(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key] !== undefined) {
return cache[key];
}
const result = fn(...args);
cache[key] = result;
return result;
};
};
// Exercise 12 Solution:
const debounce = function(fn, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
fn(...args);
}, delay);
};
};
// Exercise 13 Solution:
const pipe = function(...fns) {
return function(x) {
return fns.reduce(function(acc, fn) {
return fn(acc);
}, x);
};
};
// Exercise 14 Solution:
const partial = function(fn, ...presetArgs) {
return function(...laterArgs) {
return fn(...presetArgs, ...laterArgs);
};
};
// Exercise 15 Solution:
const createStore = function(initialState) {
let state = initialState;
const listeners = [];
return {
getState: function() { return state; },
setState: function(newState) {
state = newState;
listeners.forEach(function(listener) {
listener(state);
});
},
subscribe: function(listener) {
listeners.push(listener);
},
unsubscribe: function(listener) {
const index = listeners.indexOf(listener);
if (index > -1) {
listeners.splice(index, 1);
}
}
};
};
*/