CĂN BẢN
DOM & BOM
XỨ LÝ FORM
JAVASCRIPT TIPS
TUTORIALS
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Functional Programming là gì? Tại sao và khi nào bạn nên sử dụng trong JavaScript

Functional Programming (FP) là một phong cách lập trình tập trung vào việc sử dụng hàm và các khái niệm từ toán học để xử lý dữ liệu. Trong JavaScript, FP không chỉ là một phương pháp lập trình mà còn là một triết lý thiết kế ứng dụng.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Trong bài viết này, mình sẽ tìm hiểu chi tiết về các khái niệm và cách thực hiện Functional Programming trong JavaScript, cùng với ví dụ minh họa.

t E1 BA A3i 20xu E1 BB 91ng 20 2  png

Functional Programming là gì?

Functional Programming (lập trình hàm) là một phương pháp lập trình tập trung vào việc sử dụng các hàm (functions) để thực hiện các thao tác và tính toán. Trong Functional Programming, hàm được coi là một đối tượng đầu tiên (first-class citizen), có thể được truyền vào hàm khác, được trả về từ hàm và được lưu trữ trong biến.

Các nguyên tắc chính của Functional Programming bao gồm:

Bài viết này được đăng tại [free tuts .net]

Pure Functions (Hàm thuần túy): Pure Functions là những hàm không có tác động bên ngoài (side effects) và luôn trả về kết quả dựa trên các tham số đầu vào. Điều này giúp giảm thiểu các vấn đề liên quan đến tình trạng chia sẻ trạng thái và tăng tính dự đoán của ứng dụng.

Immutability (Không thay đổi): Dữ liệu trong Functional Programming là bất biến (immutable), có nghĩa là sau khi tạo ra, nó không thể thay đổi. Thay vào đó, khi cần thay đổi dữ liệu, chúng ta tạo ra một bản sao mới của dữ liệu và thực hiện các thay đổi trên bản sao đó. Điều này giúp tránh được các vấn đề liên quan đến sửa đổi dữ liệu gốc.

Higher-Order Functions (Hàm bậc vao): Higher-Order Functions là các hàm có khả năng nhận một hoặc nhiều hàm khác làm đối số và/hoặc trả về một hàm khác.

Closure (Đóng gói): Closure là cơ chế trong JavaScript cho phép một hàm truy cập vào biến ở phạm vi bên ngoài của nó, ngay cả sau khi hàm đã kết thúc thực thi. Điều này cho phép chúng ta tạo ra các hàm có trạng thái và tái sử dụng được.

Functional Programming giúp giảm thiểu các lỗi phổ biến trong lập trình, như các vấn đề liên quan đến trạng thái chia sẻ và side effects, từ đó tăng tính dự đoán, tái sử dụng và bảo trì của mã nguồn.

Hàm thuần túy (Pure Functions) trong JavaScript

Hàm thuần túy là một khái niệm quan trọng trong Functional Programming, được đặc trưng bởi hai điểm chính: không gây ra hiệu ứng phụ (side effects) và luôn trả về cùng một kết quả với cùng một đầu vào. Điều này có nghĩa là hàm chỉ phụ thuộc vào đầu vào của nó và không ảnh hưởng đến bất kỳ trạng thái nào bên ngoài.

Đặc điểm của hàm thuần túy

Không gây ta hiệu ứng phụ (Side Effects)

  • Hàm thuần túy không thay đổi trạng thái bên ngoài của ứng dụng, như biến toàn cục hoặc thay đổi trực tiếp dữ liệu ngoài phạm vi của hàm.

Luôn trả về cùng một kết quả với cùng một đầu vào:

  • Dù được gọi bao nhiêu lần với các đầu vào khác nhau, hàm thuần túy luôn trả về cùng một kết quả với cùng một đầu vào.

Ví dụ:

// Hàm không thuần túy: gây ra hiệu ứng phụ bằng cách thay đổi biến toàn cục
let taxRate = 0.1;
function calculateTotal(amount) {
    return amount + (amount * taxRate);
}

// Hàm thuần túy: không gây ra hiệu ứng phụ và luôn trả về cùng một kết quả với cùng một đầu vào
function calculateTotal(amount, taxRate) {
    return amount + (amount * taxRate);
}

Trong ví dụ trên, hàm calculateTotal không thuần túy do phụ thuộc vào biến toàn cục taxRate, trong khi hàm thứ hai là một hàm thuần túy vì không gây ra hiệu ứng phụ và luôn trả về cùng một kết quả với cùng một đầu vào.

Immutability (Không Thay Đổi) trong JavaScript

Immutability là một khái niệm quan trọng trong Functional Programming (FP) và là một phần không thể thiếu trong việc áp dụng FP trong JavaScript. Immutability đề cập đến việc dữ liệu, sau khi được tạo ra, không thể được thay đổi. Thay vì thay đổi trực tiếp giá trị của biến, chúng ta tạo ra một bản sao mới của dữ liệu và thay đổi bản sao đó.

Đặc điểm của Immutability

Dữ liệu không thể thay đổi:

  • Khi dữ liệu đã được tạo ra, nó không thể được thay đổi. Bất kỳ thay đổi nào đều tạo ra một bản sao mới của dữ liệu, thay vì thay đổi trực tiếp dữ liệu gốc.

Sử dụng bản sao (Copy) thay vì thay đổi trực tiếp:

  • Thay vì thay đổi trực tiếp dữ liệu gốc, chúng ta tạo ra một bản sao của dữ liệu và thực hiện các thay đổi trên bản sao đó. Điều này giữ cho dữ liệu gốc không bị ảnh hưởng bởi các thay đổi.

Ví dụ:

// Thay đổi giá trị biến trực tiếp
let numbers = [1, 2, 3];
numbers.push(4); // Sử dụng phương thức thay đổi trực tiếp

// Sử dụng immutability
let numbers = [1, 2, 3];
let newNumbers = [...numbers, 4]; // Tạo ra một mảng mới chứa các giá trị cũ và giá trị mới

Trong ví dụ trên, thay vì thay đổi trực tiếp mảng numbers, chúng ta tạo ra một bản sao của nó và thêm một phần tử mới vào bản sao đó, giữ nguyên mảng gốc không bị ảnh hưởng. Điều này làm cho việc sử dụng dữ liệu trở nên an toàn và dễ bảo trì hơn.

Higher-Order Functions (Hàm Bậc Cao) trong JavaScript

Trong lập trình, Higher-Order Functions (Hàm Bậc Cao) là các hàm mà có thể nhận các hàm khác làm đối số hoặc trả về một hàm khác. JavaScript hỗ trợ Higher-Order Functions và chúng là một phần quan trọng của ngôn ngữ này.

Nhận hàm làm đối số:

  • Một Higher-Order Function có thể nhận một hoặc nhiều hàm khác làm đối số. Điều này cho phép chúng ta truyền logic hoặc hành vi từ bên ngoài vào trong hàm.

Trả về hàm khác:

  • Một Higher-Order Function có thể trả về một hàm khác. Điều này cho phép chúng ta tạo ra một hàm mới dựa trên các điều kiện hoặc logic trong hàm gốc.

Ví dụ về Higher-Order Functions:

// Higher-Order Function nhận hàm làm đối số
function modifyArray(array, modifierFunction) {
  return array.map(modifierFunction);
}

// Hàm modifierFunction là một hàm được truyền vào
function doubleValue(value) {
  return value * 2;
}

let numbers = [1, 2, 3, 4, 5];
let doubledNumbers = modifyArray(numbers, doubleValue);
console.log(doubledNumbers); // Output: [2, 4, 6, 8, 10]

// Higher-Order Function trả về một hàm khác
function createMultiplier(multiplier) {
  return function (value) {
    return value * multiplier;
  };
}

let double = createMultiplier(2);
console.log(double(5)); // Output: 10

Trong ví dụ trên, chúng ta có một Higher-Order Function modifyArray nhận một hàm modifierFunction làm đối số và sử dụng nó để biến đổi mảng đầu vào. Chúng ta cũng có một Higher-Order Function createMultiplier trả về một hàm mới mà nhân một giá trị với một hằng số nhất định.

Screenshot 202024 03 09 20005913 png

Closure (Đóng Gói) trong JavaScript

Closure (Đóng Gói) là một khái niệm quan trọng và mạnh mẽ, cho phép các hàm trong JavaScript giữ lại và truy cập các biến từ phạm vi bên ngoài của chúng sau khi phạm vi bên ngoài đã kết thúc. Điều này tạo ra một cách để lưu trữ trạng thái và logic trong các hàm, tạo ra các hàm coi trọng trạng thái của phạm vi bên ngoài mà chúng được tạo ra.

Cách hoạt động của Closure

Khi một hàm được tạo ra trong JavaScript, nó không chỉ lưu trữ logic của chính nó, mà còn lưu trữ một tham chiếu đến phạm vi cha của nó. Khi hàm đó được gọi và cố gắng truy cập một biến mà không được định nghĩa trong phạm vi của nó, JavaScript sẽ tìm kiếm biến đó trong phạm vi cha của hàm. Nếu biến đó được tìm thấy, hàm sẽ sử dụng giá trị của biến đó.

Ví dụ về Closure:

function outerFunction() {
  let outerVariable = 'I am from outer function';

  function innerFunction() {
    console.log(outerVariable); // Inner function có thể truy cập biến của outer function
  }

  return innerFunction;
}

let innerFunc = outerFunction();
innerFunc(); // Output: I am from outer function

Screenshot 202024 03 09 20005848 png

Trong ví dụ này, hàm innerFunction là một Closure vì nó có thể truy cập biến outerVariable từ phạm vi của hàm cha outerFunction ngay cả sau khi outerFunction đã kết thúc thực thi. Khi outerFunction được gọi và trả về innerFunction, closure được tạo ra, giữ lại tham chiếu đến outerVariable. Khi innerFunction được gọi, nó vẫn có thể truy cập và sử dụng giá trị của outerVariable.

Khi nào nên sử dụng Functional Programming trong JavaScript?

Có một số tình huống mà sử dụng Functional Programming (FP) trong JavaScript sẽ mang lại lợi ích lớn. Dưới đây là một số tình huống khi nên sử dụng FP:

Xử lý dữ liệu:

  • Khi bạn cần xử lý và biến đổi dữ liệu, ví dụ như lọc, ánh xạ, hoặc giảm dữ liệu một cách linh hoạt và hiệu quả, FP là một lựa chọn tốt. Các phương thức như map, filter, và reduce trong FP có thể giúp bạn thực hiện các thao tác này một cách dễ dàng và rõ ràng.

Ứng dụng Web phức tạp:

  • Trong các ứng dụng web lớn và phức tạp, việc sử dụng FP giúp làm cho code trở nên dễ bảo trì hơn. FP khuyến khích việc sử dụng các hàm thuần túy và tránh hiệu ứng phụ, giúp giảm thiểu rủi ro của lỗi và hành vi không mong muốn.

Xử lý sự kiện và tương tác người dùng:

  • Khi bạn cần xử lý sự kiện hoặc tương tác người dùng trong ứng dụng web, FP có thể giúp làm cho code trở nên dễ đọc và dễ bảo trì hơn. Sử dụng các hàm thuần túy và tránh hiệu ứng phụ giúp đảm bảo tính đúng đắn và dễ kiểm tra của code.

Xử lý dữ liệu lớn:

  • Khi bạn phải làm việc với dữ liệu lớn hoặc dữ liệu động, FP có thể giúp giảm thiểu rủi ro của lỗi và tối ưu hóa hiệu suất. FP tập trung vào việc sử dụng các phương thức xử lý dữ liệu linh hoạt và hiệu quả, giúp bạn tận dụng tối đa tiềm năng của dữ liệu của mình.

Ví dụ:

Giả sử bạn có một danh sách các số và bạn muốn tìm tổng của các số lớn hơn 5:

// Sử dụng Imperative Programming (lập trình chủ động)
let numbers = [1, 6, 3, 8, 2, 9];
let sum = 0;
for (let i = 0; i < numbers.length; i++) {
    if (numbers[i] > 5) {
        sum += numbers[i];
    }
}
console.log(sum); // Output: 23

// Sử dụng Functional Programming (lập trình hàm)
let sum = numbers.filter(num => num > 5).reduce((acc, curr) => acc + curr, 0);
console.log(sum); 

Trong ví dụ này, sử dụng FP giúp viết code ngắn gọn hơn và dễ đọc hơn. Các phương thức filter và reduce giúp tách biệt logic xử lý dữ liệu và tạo ra một cách tiếp cận linh hoạt và hiệu quả để tìm tổng của các số lớn hơn 5.

Kết bài

Functional Programming là một phương pháp mạnh mẽ và linh hoạt trong việc lập trình JavaScript, giúp tạo ra mã nguồn dễ đọc, dễ bảo trì và dễ kiểm tra. Bằng cách sử dụng các khái niệm như hàm thuần túy, immutability, higher-order functions và closure, bạn có thể tận dụng sức mạnh của FP trong dự án của mình để viết mã JavaScript hiệu quả và dễ bảo trì.

Cùng chuyên mục:

Những tính năng mới trong ES6+ trong JavaScript

Những tính năng mới trong ES6+ trong JavaScript

4 cách tránh memory leaks trong JavaScript

4 cách tránh memory leaks trong JavaScript

Capturing và bubbling Event trong Javascript

Capturing và bubbling Event trong Javascript

Phân biệt prototype và __proto__ trong JavaScript

Phân biệt prototype và __proto__ trong JavaScript

Cách hoạt động của Event Loop trong JavaScript

Cách hoạt động của Event Loop trong JavaScript

Phương thức bind(), call(), và apply() trong JavaScript

Phương thức bind(), call(), và apply() trong JavaScript

Cách khắc phục lỗi

Cách khắc phục lỗi "hoisting" trong JavaScript

Sử dụng Promise.all và Promise.race để quản lý các Promise trong JavaScript

Sử dụng Promise.all và Promise.race để quản lý các Promise trong JavaScript

Xử lý bất đồng bộ bằng vòng lặp for-await trong JavaScript

Xử lý bất đồng bộ bằng vòng lặp for-await trong JavaScript

Sự khác biệt giữa Promise, Callback và Async/Await trong JavaScript

Sự khác biệt giữa Promise, Callback và Async/Await trong JavaScript

Cách sử dụng Async functions trong JavaScript

Cách sử dụng Async functions trong JavaScript

Hàm String isspace() trong Python

Hàm String isspace() trong Python

Cách tạo số ngẫu nhiên trong Javascript

Cách tạo số ngẫu nhiên trong Javascript

Hướng dẫn cách tạo một số ngẫu nhiên ...

Cách gộp hai object javascript lại với nhau

Cách gộp hai object javascript lại với nhau

Cách lấy chiều dài của object trong Javascript

Cách lấy chiều dài của object trong Javascript

Hướng dẫn giải phương trình bậc 1 bằng Javascript

Hướng dẫn giải phương trình bậc 1 bằng Javascript

Cách dùng nextSibling trong javascript

Cách dùng nextSibling trong javascript

Cách dùng insertAdjacentHTML trong javascript

Cách dùng insertAdjacentHTML trong javascript

Cách dùng innerHTML trong Javascript

Cách dùng innerHTML trong Javascript

Cách dùng insertBefore trong javascript

Cách dùng insertBefore trong javascript

Top