Hàm đệ quy javascript es6

Đây là bài #59 của loạt bài, chuyên khám phá JavaScript và các thành phần xây dựng của nó. Trong quá trình xác định và mô tả các yếu tố cốt lõi, chúng tôi cũng chia sẻ một số quy tắc chung mà chúng tôi sử dụng khi xây dựng SessionStack, một ứng dụng JavaScript cần mạnh mẽ và có hiệu suất cao để giúp các công ty tối ưu hóa trải nghiệm kỹ thuật số của người dùng của họ

Giới thiệu

Bạn đã bao giờ phải đối mặt với thách thức giải quyết một nhiệm vụ mà dường như giải pháp của nhiệm vụ ban đầu dẫn đến một nhiệm vụ tương tự mới chưa?

Đôi khi, điều này có thể tiếp tục và tạo ra các tác vụ tương tự nhỏ hơn cho đến vô cùng ngoại trừ bị chấm dứt bởi một số lệnh. Lưu ý rằng nhiệm vụ loại bỏ nhiệm vụ này của bạn làm cho cơ sở mã của bạn trở nên khổng lồ, cồng kềnh và khó đọc. Làm thế nào sau đó bạn có thể đi về điều này?

Trong phần này, chúng ta sẽ xem đệ quy là gì, tại sao nó được sử dụng trong phát triển phần mềm, cách hoạt động của đệ quy trong Javascript và khi nào thì không nên sử dụng đệ quy. Ngoài ra, chúng tôi sẽ xem xét một số ví dụ về đệ quy trong các trường hợp sử dụng của JavaScript và sau đó xem xét sự khác biệt của đệ quy với các hàm Vòng lặp phổ biến

đệ quy là gì

Đệ quy là một mẫu hoặc khái niệm lập trình được nhúng trong nhiều ngôn ngữ lập trình và JavaScript không bị loại bỏ. Đây là một tính năng được sử dụng để tạo một hàm liên tục gọi chính nó nhưng với đầu vào nhỏ hơn mỗi lần liên tiếp cho đến khi đạt được kết quả mong muốn của mã ngay từ đầu

Điều này có xu hướng giữ một bảng mã rất rõ ràng trong khi cung cấp giải pháp cho nhiều tác vụ có cấu trúc tương tự. Hàm hoạt động dựa trên khái niệm đệ quy được gọi là hàm đệ quy

Dưới đây, là cú pháp của một hàm đệ quy

Trong ví dụ trên, chúng tôi giả sử hàm đệ quy là recursion(). Đây là định dạng đơn giản nhất mà bất kỳ hàm đệ quy nào cũng sẽ sử dụng. Ngoài ra, recursion() thứ hai nằm ngoài khối chức năng chỉ gọi toàn bộ chức năng để thực thi

Tại sao sử dụng đệ quy

Một yếu tố chính làm cho đệ quy trở nên nổi bật là nó thực hiện các tác vụ phức tạp trong một vài dòng mã trái ngược với khi không sử dụng đệ quy. Và điều này làm cho cơ sở mã trông đơn giản và thanh lịch, do đó tiết kiệm thời gian và cho phép hoàn thành công việc nhanh chóng. Đồng thời loại bỏ cơ sở mã lớn và cồng kềnh

Chẳng hạn, chúng ta có thể viết một hàm đệ quy để tính các số giai thừa như trong ví dụ bên dưới

Mặc dù ví dụ này có thể được sao chép bằng các vòng lặp, nhưng nó có thể gặp khó khăn khi liên quan đến dữ liệu lớn. Điều này là do ngăn xếp được sử dụng để lưu trữ các biến trong các lần truy cập chứ không phải trong các vòng lặp

Cách đệ quy JavaScript hoạt động

Đệ quy trong Javascript hoạt động chính xác như trong các ngôn ngữ khác. Để hiểu rõ hơn về cách thức hoạt động của đệ quy, chúng ta hãy xem cấu trúc cú pháp của hàm đệ quy ở trên. Có ba phần cơ bản của cú pháp đó mà bất kỳ ai viết hàm đệ quy đều phải cung cấp. Chúng như sau

  • Khai báo hàm
  • trường hợp cơ sở
  • Lệnh gọi đệ quy

Khai báo hàm

Đây là phần đã khai báo hàm đệ quy dự định. Nó được thực hiện giống như cách khai báo bình thường của một hàm mới được thực hiện trong JavaScript. Hàm đã khai báo có thể nhận đối số

trường hợp cơ sở

Đây là nền tảng của mọi hàm đệ quy. Nó là đơn vị cơ bản của vấn đề ban đầu được giải quyết khi vấn đề được chia thành các nhiệm vụ nhỏ hơn

Nó cũng có thể được xem là lệnh có khả năng kết thúc quá trình đệ quy nếu điều kiện đặt là đúng. Một số trường hợp cơ sở có thể được bao bọc trong một if….else statement

Do đó, một ví dụ dưới đây

Khi điều kiện cơ sở đã nêu được đáp ứng, lệnh với câu lệnh trả về được thực thi

Lệnh gọi đệ quy

Lệnh hoặc đối số này chịu trách nhiệm kích hoạt các cuộc gọi đệ quy. Ngoài ra, đây là lệnh giải quyết bản chất chính của vấn đề bạn đang cố gắng giải quyết. Đó là bất kỳ mã JavaScript chung nào, tùy thuộc vào mục tiêu mà nhà phát triển muốn đạt được

Khi tất cả những thứ này đã sẵn sàng, bây giờ bạn có thể gọi hàm để thực thi bằng cách sử dụng hàm recursion(). Chức năng đệ quy đầy đủ bây giờ trông như thế này;

Ví dụ về các trường hợp sử dụng đệ quy

Đã hiểu cách đệ quy hoạt động trong JavaScript trong phần trước, bây giờ chúng ta sẽ xem xét một số trường hợp sử dụng đệ quy. Điều này cũng sẽ cho phép chúng ta hiểu sâu hơn về khả năng sử dụng của đệ quy

ví dụ 1. đếm ngược số

Giả sử bạn định viết một chương trình sẽ đếm ngược các số theo thứ tự giảm dần, ví dụ: từ 10 xuống 1. Đầu ra dự định phải giống như 10,9,8,7,6,5,4,3,2,1

Viết một chương trình sẽ giảm giá trị theo cách thủ công ở mỗi bước và thời gian sẽ trông cồng kềnh, nhưng đệ quy có xu hướng đạt được điều đó với ít dòng mã hơn

Chúng ta hãy xem mã này dưới đây

Bây giờ chúng ta hãy mổ xẻ đoạn mã trên đối với các phần của cú pháp hàm đệ quy

Đoạn mã trên khai báo hàm descendNum nhận đối số StartNum mô tả số bắt đầu đếm ngược. Dòng mã này cũng in ra số bắt đầu

let NextNum = StartNum — 1;

Dòng mã này là lệnh gọi đệ quy. Nó khai báo một biến NextNum là phép trừ 1 từ số bắt đầu, do đó tạo ra mức giảm mong muốn

Khối mã này xảy ra là trường hợp cơ bản. Việc giảm giá trị của số bắt đầu chỉ có thể vượt qua nếu đáp ứng điều kiện NextNum > 0

ví dụ 2. đảo ngược chuỗi

Giả sử bạn muốn viết lại một chuỗi từ ký tự cuối cùng sang ký tự đầu tiên, có thể sử dụng đệ quy để thực hiện việc đó một cách liền mạch. Đảo ngược chuỗi này có thể hữu ích trong mã hóa mật khẩu và tương tự

Hãy nhìn vào đoạn mã dưới đây

Đầu ra trở thành; . Xem xét những gì xảy ra trong khối mã khi chạm vào trang điểm hàm đệ quy. recursion()0 khai báo hàm đệ quy và nhận đối số recursion()1

Sau đó, trường hợp cơ sở được hình thành. Nó giới thiệu độ dài của thuộc tính chuỗi làm cơ sở cho việc đảo ngược chuỗi. Nếu độ dài văn bản bằng 1, nó sẽ trả về vì nếu không, lệnh gọi đệ quy có hiệu lực như được thấy trong mã bên dưới

Tiếp theo là lệnh gọi đệ quy xác định tác vụ đảo ngược chuỗi và sau đó là lệnh gọi hàm kích hoạt hàm để đạt được đầu ra cần thiết như được thấy trong mã bên dưới

ví dụ 3. Tìm lũy thừa của một số

Giả sử bạn muốn viết một chương trình đưa ra cấp số nhân của một số đã cho, điều này có thể được thực hiện dễ dàng với đệ quy. Xem mã dưới đây

Ở đây, hàm đệ quy được khai báo bởi recursion()2 nhận các đối số recursion()3 và recursion()4. Nó như sau;

Sau đó, trường hợp cơ sở được phát triển. Điều kiện để hàm đệ quy này là nếu lũy thừa bằng 1 thì chương trình in ra số cần nâng lên lũy thừa nếu không thì thực hiện lệnh gọi hàm đệ quy. Trường hợp cơ bản như sau

Sau đó, cuộc gọi đệ quy thực hiện nhiệm vụ theo cấp số nhân thực tế. Nó như sau

recursion()5 làm toán thực sự. Lý do cho đối số recursion()6 là trong các phép toán đơn giản, recursion()3 được giả định bằng với recursion()8

Do đó, lời gọi đệ quy như đã nêu trong ví dụ trở thành recursion()9

Đệ quy Vs Iterators

Người ta có thể thắc mắc rằng hầu hết những điều này có thể đạt được bằng cách sử dụng trình vòng lặp, vậy tại sao lại sử dụng Đệ quy?

câu trả lời là đây

  • Người ta đã quan sát thấy rằng đệ quy dễ viết hơn và đơn giản hơn các trình vòng lặp
  • Nó cũng ít cồng kềnh hơn so với các vòng do đó làm cho nó thanh lịch hơn
  • Với đệ quy, điều quan trọng nhất là điều kiện kết thúc hàm điều hành chứ không phải số lần nó phải chạy. Nhưng điều này không chắc chắn đối với iterators

Chúng ta hãy xem xét sự khác biệt giữa hai phương pháp này bằng cách xem xét một ví dụ khác về một tác vụ được thực hiện bằng hai phương pháp

Chúng ta sẽ viết chương trình tìm tổng các số trong một khoảng cho trước

Sử dụng vòng lặp

Sử dụng đệ quy

Đầu ra vẫn giữ nguyên

Khi nào không sử dụng Đệ quy

Mặc dù đệ quy là một mô hình tuyệt vời để viết mã sạch hơn mà các nhà phát triển có thể dễ dàng sửa lỗi, nhưng nó đặt ra một số vấn đề. Chẳng hạn, đệ quy gây ra các vấn đề về hiệu năng trong các ứng dụng. Điều này là do thuật toán chậm hơn

Ví dụ: khi bạn chạy chương trình theo cách đệ quy trong một thời gian, hệ thống có xu hướng bị treo trong một thời gian hoặc chậm lại khi phân tích dữ liệu. Do đó, không nên sử dụng đệ quy trong các chương trình nhỏ vì nó quá mức cần thiết. Thay vào đó, tốt hơn là sử dụng các trình vòng lặp trong các chương trình nhỏ hơn không liên quan đến việc phân tích dữ liệu lớn

Phần kết luận

Đệ quy JavaScript là tất cả về việc viết một cơ sở mã sạch hơn và ít cồng kềnh hơn nhưng vẫn cung cấp các giải pháp cho các tác vụ đa luồng. Trong javaScript, hàm đệ quy của bạn đã sẵn sàng để được thực thi bằng cách khai báo hàm với trường hợp cơ sở thích hợp và các lệnh bước đệ quy

Mặc dù đệ quy là mẫu được đề xuất để viết mã sạch vì nó giúp chúng ta giải quyết các vấn đề phức tạp trong một vài dòng mã, nhưng việc sử dụng đệ quy có thể gây ra chi phí — nó có thể dẫn đến các vấn đề về hiệu suất

Vì vậy, nếu bạn chọn sử dụng đệ quy, bạn nên theo dõi chặt chẽ cách nó tác động đến hiệu suất mã của bạn và làm cho sản phẩm của bạn cung cấp trải nghiệm tốt hơn cho người dùng của bạn

Ngay cả khi bạn cảm thấy rằng các quyết định đúng đắn đã được đưa ra, bạn vẫn luôn cần phải xác minh rằng điều này thực sự đúng và người dùng của bạn có trải nghiệm tuyệt vời với sản phẩm của bạn

Đối với chúng tôi tại SessionStack, việc tối ưu hóa từng đoạn mã của chúng tôi là rất quan trọng

Lý do là thư viện của chúng tôi được tích hợp vào các ứng dụng web và thu thập dữ liệu từ các phiên của người dùng, chẳng hạn như sự kiện của người dùng, thay đổi DOM, dữ liệu mạng, ngoại lệ, thông báo gỡ lỗi, v.v. Việc thu thập dữ liệu này mà không gây ra bất kỳ tác động nào đến hiệu suất là một thách thức mà chúng tôi đã giải quyết thành công

Sau đó, dữ liệu này được xử lý và cho phép bạn phát lại hành trình của người dùng dưới dạng video để tối ưu hóa quy trình làm việc của sản phẩm, tái tạo lỗi hoặc xem người dùng gặp khó khăn ở đâu