Không dễ lập trình chức năng trong JavaScript


Đỗ Bình Ðịnh
1 năm trước
Hữu ích 7 Chia sẻ Viết bình luận 0
Đã xem 5204

Giới thiệu

JavaScript cho phép hoạt động trên các mảng theo cách chức năng, ví dụ như sử dụng filterhoặc các maphàm. Là một đối số cho các hàm này, chúng ta có thể truyền các biểu thức lambda hoặc tham chiếu hàm. Có sự khác biệt giữa chúng? Câu trả lời là có.

Vấn đề là gì?

Trong dự án của chúng tôi, chúng tôi đang xây dựng một ánh xạ bằng cách sử dụng  String.fromCharCodechức năng. Để đơn giản hóa việc sử dụng chức năng này, mã của tôi trông tương tự như:

[66, 67, 68].map(v => String.fromCharCode(v))

Khi chúng tôi chạy mã này với nút chúng tôi nhận được [ 'B', 'C', 'D' ], nhưng khi chúng tôi quyết định cấu trúc lại nó để sử dụng tham chiếu hàm thì kết quả sẽ khác:

> [66, 67, 68].map(String.fromCharCode)
[ 'B\u0000\u0000', 'C\u0001\u0000', 'D\u0002\u0000' ]

Chuyện gì đã xảy ra?

Để tìm lý do cho hành vi này, trước tiên chúng ta hãy chơi với chức năng String.fromCharCode:

> String.fromCharCode(66)
'B'
> String.fromCharCode([66, 67, 68])
'\u0000'
> String.fromCharCode(66, 67, 68)
'BCD'

String.fromCharCode giao dịch với nhiều loại và số lượng đối số.

Bây giờ, hãy kiểm tra chức năng map:

> [66, 67, 68].map(v => v)
[ 66, 67, 68 ]
> [66, 67, 68].map((v, u) => [v, u])
[ [ 66, 0 ], [ 67, 1 ], [ 68, 2 ] ]
> [66, 67, 68].map((v, u, w) => [v, u, w])
[ [ 66, 0, [ 66, 67, 68 ] ],
  [ 67, 1, [ 66, 67, 68 ] ],
  [ 68, 2, [ 66, 67, 68 ] ] ]

map, giống như nhiều hàm mảng khác, luôn truyền ba đối số cho hàm . Đầu tiên là giá trị hiện tại, thứ hai là chỉ số của giá trị hiện tại và thứ ba là toàn bộ mảng.

Nó có nghĩa là việc chuyển String.fromCharCodeđến  mapchức năng dưới mui xe trông như thế này:

> [66, 67, 68].map((v, u, w) => String.fromCharCode(v, u, w))
[ 'B\u0000\u0000', 'C\u0001\u0000', 'D\u0002\u0000' ]

Và điều này tương đương với ví dụ ban đầu.

Phần kết luận

Chúng ta phải cẩn thận khi chúng ta muốn sử dụng một hàm có thể có nhiều hơn một đối số, nhưng chúng ta chỉ muốn truyền giá trị. Chúng ta phải truyền hàm dưới dạng biểu thức lambda:

> [66, 67, 68].map(v => String.fromCharCode(v))
[ 'B', 'C', 'D' ]

hoặc tạo một hàm khác đảm bảo rằng chỉ đối số đầu tiên sẽ được chuyển đến hàm mong muốn:

> const useOnlyValue = f => v => f(v);
undefined
> [66, 67, 68].map(useOnlyValue(String.fromCharCode))
[ 'B', 'C', 'D' ]
Hữu ích 7 Chia sẻ Viết bình luận 0
Đã xem 5204