Gần đây, tôi nhận thấy mình đang lập trình nhiều chức năng hơn với JavaScript – đặc biệt là trong những ngày gần đây với dự án WinJS mà tôi đang thực hiện và việc sử dụng nhiều lời hứa mà nó khuyến khích. Điều này khiến tôi cảm thấy hơi kỳ lạ khi xem xét niềm đam mê hiện tại của tôi là xây dựng các ứng dụng JavaScript hướng đối tượng với Backbone. Nhưng đồng thời, có điều gì đó rất tự nhiên về phong cách chức năng trong JavaScript. Có rất nhiều điều thú vị mà bạn có thể làm với phong cách chức năng trong JavaScript và tôi khuyến khích bạn khám phá nó
Một trong những công cụ mà tôi đã chọn trong quá trình khám phá kiểu chức năng là ứng dụng chức năng một phần, theo Wikipedia, cho phép chúng tôi cung cấp “một số đối số cho một chức năng, tạo ra một chức năng khác nhỏ hơn. ” [“Arity” là một từ ưa thích để chỉ số lượng đối số của một hàm]. Lưu ý rằng ứng dụng chức năng một phần không giống như "cà ri". Hai ý tưởng có thể giống nhau, nhưng chúng chắc chắn là khác nhau và hai thuật ngữ không nên thay thế cho nhau
Ứng dụng hàm một phần thực sự có nghĩa là chúng ta có thể lấy một hàm có 2 tham số và tạo một hàm được áp dụng một phần có tham số đầu tiên là cố định. Bản thân kết quả là một hàm chỉ mong đợi một tham số. Khi gọi chức năng cuối cùng đó, kết quả của chức năng ban đầu được tạo ra
Một ví dụ
Ở đây, chúng tôi đang sử dụng tiêu chuẩn ECMAScript 5 của chức năng “liên kết” để thực hiện ứng dụng một phần. Chức năng “liên kết” phục vụ hai mục đích. 1] để liên kết ngữ cảnh của hàm [đối số [đối số này]] và 2] để tạo một hàm được áp dụng một phần
Kết quả cuối cùng, khi gọi hàm "một phần", là những gì bạn mong muốn nhận được bằng cách gọi hàm ban đầu với hai tham số. Điều này có thể được sử dụng nhiều lần, trên bất kỳ số lượng tham số nào. Bạn có thể cung cấp một hoặc nhiều đối số để liên kết với hàm được áp dụng một phần của mình và bạn cũng có thể áp dụng một phần hàm được áp dụng một phần. Tất nhiên, điều này có thể hơi lố bịch sau một thời gian, nhưng vẫn có thể thực hiện được
Cách cơ bản nhất để đưa một phần ứng dụng vào mã của bạn là viết cho các trình duyệt và thời gian chạy [như NodeJS và WinRT] hỗ trợ ECMAScript-5
[Ghi chú bên lề. Vì tôi đang làm việc với WinJS và WinRT trong thời gian chạy Windows 8, nên tôi phải sử dụng ECMAScript 5 thô trong JavaScript của mình. IE10 thực hiện rất tốt việc triển khai tiêu chuẩn này và thật sự rất vui khi viết các ứng dụng cho trình duyệt này và thời gian chạy WinRT. Lợi ích bổ sung của việc không phải lo lắng về khả năng tương thích giữa các trình duyệt khi xây dựng ứng dụng WinJS cũng thực sự mới mẻ. ]
Nhưng ngay cả khi bạn không sử dụng trình duyệt hoặc thời gian chạy hỗ trợ các tiêu chuẩn ECMAScript-5 và chức năng “liên kết”, ứng dụng một phần vẫn dễ thực hiện. Viết một hàm để tự làm việc đó không tốn nhiều công sức và có rất nhiều cách triển khai có sẵn để sử dụng – như cách triển khai này của John Resig
Bây giờ bạn có thể không muốn đi và sửa đổi nguyên mẫu JavaScript “Chức năng” cốt lõi để thêm cái này [cá nhân tôi sẽ không làm]. Nhưng đừng lo, bạn có thể dễ dàng sửa đổi nó để nó hoạt động như một lời gọi hàm riêng biệt. Hoặc, bạn có thể sử dụng thư viện như Underscore. js, cung cấp một phần ứng dụng thông qua chức năng “liên kết” trên chính nó thay vì sửa đổi Nguyên mẫu chức năng
Có lẽ có hàng ngàn triển khai khác về điều này xung quanh. Tôi chỉ liệt kê hai điều này vì mục đích ngắn gọn trong bài đăng trên blog này
Một trường hợp sử dụng cho điều này
Tôi đã biết về ứng dụng chức năng một phần từ khá lâu rồi. Nhưng tôi chưa bao giờ có lý do để sử dụng nó và không bao giờ hiểu tại sao nó lại hữu ích hoặc trong những tình huống nào thì nó có thể là một ý tưởng hay. Nó chỉ giống như một bài tập học thuật đối với tôi. Tuy nhiên, trong ứng dụng WinJS/WinRT mà tôi đang xây dựng với nhóm MS P&P, tôi có thể đã tìm thấy một kịch bản hợp lý và tạo ra một biểu thức mã rõ ràng hơn nhiều so với việc không sử dụng nó
Đây là một số mã mà @bennage và tôi đã viết cho ứng dụng WinJS/WinRT mẫu mà chúng tôi đang xây dựng
Nó không quá tệ. Trên thực tế, nó khá ngắn gọn và dễ đọc. Nó sử dụng rất nhiều lời hứa và xâu chuỗi chúng lại với nhau. Mỗi lệnh gọi hàm trả về một lời hứa, điều này tạo điều kiện thuận lợi cho các lệnh gọi “then” được xâu chuỗi. Ngoại trừ có một cuộc gọi ở giữa nơi một hàm nội tuyến được cung cấp để nhận tham số thứ hai được truyền cho hàm thông qua một bao đóng. Tôi muốn xem cần làm gì để biến chức năng nội tuyến này biến mất và ứng dụng một phần đã giải quyết vấn đề đó cho tôi
Trong phiên bản này, chức năng nội tuyến đã bị loại bỏ và một biến cục bộ đã được cung cấp ở vị trí của nó. Biến cục bộ đó là một hàm được áp dụng một phần, sử dụng hàm “liên kết” của ECMAScript-5. Tôi áp dụng tham số đầu tiên cho lệnh gọi hàm thực tế và hàm đó trả về một hàm hiện chỉ cần một tham số. Vì tham số xuất phát từ lệnh gọi “then” trong chuỗi lời hứa là tham số chính xác mà hàm được áp dụng một phần này cần, nên tôi có thể cung cấp hàm được áp dụng một phần này cho lệnh gọi “then” và mọi thứ sẽ hoạt động như mong đợi
Không, thực sự. Một trường hợp sử dụng thực tế cho điều này?
Ok, đây là một ví dụ khá tầm thường và có thể dễ dàng bị tranh cãi là không cần thiết. Mã ban đầu không tệ lắm và có thể dễ hiểu hơn đối với một số người. Nhưng kết quả cuối cùng của những câu nói “thì” được xâu chuỗi lại có một vẻ đẹp và sự sang trọng nhất định mà tôi yêu thích. Nó có một phong cách và quy trình chức năng riêng biệt giúp tôi rất dễ đọc, như thể tôi đang xem một biểu đồ trình tự cho mã của mình – và tôi không thể không yêu thích điều đó