2009-04-06 29 views
5

Tôi đã đọc hùng biện JavaScript và tôi đã xem qua ví dụ này cho các câu đố:Một giải thích rõ ràng hơn cho đệ quy và luồng thực thi trong JavaScript?

Hãy xem xét câu đố này: Bằng cách bắt đầu từ số 1 và lặp đi lặp lại hoặc thêm 5 hoặc nhân với 3, một lượng vô hạn của số mới có thể được sản xuất . Làm thế nào bạn sẽ viết một hàm , với một số, cố gắng để tìm một chuỗi các bổ sung và phép nhân tạo ra số đó?

Dưới đây là đoạn code cho các giải pháp:

function findSequence(goal) { 
    function find(start, history) { 
    if (start == goal) 
     return history; 
    else if (start > goal) 
     return null; 
    else 
     return find(start + 5, "(" + history + " + 5)") || 
      find(start * 3, "(" + history + " * 3)"); 
    } 
    return find(1, "1"); 
} 

print(findSequence(24)); 

Có thể ai đó làm sáng tỏ cách DOD tìm được thực thi nếu nó không có một giá trị cho các đối số bắt đầu và mục tiêu? Cũng như thế nào sự đệ quy xảy ra?

+0

Xem thêm [Cách đệ quy này hoạt động?] (Http://stackoverflow.com/q/15712230/1048572) và [JavaScript đệ quy từ Eloquent Javascript] (http://stackoverflow.com/q/26205376/1048572) – Bergi

Trả lời

5

Nhưng findkhông được thực hiện mà không có một giá trị cho startgoal. Nó được thực hiện lần đầu tiên với giá trị 1 cho start và giá trị duy nhất cho goal24.

Có thể bạn đang bối rối về thứ tự hoạt động. Ở đó, chúng tôi thấy khai báo của một hàm, findSequence. Trong quá trình khai báo, không có mã nào được thực hiện. Hàm findSequence chỉ được thực hiện sau, trên dòng cuối cùng, nơi kết quả thực thi hàm được in ra.

Trong tuyên bố findSequence, có một tuyên bố về một chức năng khác, find. Một lần nữa, nó không được thực hiện cho đến sau này. Hàm findSequence chỉ có một dòng mã có thể thực thi, mã gọi find(1, "1"). Việc thực hiện một dòng đó sẽ kích hoạt việc thực thi find một số lần, đệ quy.Hàm find làm cho tham chiếu đến goal; khi trình thông dịch Javascript thực thi mã, goal luôn đề cập đến tham số của findSequence và vì trong ví dụ này, findSequence chỉ được gọi một lần, goal luôn có cùng giá trị, 24.

Bạn sẽ có thể thấy nơi xảy ra sự đệ quy. Nếu start bằng goal, thì chức năng sẽ dừng; nó trả về lịch sử về cách nó đến con số đó. Nếu start lớn hơn goal, thì nó trả về null, cho biết rằng đường dẫn đó không phải là đường dẫn đến số mục tiêu. Nếu start vẫn nhỏ hơn goal, khi đó hàm cố gắng gọi chính nó là với giá trị bắt đầu cộng 5. Nếu trả về giá trị không null thì đó là giá trị được trả lại. Nếu không, nó cố gắng nhân với 3 và trả về giá trị lịch sử đó thay thế.

Lưu ý rằng mặc dù mã này có thể trả về nhiều số, nhưng nó không thể trả lại tất cả số. Nếu mục tiêu là 2, ví dụ: findSequence sẽ trả về null vì không có cách nào để bắt đầu tại 1 và truy cập 2 bằng cách thêm 5 hoặc nhân với 3.

+0

Điều đó xóa những điều lên! Cảm ơn lời giải thích :) – ajushi

+0

'tìm lại (bắt đầu + 5," ("+ lịch sử +" + 5) ") || tìm (bắt đầu * 3, "(" + lịch sử + "* 3)") ', dòng này hoạt động như thế nào? – user7104874

1

Khi tìm thấy được gọi bên trong findSequence, nó có quyền truy cập vào biến mục tiêu được đặt trong định nghĩa của findSequence. Một ví dụ đơn giản của việc này là:

function outerFunction() { 
    var a = 2; 
    function innerFunction() { 
    alert(a); 
    } 
    innerFunction(); 
} 
outerFunction(); 

Biến bắt đầu được định nghĩa khi nó:

return find(1, "1"); 

có hiệu quả có một biến ban đầu bắt đầu 1, mục tiêu biến 24, và một lịch sử của "1 "trên thẻ đầu tiên.

EDIT: Mỗi nhận xét của Rob, đóng cửa không thực sự gây ra điều này ở đây, vì find() không được thực thi ngoài findSequence(), phạm vi đang gây ra mục tiêu được tìm thấy.

+0

Điều đó thực sự có liên quan gì đến việc đóng cửa không? Tôi nghĩ rằng nó chỉ là phạm vi phân giải bình thường: "tìm" không có "mục tiêu" định danh của riêng nó, do đó, nó giải quyết cho một trong phạm vi kèm theo. Các đóng cửa sẽ chỉ áp dụng nếu "tìm" được gọi gián tiếp sau khi "findSequence" đã trả về. –

+0

có thực sự, đó là sự thật, nó không phải là một vấn đề đóng cửa, chỉ là một vấn đề phạm vi –

0

Nếu tôi hiểu chính xác câu hỏi của bạn: Dòng cuối cùng của mã đang gọi hàm findSequence(), với mục tiêu 24. Trong hàm findSequence() có hàm find(), được xác định và sau đó được gọi trong return cho findSequence, với khởi đầu bằng 1, và lịch sử bằng 1.

Các vấn đề liên quan