2017-08-15 17 views
5

Tôi vấp vào generator functions on MDN và những gì tôi bối rối là ví dụ sau:Tại sao tuyên bố lợi nhuận của một hàm trình tạo javascript trả về các tham số của .next()?

function* logGenerator() { 
    console.log(yield); 
    console.log(yield); 
    console.log(yield); 
} 

var gen = logGenerator(); 

// the first call of next executes from the start of the function 
// until the first yield statement 
gen.next(); 
gen.next('pretzel'); // pretzel 
gen.next('california'); // california 
gen.next('mayonnaise'); // mayonnaise 

Những gì tôi không hiểu là tại sao báo cáo kết quả yield đó là lập luận của console.log trả về tham số truyền cho phương thức .next() của máy phát điện . Điều này có xảy ra do một số trống rỗng yield phải trả lại giá trị của tham số đầu tiên của phương thức .next()?

Tôi cũng đã thử một số ví dụ khác, mà dường như để xác nhận tuyên bố trên như:

gen.next(1,2,3); // the printed value is 1, the 2 and 3 are ignored 
// and the actual yielded value is undefined 

Ngoài ra là có một cách để truy cập vào các thông số hơn nữa của phương pháp .next() bên trong cơ thể của hàm máy phát điện?

Một điều khác tôi nhận thấy là, trong khi tuyên bố lợi nhuận trả về các giá trị này cho console.log chúng thực sự không được tạo ra như đầu ra của trình tạo. Tôi phải nói rằng tôi thấy nó rất khó hiểu.

+0

... bởi vì đó là điều đáng lẽ phải xảy ra? Tại sao điều này làm bạn bối rối? – user2357112

+0

Đó chỉ là những gì biểu thức 'yield' đánh giá. – user2357112

+0

@ user2357112 nó gây nhầm lẫn cho tôi vì tôi không thấy thông số được tham chiếu trong mã ở trên. Có đọc các liên kết từ các câu trả lời nó tất cả có ý nghĩa bây giờ, nhưng khi tôi lần đầu tiên nhìn thấy nó, tôi đã không hiểu nó. Một lưu ý phụ, bạn cũng có thể làm những việc như 'function * x() {yield yield yield;}' – Jakub

Trả lời

2

Câu hỏi hay. Tôi nghĩ đọc MDN theo phương pháp .next() hữu ích nhất. Bạn có thể xác định giá trị mà bạn muốn vượt qua trong các chức năng máy phát điện riêng của mình (ví dụ yield 1) hoặc vượt qua các giá trị thông qua next() bằng cách nói một cái gì đó giống như gen.next(1)

Nhà điều hành next() tự trả về một đối tượng, với value và một boolean gắn liền với nó của done để biểu thị cho dù toàn bộ chức năng của máy phát đã kết thúc chưa. Và có hai cách để truy cập/vượt qua nó value.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/next

0

This makes it quite clear:

[rv] = năng suất [biểu hiện];

biểu thị Xác định giá trị trả về từ hàm tạo thông qua giao thức lặp. Nếu bỏ qua, undefined được trả về để thay thế.

rv Trả về giá trị tùy chọn được chuyển đến phương thức next() của trình tạo để tiếp tục thực thi.

Về cơ bản, bạn đang in ra thông số bạn đã gửi qua để tiếp tục thực hiện.

1

Sự rắc rối xuất phát từ thực tế là yieldnext có cú pháp khác nhau, trong khi họ thực sự làm điều tương tự. Máy phát và người gọi của nó là đối xứng (đó là lý do tại sao chúng được gọi là "đồng" -routines và không phải là "phụ" -routines). Cả hai chức năng có thể được coi là kết nối bởi một kênh truyền thông, và có thể làm công việc hoặc giấc ngủ của họ chờ đợi một tin nhắn đến trong kênh. Sự khác biệt duy nhất là máy phát ban đầu ngủ (tức là, có một lệnh "lắng nghe" ngầm định ở đầu nó), trong khi người gọi ban đầu tỉnh táo.

Cả yieldnext làm tương tự điều ba điều:

  • viết đối số của nó vào kênh
  • mùa thu ngủ và lắng nghe một tin nhắn gửi đến
  • phát ra thông điệp đến như giá trị của nó và thức dậy (có nghĩa là, tiếp tục với những gì bên dưới chúng)

Minh họa:

_ = console.log.bind(console) 
 

 
function *gen() { 
 
    _('gen: good morning') 
 

 
    _('gen: sending hi') 
 
    _('gen: zzz') 
 
    p = yield 'hi' 
 
    _('gen: awake! got', p) 
 

 
    _('gen: now sending fine') 
 
    _('gen: zzz') 
 
    p = yield 'fine' 
 
    _('gen: awake! got', p) // *** 
 
} 
 

 
function main() { 
 

 
    var g = gen() 
 

 
    _('main: sending knock knock') 
 
    _('main: zzz') 
 
    r = g.next('knock knock') 
 
    _('main: awake! got', r) 
 

 
    _('main: sending how r u') 
 
    _('main: zzz') 
 
    r = g.next('how r u') 
 
    _('main: awake! got', r) 
 
} 
 

 
main()

Lưu ý rằng kể từ khi ghi đi kèm trước khi đọc, thông điệp đầu tiên gửi đến các máy phát điện bị mất. Nó chỉ được sử dụng để đánh thức máy phát điện. Cũng lưu ý cách chúng tôi đã để máy phát ở trạng thái ngủ, vì vậy không đạt được đường dây ***.

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