JavaScript Course Content

Hàm Nâng Cao & Closures trong JavaScript

Thành thạo closures, higher-order functions và các khái niệm lập trình hàm nâng cao

Cấp độ Nâng caoLý thuyết + Thực hànhVí dụ tương tác25+ Câu hỏi

Tiến độ học tập: 75% hoàn thành

Mục tiêu học tập
Sau khi hoàn thành bài học này, bạn sẽ thành thạo các khái niệm JavaScript nâng cao

Hiểu sâu về Closures và lexical scoping

Nắm vững Higher-Order Functions và callbacks

Áp dụng Function Composition và Currying

Sử dụng Memoization để tối ưu performance

Hiểu Factory Functions và Module Pattern

Làm việc với Recursion và Tail Call Optimization

Áp dụng Functional Programming Patterns

Xây dựng Custom Decorators và Middleware

Các khái niệm nâng cao
Tìm hiểu sâu về các khái niệm hàm JavaScript phức tạp

Closure (Bao đóng)

Intermediate

Hàm có thể "nhớ" và truy cập biến từ lexical scope bên ngoài ngay cả khi scope đó đã kết thúc thực thi.

Ví dụ về Closure (Bao đóng)

javascript
1function outer(x) {
2 return function inner(y) {
3 return x + y; // "nhớ" x từ outer scope
4 };
5}

Điểm quan trọng:

  • Closures "nhớ" outer scope variables
  • Useful cho data encapsulation
  • Có thể gây memory leaks nếu không cẩn thận

Lexical Scoping

Beginner

Scope được xác định bởi vị trí khai báo trong code, không phải runtime context.

Ví dụ về Lexical Scoping

javascript
1const global = 'global';
2function outer() {
3 const local = 'local';
4 return () => console.log(global, local);
5}

Điểm quan trọng:

  • Scope xác định tại compile time
  • Inner functions truy cập outer scope
  • Cơ sở cho closures

Higher-Order Function

Intermediate

Hàm nhận hàm khác làm argument hoặc trả về hàm, cho phép abstraction cao hơn.

Ví dụ về Higher-Order Function

javascript
1const withLogging = (fn) => (...args) => {
2 console.log('Calling:', fn.name);
3 return fn(...args);
4};

Điểm quan trọng:

  • Functions as first-class citizens
  • Enables functional programming patterns
  • Used in map, filter, reduce

Currying

Advanced

Technique chuyển đổi hàm nhiều parameters thành chuỗi hàm một parameter.

Ví dụ về Currying

javascript
1const add = a => b => c => a + b + c;
2const addFive = add(5);
3const addFiveTen = addFive(10);

Điểm quan trọng:

  • Partial application of functions
  • Creates reusable specialized functions
  • Functional programming technique

Memoization

Advanced

Caching kết quả của expensive function calls để tối ưu performance.

Ví dụ về Memoization

javascript
1const memoize = (fn) => {
2 const cache = {};
3 return (...args) => {
4 const key = JSON.stringify(args);
5 return cache[key] || (cache[key] = fn(...args));
6 };
7};

Điểm quan trọng:

  • Trade memory for speed
  • Ideal for pure functions
  • Avoid with side effects

Function Composition

Advanced

Kết hợp nhiều hàm nhỏ để tạo thành hàm phức tạp hơn.

Ví dụ về Function Composition

javascript
1const compose = (f, g) => x => f(g(x));
2const addOne = x => x + 1;
3const double = x => x * 2;
4const addOneThenDouble = compose(double, addOne);

Điểm quan trọng:

  • Build complex operations from simple ones
  • Promotes code reusability
  • Core of functional programming
So sánh các khái niệm
Hiểu rõ sự khác biệt giữa các khái niệm hàm nâng cao
Khái niệmMục đíchTrường hợp sử dụngHiệu suất
ClosuresData encapsulation and state persistencePrivate variables, module patternsMedium
Higher-Order FunctionsFunction composition and abstractionCallbacks, event handling, functional programmingHigh
CurryingPartial application and reusabilityConfiguration functions, specialized utilitiesMedium
MemoizationPerformance optimization through cachingExpensive calculations, recursive functionsHigh
Function CompositionBuilding complex operations from simple onesData transformation pipelinesHigh
RecursionSolving problems by breaking them downTree traversal, mathematical sequencesLow
Thực hành tốt nhất
Hướng dẫn viết hàm nâng cao sạch và hiệu quả

Avoid Memory Leaks với Closures

Cleanup references khi không cần để tránh memory leaks

Ví dụ thực hành tốt

javascript
// Có thể gây memory leak
function problematicClosure() {
const largeData = new Array(1000000).fill('data');
return function smallOperation() {
return 'done';
};
}
// Cách tốt hơn
function betterClosure() {
const largeData = new Array(1000000).fill('data');
return function smallOperation() {
// largeData = null; // Cleanup if not needed
return 'done';
};
}

Sử dụng Factory Functions cho Object Creation

Factory functions provide flexibility và encapsulation

Ví dụ thực hành tốt

javascript
// Factory function
function createUser(name, email) {
let isLoggedIn = false;
return {
name,
email,
login() { isLoggedIn = true; },
logout() { isLoggedIn = false; },
isActive() { return isLoggedIn; }
};
}
const user = createUser('John', '[email protected]');

Prefer Function Composition

Tạo complex operations từ simple functions

Ví dụ thực hành tốt

javascript
const pipe = (...fns) => (value) => fns.reduce((acc, fn) => fn(acc), value);
const processData = pipe(
data => data.trim(),
data => data.toLowerCase(),
data => data.split(' ')
);

Use Memoization cho Expensive Operations

Cache results để improve performance

Ví dụ thực hành tốt

javascript
const memoize = (fn) => {
const cache = {};
return (...args) => {
const key = JSON.stringify(args);
return cache[key] || (cache[key] = fn(...args));
};
};
const expensiveFn = memoize((n) => {
// expensive calculation
return result;
});
Lỗi thường gặp
Tránh những lỗi phổ biến khi làm việc với hàm nâng cao

Closure trong loops với var

Sử dụng var trong vòng lặp có thể gây ra kết quả không mong muốn do hoisting

Sai:
// Lỗi
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // Prints 3, 3, 3
}
Đúng:
// Đúng với let
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // Prints 0, 1, 2
}
// Hoặc sử dụng IIFE
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(() => console.log(j), 100); // Prints 0, 1, 2
})(i);
}

Memory leaks từ forgotten closures

Closures có thể giữ references đến DOM elements, gây memory leaks

Sai:
// Lỗi - memory leak
function createHandler() {
const hugeDOMElement = document.querySelector('#huge-element');
return function() {
console.log('handled');
// hugeDOMElement is still referenced
};
}
Đúng:
// Đúng - cleanup references
function createHandler() {
let hugeDOMElement = document.querySelector('#huge-element');
return function() {
console.log('handled');
hugeDOMElement = null; // Cleanup
};
}

Overusing closures khi không cần

Không nên dùng closures cho những operations đơn giản

Sai:
// Không cần thiết
function createAdder(x) {
return function(y) {
return x + y;
};
}
Đúng:
// Đơn giản hơn
const add = (x, y) => x + y;
// Hoặc sử dụng closure khi thực sự cần
const createSpecializedAdder = (base) => (value) => base + value;

Mục lục

Không có mục lục