Rekursi ekor ialah teknik pengoptimuman algoritma yang boleh mengubah algoritma rekursif kepada algoritma berulang yang lebih cekap. Berbanding dengan rekursi konvensional, rekursi ekor boleh mengurangkan kedalaman tindanan, dengan itu mengelakkan masalah seperti limpahan tindanan. Walau bagaimanapun, JavaScript tidak menyokong rekursi ekor, yang merupakan masalah untuk banyak amalan kejuruteraan.
Mengapa JavaScript tidak menyokong rekursi ekor?
Dalam banyak bahasa pengaturcaraan, operasi rekursif ekor dioptimumkan secara automatik ke dalam operasi berulang oleh penterjemah atau pengkompil. Ini dicapai melalui teknik pengoptimuman tertentu. Walau bagaimanapun, JavaScript tidak menyokong pengoptimuman ini dan menukar rekursi ekor kepada operasi lelaran memerlukan menulis kod lelaran secara manual.
Enjin JavaScript bergantung pada kod skrip yang ditulis oleh pembangun JavaScript dan menggunakan mekanisme panggilan dan penghurai sintaks yang dibangunkan oleh pembangun JavaScript untuk menghuraikan kod. Oleh kerana model tindanan yang digunakan oleh enjin JavaScript adalah berbeza daripada model tindanan yang biasa dalam bahasa lain, adalah sangat sukar untuk melaksanakan pengoptimuman rekursi ekor.
Panggilan ekor dan rekursi ekor
Apabila mempelajari JavaScript, anda mungkin sering mendengar konsep "pengoptimuman panggilan ekor" dan "rekursi ekor" Walaupun kedua-dua konsep ini sangat serupa, Tetapi ia berbeza .
Panggilan ekor bermaksud apabila pernyataan terakhir fungsi ialah panggilan fungsi, panggilan fungsi ini boleh dioptimumkan oleh pengkompil untuk "melompat" ke sub-fungsi untuk pelaksanaan, yang boleh mengelakkan daripada mencipta berbilang bingkai overhed, dengan itu mengurangkan penggunaan memori, yang juga merupakan teknik pengoptimuman.
Rekursi ekor ialah sejenis panggilan ekor yang istimewa. Rekursi ialah apabila fungsi memanggil dirinya sendiri semasa pelaksanaan. Jika rekursi adalah rekursi ekor, maka panggilan rekursif ini mestilah pernyataan terakhir fungsi, iaitu, tiada operasi tambahan diperlukan Ia hanya perlu menukar panggilan fungsi dan pemindahan parameter ke dalam arahan, dan kemudian melompat ke permulaan daripada fungsi tersebut.
Contoh rekursi ekor
Berikut ialah pelaksanaan rekursif klasik bagi faktorial:
function factorial(n) { if (n === 1) return 1; return n * factorial(n - 1); }
Pada masa ini, kami akan memanggilnya secara rekursif n kali, dan ia akan rekod panggilan be n fungsi ditinggalkan pada timbunan. Apabila nombor faktor adalah besar, anda akan menghadapi masalah limpahan timbunan.
Ubah suai kod di atas untuk melaksanakan rekursi ekor:
function factorial(n, sum = 1) { if (n === 1) return sum; return factorial(n - 1, n * sum); }
Dalam fungsi ini, pembolehubah jumlah merekodkan hasil perantaraan pemfaktoran boleh dikira dengan membandingkannya dengan nombor sebelumnya untuk mengira dengan mendarab, tidak perlu mengira pemfaktoran setiap nombor dan kemudian mendarabnya. Kami menghantar hasil perantaraan ini sebagai parameter kepada rekursi seterusnya, dengan itu mencapai pengoptimuman rekursi ekor.
Kesimpulan
Enjin JavaScript tidak menyokong pengoptimuman rekursi ekor, yang mempunyai had tertentu untuk pembangun. Pembangun mesti menukar secara manual kepada algoritma berulang, atau melaksanakan rekursi ekor dalam bahasa lain. Jika anda perlu menggunakan rekursi ekor dalam kerja sebenar, anda boleh menggunakan penyelesaian seperti mensimulasikan timbunan panggilan secara manual untuk mencapai kesannya.
Atas ialah kandungan terperinci Adakah javascript tidak menyokong rekursi ekor?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!