JavaScript - Currying: Hướng dẫn cho người mới bắt đầu

Xin chào các bạn đang học lập trình! Hôm nay, chúng ta sẽ bắt đầu một hành trình thú vị vào thế giới của JavaScript và khám phá một khái niệm叫做 "currying." Đừng lo lắng nếu bạn chưa từng nghe đến nó trước đây - chúng ta sẽ bắt đầu từ những điều cơ bản và dần dần nâng cao. Đến cuối bài hướng dẫn này, bạn sẽ có thể currying các hàm như một chuyên gia!

JavaScript - Currying

Currying là gì?

Trước khi chúng ta đi vào phần cách thực hiện, hãy hiểu xem currying thực sự là gì. Currying là một kỹ thuật trong lập trình hàm, trong đó chúng ta chuyển đổi một hàm nhận nhiều đối số thành một chuỗi các hàm, mỗi hàm nhận một đối số.

Hãy tưởng tượng bạn đang làm một sandwich. Thay vì đặt tất cả các nguyên liệu lại với nhau một lần, currying giống như thêm một nguyên liệu tại một thời điểm, từng bước một. Nó cho bạn nhiều sự kiểm soát và linh hoạt hơn trong việc xây dựng "sandwich hàm" của bạn.

Cách thực hiện Currying trong JavaScript

Bây giờ, hãy cùng nhìn vào cách chúng ta có thể thực hiện currying trong JavaScript. Chúng ta sẽ khám phá hai phương pháp chính: sử dụng closure và sử dụng phương thức bind().

Currying bằng cách sử dụng Closure

Closure trong JavaScript giống như những hộp ma thuật nhớ lại môi trường mà chúng được tạo ra. Chúng ta có thể sử dụng khả năng này để tạo ra các hàm curried. Hãy bắt đầu với một ví dụ đơn giản:

function curry(f) {
return function(a) {
return function(b) {
return f(a, b);
};
};
}

function sum(a, b) {
return a + b;
}

let curriedSum = curry(sum);

console.log(curriedSum(2)(3)); // Output: 5

Trong ví dụ này:

  1. curry là một hàm cao cấp nhận một hàm f làm đối số.
  2. Nó trả về một hàm mới nhận đối số đầu tiên a, mà lại trả về một hàm khác nhận đối số thứ hai b.
  3. Cuối cùng, hàm này gọi hàm gốc f với cả hai đối số.

Hãy phân tích từng bước:

  1. Chúng ta định nghĩa một hàm curry để chuyển đổi hàm thông thường thành hàm curried.
  2. Chúng ta có một hàm sum đơn giản để cộng hai số.
  3. Chúng ta tạo một curriedSum bằng cách truyền sum vào hàm curry.
  4. Khi chúng ta gọi curriedSum(2)(3), nó thực sự làm như sau:
  • curriedSum(2) trả về một hàm nhớ lại 2 làm đối số đầu tiên.
  • Chúng ta ngay lập tức gọi hàm trả về này với (3), hoàn thành phép toán.

Đ Cooler, phải không? Giống như chúng ta đang xây dựng gọi hàm của mình từng piece một!

Currying bằng cách sử dụng phương thức bind()

JavaScript cũng cung cấp cho chúng ta một phương thức nội tại gọi là bind() mà chúng ta có thể sử dụng cho currying. Phương thức bind() tạo ra một hàm mới mà khi gọi, có this được đặt thành một giá trị cung cấp, với một chuỗi các đối số trước bất kỳ đối số nào được cung cấp khi hàm mới được gọi.

Hãy xem cách chúng ta có thể sử dụng bind() cho currying:

function multiply(x, y) {
return x * y;
}

let multiplyByTwo = multiply.bind(this, 2);
console.log(multiplyByTwo(4)); // Output: 8

let multiplyByThree = multiply.bind(this, 3);
console.log(multiplyByThree(4)); // Output: 12

Trong ví dụ này:

  1. Chúng ta bắt đầu với một hàm multiply đơn giản nhận hai đối số.
  2. Chúng ta sử dụng bind() để tạo ra một hàm mới multiplyByTwo. Đối số đầu tiên 2 được đặt trước.
  3. Khi chúng ta gọi multiplyByTwo(4), nó thực chất đang gọi multiply(2, 4).
  4. Chúng ta làm tương tự để tạo ra multiplyByThree, đặt 3 làm đối số đầu tiên.

Phương thức bind() cho phép chúng ta "fix" một số đối số của một hàm, tạo ra một hàm mới với những đối số đó đã được đặt.

Các ứng dụng của Currying

Bây giờ chúng ta đã hiểu cách currying các hàm, hãy khám phá lý do tại sao chúng ta lại muốn làm điều này. Currying có một số ứng dụng thực tế trong JavaScript:

  1. Composition của hàm: Currying giúp dễ dàng hơn trong việc composition hàm, nơi đầu ra của một hàm trở thành đầu vào của hàm khác.

  2. Áp dụng một phần: Chúng ta có thể tạo ra các hàm chuyên dụng từ các hàm tổng quát hơn, như ví dụ multiplyByTwo.

  3. Tránh lặp lại: Khi bạn thấy mình gọi một hàm với một số đối số giống nhau nhiều lần, currying có thể giúp giảm thiểu sự lặp lại.

  4. Xử lý sự kiện: Trong phát triển frontend, currying có thể hữu ích cho việc xử lý sự kiện với các tham số bổ sung.

Hãy nhìn vào một ví dụ thực tế sử dụng currying cho xử lý sự kiện:

function handleClick(message, event) {
console.log(message, event.target);
}

let button = document.getElementById('myButton');
button.addEventListener('click', handleClick.bind(null, 'Button clicked:'));

Trong ví dụ này, chúng ta sử dụng currying để truyền một tham số bổ sung cho bộ xử lý sự kiện. Khi nút được nhấp, nó sẽ in ra "Button clicked:" theo sau là đối tượng sự kiện.

Các phương pháp Currying trong JavaScript

Dưới đây là bảng tóm tắt các phương pháp chúng ta đã thảo luận cho currying trong JavaScript:

Phương pháp Mô tả Ví dụ
Closure Sử dụng hàm lồng nhau để tạo hàm curried function curry(f) { return function(a) { return function(b) { return f(a, b); }; }; }
bind() Sử dụng phương thức bind() để đặt trước đối số let multiplyByTwo = multiply.bind(this, 2);

Kết luận

Chúc mừng! Bạn đã刚刚 bước vào thế giới của currying trong JavaScript. Nhớ rằng, như khi học bất kỳ khái niệm lập trình mới nào, thực hành là chìa khóa. Hãy thử tạo ra các hàm curried của riêng bạn và thử nghiệm với các trường hợp sử dụng khác nhau.

Currying có thể trông có vẻ trừu tượng ban đầu, nhưng khi bạn sử dụng nó nhiều hơn, bạn sẽ bắt đầu thấy nó làm cho mã của bạn linh hoạt và tái sử dụng hơn. Nó giống như học cách sử dụng một công cụ mới trong bộ công cụ lập trình của bạn - ban đầu có thể cảm thấy khó khăn, nhưng sớm bạn sẽ tự hỏi làm thế nào bạn từng lập trình mà không có nó!

Tiếp tục lập trình, tiếp tục học hỏi, và quan trọng nhất, hãy vui vẻ! JavaScript là một sân chơi của các khả năng, và currying chỉ là một trong nhiều tính năng thú vị đang chờ bạn khám phá.

Credits: Image by storyset