🎭 Function Techniques: The Secret Superpowers of JavaScript Functions
Imagine you’re a chef in a magical kitchen. Each cooking technique you learn makes you better, faster, and more creative. Today, we’ll learn the secret techniques that transform ordinary functions into extraordinary ones!
🌟 What We’ll Discover
Think of functions like LEGO blocks. Basic functions are single blocks. But with these 7 techniques, you’ll learn to build amazing structures!
graph TD A["🎯 Function Techniques"] --> B["Pure Functions"] A --> C["Side Effects"] A --> D["Recursion"] A --> E["Memoization"] A --> F["Currying"] A --> G["Partial Application"] A --> H["Composition"]
1. 🧼 Pure Functions: The Honest Helper
The Story
Imagine a vending machine. You put in $1, press “cola” — you ALWAYS get a cola. Same input, same output. Every. Single. Time.
That’s a pure function!
What Makes It Pure?
- Same input = Same output (always!)
- No sneaky changes (doesn’t touch anything outside itself)
Example: Pure vs Impure
// ✅ PURE - like a honest calculator
function add(a, b) {
return a + b;
}
add(2, 3); // Always 5
add(2, 3); // Still 5!
// ❌ IMPURE - sneaky counter!
let count = 0;
function addAndCount(a, b) {
count++; // Touches outside world!
return a + b;
}
Why Pure Functions Rock
| Benefit | What It Means |
|---|---|
| 🔮 Predictable | You always know what you’ll get |
| 🧪 Easy to test | No surprises! |
| 🔄 Reusable | Works anywhere |
Remember: Pure functions are like honest friends — no surprises, no drama!
2. 💥 Side Effects: The Outside Touch
The Story
When you draw on the wall (not paper), that’s a side effect! You changed something outside your drawing book.
What Are Side Effects?
Anything that changes the “outside world”:
- ✏️ Changing a variable outside the function
- 📺 Showing something on screen
- 💾 Saving to a database
- 🌐 Fetching from the internet
Example: Spot the Side Effect
// Side effect: changing 'total'
let total = 0;
function addToTotal(num) {
total = total + num; // 💥 BOOM!
return total;
}
// Side effect: showing on screen
function greet(name) {
console.log("Hello " + name);
// 💥 Changes the console!
}
When Side Effects Are OK
Sometimes you NEED them! Just:
- 📍 Keep them in one place
- 📝 Name functions clearly
- ⚠️ Handle errors
Think of it this way: Side effects aren’t evil — they’re just powerful. Use them wisely!
3. 🔁 Recursion: The Russian Doll
The Story
Open a Russian doll. Inside? Another doll! Open that one. Another! Keep going until you find the tiniest doll.
That’s recursion! A function calling itself until it hits the smallest problem.
The Magic Formula
1. Base case (the tiny doll — STOP here!)
2. Recursive case (open the next doll)
Example: Counting Down
function countdown(n) {
// Base case: stop at 0!
if (n === 0) {
console.log("Blast off! 🚀");
return;
}
console.log(n);
countdown(n - 1); // Call myself!
}
countdown(3);
// 3
// 2
// 1
// Blast off! 🚀
Example: Factorial (5! = 5×4×3×2×1)
function factorial(n) {
if (n <= 1) return 1; // Base!
return n * factorial(n - 1);
}
factorial(5); // 120
graph TD A["factorial 5"] --> B["5 × factorial 4"] B --> C["4 × factorial 3"] C --> D["3 × factorial 2"] D --> E["2 × factorial 1"] E --> F["1 ← BASE CASE!"]
Warning: Always have a base case, or you’ll loop forever!
4. 📝 Memoization: The Smart Notebook
The Story
Your teacher asks “What’s 12 × 12?” You calculate: 144. She asks again tomorrow. Do you calculate again? NO! You remember!
Memoization = Remember answers to avoid recalculating!
How It Works
1. Check: Did I solve this before?
2. YES → Return saved answer! ⚡
3. NO → Calculate, SAVE it, return
Example: Slow vs Memoized
// Slow: calculates every time!
function slowFib(n) {
if (n <= 1) return n;
return slowFib(n-1) + slowFib(n-2);
}
slowFib(40); // 😰 Takes forever!
// Fast: remembers answers!
function memoize(fn) {
const cache = {};
return function(n) {
if (cache[n]) return cache[n];
cache[n] = fn(n);
return cache[n];
};
}
const fastFib = memoize(function(n) {
if (n <= 1) return n;
return fastFib(n-1) + fastFib(n-2);
});
fastFib(40); // ⚡ Instant!
| Without Memo | With Memo |
|---|---|
| 🐌 Slow | 🚀 Fast |
| Recalculates | Remembers |
| Wastes energy | Saves energy |
5. 🍛 Currying: One Ingredient at a Time
The Story
Imagine ordering a pizza. Instead of saying everything at once, you say:
- “I want pizza” → OK, what size?
- “Large” → OK, what topping?
- “Pepperoni” → Here’s your pizza!
Currying = Breaking a multi-argument function into single steps!
Example: Regular vs Curried
// Regular: all at once
function add(a, b, c) {
return a + b + c;
}
add(1, 2, 3); // 6
// Curried: one at a time
function curriedAdd(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
curriedAdd(1)(2)(3); // 6
// Or step by step:
const addOne = curriedAdd(1);
const addOneAndTwo = addOne(2);
addOneAndTwo(3); // 6
Arrow Function Style (Cleaner!)
const curriedAdd = a => b => c => a + b + c;
curriedAdd(1)(2)(3); // 6
Why curry? Create specialized functions from general ones!
6. ✂️ Partial Application: Pre-fill Some Blanks
The Story
A form has 5 fields. 3 are always the same for you. Pre-fill those! Now you only enter 2.
Partial application = Fill in SOME arguments now, rest later!
Difference from Currying
| Currying | Partial Application |
|---|---|
| One arg at a time | Some args now, rest later |
| Always single steps | Flexible |
Example
// Original function
function greet(greeting, name) {
return greeting + ", " + name + "!";
}
// Partially apply: fix the greeting
function sayHello(name) {
return greet("Hello", name);
}
sayHello("Alice"); // "Hello, Alice!"
sayHello("Bob"); // "Hello, Bob!"
Using bind()
function multiply(a, b) {
return a * b;
}
// Pre-fill 'a' with 2
const double = multiply.bind(null, 2);
double(5); // 10
double(10); // 20
Think of it as: Creating a specialized version of a general tool!
7. 🧩 Function Composition: Chain the Powers!
The Story
Imagine a factory:
- Machine 1: Washes apples
- Machine 2: Peels apples
- Machine 3: Slices apples
Connect them! Apple goes in → Washed, peeled, sliced apple comes out!
Composition = Connecting functions like a pipeline!
Example: Step by Step
const addTwo = x => x + 2;
const triple = x => x * 3;
const square = x => x * x;
// Manual chain
let result = 5;
result = addTwo(result); // 7
result = triple(result); // 21
result = square(result); // 441
Compose Function
// Right to left (math style)
function compose(...fns) {
return x => fns.reduceRight(
(acc, fn) => fn(acc),
x
);
}
const superMath = compose(
square,
triple,
addTwo
);
superMath(5);
// addTwo(5)=7 → triple(7)=21 → square(21)=441
graph LR A["5"] --> B["addTwo"] B --> C["7"] C --> D["triple"] D --> E["21"] E --> F["square"] F --> G["441"]
Pipe: Left to Right (Easier to Read!)
function pipe(...fns) {
return x => fns.reduce(
(acc, fn) => fn(acc),
x
);
}
const superMath = pipe(
addTwo,
triple,
square
);
// Reads naturally: add, then triple, then square
🎯 Quick Comparison
| Technique | One-Line Summary |
|---|---|
| Pure Functions | Same input → Same output, no surprises |
| Side Effects | Changes outside the function |
| Recursion | Function calls itself (remember base case!) |
| Memoization | Remember answers, don’t recalculate |
| Currying | One argument at a time |
| Partial Application | Pre-fill some arguments |
| Composition | Chain functions like a pipeline |
🌈 The Big Picture
graph TD A["Your Function Journey"] --> B["Start with Pure Functions"] B --> C["Understand Side Effects"] C --> D["Master Recursion"] D --> E["Speed Up with Memoization"] E --> F["Get Flexible with Currying"] F --> G["Pre-fill with Partial Application"] G --> H["Build Pipelines with Composition"] H --> I["🏆 Function Master!"]
💪 You Did It!
You just learned 7 powerful techniques that professional developers use every day!
Remember:
- 🧼 Pure = Honest, predictable
- 💥 Side Effects = Outside changes (use carefully)
- 🔁 Recursion = Self-calling (don’t forget the stop!)
- 📝 Memoization = Smart memory
- 🍛 Currying = One step at a time
- ✂️ Partial = Pre-fill arguments
- 🧩 Composition = Chain functions together
Now go build amazing things! 🚀
