javascript
examples
examples.js⚡javascript
/**
* =====================================================
* 5.2 FUNCTION EXPRESSIONS - EXAMPLES
* =====================================================
* Alternative way to define functions
*/
// =====================================================
// 1. BASIC FUNCTION EXPRESSION
// =====================================================
console.log('--- Basic Function Expression ---');
const greet = function (name) {
return 'Hello, ' + name + '!';
};
console.log(greet('Alice'));
console.log(greet('Bob'));
// =====================================================
// 2. ANONYMOUS VS NAMED EXPRESSIONS
// =====================================================
console.log('\n--- Anonymous vs Named ---');
// Anonymous
const add = function (a, b) {
return a + b;
};
// Named
const subtract = function sub(a, b) {
return a - b;
};
console.log('add.name:', add.name); // "add" (inferred)
console.log('subtract.name:', subtract.name); // "sub"
// =====================================================
// 3. NAMED EXPRESSION FOR RECURSION
// =====================================================
console.log('\n--- Recursion with Named Expression ---');
const factorial = function fact(n) {
if (n <= 1) return 1;
return n * fact(n - 1); // Uses internal name
};
console.log('5! =', factorial(5));
console.log('10! =', factorial(10));
// The internal name 'fact' is only accessible inside
// console.log(fact(5)); // Error: fact is not defined
// =====================================================
// 4. HOISTING DIFFERENCES
// =====================================================
console.log('\n--- Hoisting Differences ---');
// Function declaration - hoisted
console.log('Declaration (hoisted):', declaredFunc());
function declaredFunc() {
return "I'm hoisted!";
}
// Function expression - NOT hoisted
// console.log(expressedFunc()); // Error!
const expressedFunc = function () {
return "I'm NOT hoisted!";
};
console.log('Expression (after definition):', expressedFunc());
// =====================================================
// 5. IIFE - IMMEDIATELY INVOKED FUNCTION EXPRESSION
// =====================================================
console.log('\n--- IIFE ---');
// Basic IIFE
(function () {
console.log('IIFE executed immediately!');
})();
// IIFE with parameters
const result = (function (a, b) {
return a + b;
})(10, 20);
console.log('IIFE result:', result);
// Named IIFE
(function init() {
console.log('Initialization complete');
})();
// =====================================================
// 6. IIFE FOR PRIVATE SCOPE
// =====================================================
console.log('\n--- IIFE for Private Scope ---');
const counter = (function () {
let count = 0; // Private variable
return {
increment: function () {
count++;
return count;
},
decrement: function () {
count--;
return count;
},
getCount: function () {
return count;
},
};
})();
console.log('Initial:', counter.getCount());
console.log('After increment:', counter.increment());
console.log('After increment:', counter.increment());
console.log('After decrement:', counter.decrement());
// console.log(count); // Error: count is not defined (private)
// =====================================================
// 7. CALLBACK FUNCTIONS
// =====================================================
console.log('\n--- Callback Functions ---');
function processArray(arr, callback) {
const results = [];
for (const item of arr) {
results.push(callback(item));
}
return results;
}
// Using function expression as callback
const double = function (x) {
return x * 2;
};
const square = function (x) {
return x * x;
};
const numbers = [1, 2, 3, 4, 5];
console.log('Doubled:', processArray(numbers, double));
console.log('Squared:', processArray(numbers, square));
// Inline anonymous callback
console.log(
'Tripled:',
processArray(numbers, function (x) {
return x * 3;
})
);
// =====================================================
// 8. HIGHER-ORDER FUNCTIONS
// =====================================================
console.log('\n--- Higher-Order Functions ---');
// Function that returns a function
function createMultiplier(factor) {
return function (number) {
return number * factor;
};
}
const triple = createMultiplier(3);
const quadruple = createMultiplier(4);
console.log('triple(10):', triple(10));
console.log('quadruple(10):', quadruple(10));
// Function that takes multiple callbacks
function conditional(value, onTrue, onFalse) {
return value ? onTrue() : onFalse();
}
const result2 = conditional(
true,
function () {
return 'It was true';
},
function () {
return 'It was false';
}
);
console.log('Conditional result:', result2);
// =====================================================
// 9. FUNCTION COMPOSITION
// =====================================================
console.log('\n--- Function Composition ---');
const compose = function (f, g) {
return function (x) {
return f(g(x));
};
};
const addOne = function (x) {
return x + 1;
};
const doubleNum = function (x) {
return x * 2;
};
const squareNum = function (x) {
return x * x;
};
const addOneThenDouble = compose(doubleNum, addOne);
const doubleThenSquare = compose(squareNum, doubleNum);
console.log('addOneThenDouble(5):', addOneThenDouble(5)); // (5+1)*2 = 12
console.log('doubleThenSquare(3):', doubleThenSquare(3)); // (3*2)² = 36
// =====================================================
// 10. MODULE PATTERN
// =====================================================
console.log('\n--- Module Pattern ---');
const calculator = (function () {
// Private state
let memory = 0;
// Private function
function log(operation, value) {
console.log(` ${operation}: ${value}, Memory: ${memory}`);
}
// Public interface
return {
add: function (n) {
memory += n;
log('Add', n);
return this;
},
subtract: function (n) {
memory -= n;
log('Subtract', n);
return this;
},
multiply: function (n) {
memory *= n;
log('Multiply', n);
return this;
},
getResult: function () {
return memory;
},
clear: function () {
memory = 0;
log('Clear', 0);
return this;
},
};
})();
calculator.add(10).multiply(2).subtract(5).add(3);
console.log('Final result:', calculator.getResult());
// =====================================================
// 11. FACTORY FUNCTION
// =====================================================
console.log('\n--- Factory Function ---');
const createUser = function (name, role) {
// Private
let loginCount = 0;
// Public
return {
name: name,
role: role,
login: function () {
loginCount++;
console.log(`${name} logged in. Total logins: ${loginCount}`);
},
getLoginCount: function () {
return loginCount;
},
};
};
const user1 = createUser('Alice', 'admin');
const user2 = createUser('Bob', 'user');
user1.login();
user1.login();
user2.login();
console.log('Alice logins:', user1.getLoginCount());
console.log('Bob logins:', user2.getLoginCount());
// =====================================================
// 12. CONDITIONAL FUNCTION CREATION
// =====================================================
console.log('\n--- Conditional Function Creation ---');
function createFormatter(type) {
if (type === 'uppercase') {
return function (str) {
return str.toUpperCase();
};
} else if (type === 'lowercase') {
return function (str) {
return str.toLowerCase();
};
} else {
return function (str) {
return str;
};
}
}
const uppercase = createFormatter('uppercase');
const lowercase = createFormatter('lowercase');
console.log(uppercase('Hello World'));
console.log(lowercase('Hello World'));
// =====================================================
// 13. STORING FUNCTIONS IN DATA STRUCTURES
// =====================================================
console.log('\n--- Functions in Data Structures ---');
// Array of functions
const operations = [
function (x) {
return x + 10;
},
function (x) {
return x * 2;
},
function (x) {
return x - 5;
},
];
let value = 10;
for (const op of operations) {
value = op(value);
console.log('Value:', value);
}
// Object of functions
const handlers = {
click: function (e) {
console.log('Clicked!');
},
hover: function (e) {
console.log('Hovered!');
},
keypress: function (e) {
console.log('Key pressed!');
},
};
handlers.click();
handlers.hover();
// =====================================================
// 14. FUNCTION EXPRESSION AS METHOD
// =====================================================
console.log('\n--- Function Expression as Method ---');
const person = {
name: 'Charlie',
greet: function () {
return "Hi, I'm " + this.name;
},
// ES6 shorthand (also a function expression internally)
wave() {
return this.name + ' waves!';
},
};
console.log(person.greet());
console.log(person.wave());
// =====================================================
// 15. PRACTICAL EXAMPLE: EVENT HANDLER PATTERN
// =====================================================
console.log('\n--- Event Handler Pattern ---');
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 (handler) {
handler(data);
});
}
},
off: function (event, handler) {
if (events[event]) {
events[event] = events[event].filter(function (h) {
return h !== handler;
});
}
},
};
})();
// Register handlers
const logHandler = function (data) {
console.log('Event data:', data);
};
EventEmitter.on('message', logHandler);
EventEmitter.on('message', function (data) {
console.log('Another handler:', data.toUpperCase());
});
// Emit event
EventEmitter.emit('message', 'Hello!');
// =====================================================
// SUMMARY
// =====================================================
console.log('\n--- Summary ---');
console.log(`
Function Expressions:
• const fn = function() {};
• NOT hoisted
• Can be anonymous or named
Named Expressions:
• Better stack traces
• Enable recursion
• Self-documenting
IIFE:
• (function() { })();
• Runs immediately
• Creates private scope
Common Patterns:
• Module pattern
• Factory functions
• Callbacks
• Higher-order functions
`);