2012-01-10 53 views
5

Tôi đang cố gắng tạo một hàm ẩn danh đệ quy.Làm thế nào để làm cho javascript này hoạt động?

Dưới đây là các chức năng:

(function (i) { 
    console.log(i); 
    if (i < 5) this(i + 1) 
})(0) 

Tôi biết "này" là đối tượng cửa sổ. Có cách nào để gọi hàm này không?

+1

** Điều tốt nhất cần làm là không có chức năng ẩn danh, mà thay vào đó là hàm được xác định bằng câu lệnh khai báo hàm. – Pointy

Trả lời

12

Thuộc tính arguments.callee có thể được sử dụng.

(function(i){console.log(i);if(i<5)arguments.callee(i+1)})(0) 

Một phương pháp khác để đạt được cùng chức năng là đặt tên hàm. Ngoài phạm vi, tên sẽ không có sẵn:

(function tmp(i){console.log(i);if(i<5)tmp(i+1)})(0); //OK, runs well 
alert(typeof tmp); // Undefined 


Lưu ý rằng việc sử dụng arguments.callee tài sản bị cấm trong chế độ nghiêm ngặt:

"use strict"; 
(function(){arguments.callee})(); 

ném:

TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

+1

Cảm ơn! Tôi sẽ ngủ thông minh hơn. –

+4

Lưu ý rằng 'arguments.callee' không được dùng nữa (và khá là lố bịch, nếu bạn đã từng nghe nó nói tại một hội nghị JavaScript), và sẽ không được hỗ trợ trong tương lai. Nó cũng khá chậm. Ngoài ra, đặt tên cho các hàm của bạn khi chúng được định nghĩa với một biểu thức * chức năng * (trái ngược với tuyên bố khai báo) là nguy hiểm vì [các trình duyệt đôi khi làm những điều kỳ lạ.] (Http://kangax.github.com/nfe/) – Pointy

+0

Không mong đợi để tìm hiểu một từ mới về chủ đề này. "Vociferously" thật tuyệt vời. –

1

Ah ... các dạng đệ quy chức năng .... [[[flashback to comp sci class]]]

Bạn có thể sử dụng hàm trợ giúp:

function X(f) { return f.apply(this, arguments); } 
X(function(me, n) { return n<=1 ? n : n*me(me,n-1); }, 6); 

(trả về 720; đây là chức năng thừa, ví dụ kinh điển của đệ quy)

Điều này có thể lần lượt được ẩn danh:

(function (f) { return f.apply(this, arguments); })(
    function(me, n) { return n<=1 ? n : n*me(me,n-1); }, 
    6); 

hoặc chuyên ngành chức năng của một đối số, để tránh applyarguments:

(function (f,x) { return f(f,x); })(
    function(me, n) { return n<=1 ? n : n*me(me,n-1); }, 
    6); 

(cả hai loại này cũng trả lại 720)

Bí quyết sử dụng chức năng trợ giúp này cho phép chức năng của bạn nhận được elf là đối số đầu tiên của nó, và do đó gọi chính nó.

Để thích ứng với ví dụ của bạn:

(function (f,x) { return f(f,x); })(
    function(me, i) { console.log(i); if (i<5) me(me,i+1); }, 
    0) 

trong đó hoạt động như mong đợi trong Firebug (log 0,1,2,3,4,5 để an ủi)

1

Bạn đặt tên cho chức năng ẩn danh, ở đây tôi đặt tên cho nó là "_", mặc dù nó được đặt tên, nhưng nó vẫn còn ẩn danh.

(function _(i) { 
    console.log(i); 
    if (i < 5){ _(i + 1); } 
})(0); 
Các vấn đề liên quan