2009-07-14 50 views
15

Tôi đang cố gắng tạo một hàm giữ trạng thái nhưng được gọi với foo().
Có thể không?Có thể thực hiện một hàm functor trong JavaScript không?

+2

Joel Spolsky có một bài viết thật sự tốt đẹp trên functors javascript: http://www.joelonsoftware.com/items/2006/08/01.html – peirix

+0

Bài viết này không phải là trên functors, nó hoạt động. –

+0

@torazaburo Không có functors trong Javascript. Nhưng cùng một tính năng C++ có thể được mô phỏng bằng các hàm bởi vì chúng là các đối tượng. –

Trả lời

28

Tôi tin rằng đây là những gì bạn muốn:

var foo = (function() { 
    var state = 0; 

    return function() { 
     return state++; 
    }; 
})(); 

Hoặc, sau the Wikipedia example:

var makeAccumulator = function (n) { 
    return function (x) { 
     n += x; 
     return n; 
    }; 
}; 

var acc = makeAccumulator(2); 

alert(acc(2)); // 4 
alert(acc(3)); // 7 

JavaScript là một trong những ngôn ngữ mà có, IMHO, hỗ trợ tuyệt vời cho các chức năng như công dân hạng nhất .

+0

nó trả về không xác định hai lần. –

+0

"Nó". Ví dụ foo() thực sự trả về không xác định. Nó chỉ là một ví dụ. Ví dụ tích lũy sẽ hoạt động như mong đợi. Tôi đã thêm một trường hợp sử dụng đơn giản. –

+0

Cảm ơn. Ví dụ foo. Tôi đã nhận xét trước ví dụ thứ hai. –

4

Kể từ khi chức năng Javascript là đối tượng hạng nhất, đây là cách để làm điều đó:

var state = 0; 
var myFunctor = function() { alert('I functored: ' + state++);}; 

Biến state sẽ có sẵn cho các myFunctor chức năng trong việc đóng cửa địa phương. (Toàn cầu trong ví dụ này). Các câu trả lời khác cho câu hỏi này có những ví dụ phức tạp hơn.

Không chỉ tương đương với "toán tử triển khai thực hiện()" trên một số đối tượng hiện có.

2

Bạn có thể coi các hàm là đối tượng và cung cấp cho chúng "biến thành viên". Ở đây chúng tôi đang sử dụng hàm bên trong trong fact, nhưng thay vì chỉ khai báo nó dưới dạng biến cục bộ (var loop = ...), chúng tôi đang đặt định nghĩa của nó bên ngoài hàm, sử dụng cú pháp đối tượng (fact.loop = ...). Điều này cho phép chúng tôi về cơ bản "xuất" chức năng nội bộ loop của fact để có thể sử dụng lại chức năng doubleFact.

var fact = function(n) { 
    return fact.loop(n, 1); 
}; 

fact.loop = function(n, acc) { 
    if (n < 1) { 
    return acc; 
    } else { 
    return fact.loop(n-1, acc * n); 
    } 
}; 

var doubleFact = function(x) { 
    return fact.loop(x * 2, 1); 
}; 

console.log(fact(5)); // 120 
console.log(doubleFact(5)); // 3628800 

Ý tưởng tương tự có thể được sử dụng để duy trì trạng thái.

var countCalled = function() { 
    console.log("I've been called " + (++countCalled.callCount) + " times."); 
}; 

countCalled.callCount = 0; 

countCalled(); // I've been called 1 times. 
countCalled(); // I've been called 2 times. 
countCalled(); // I've been called 3 times. 

Nếu bạn muốn để có thể nhanh chóng nhiều người, mỗi trạng thái của mình, hãy thử này:

var CallCounter = function(name) { 
    var f = function() { 
    console.log(name + " has been called " + (++f.callCount) + " times."); 
    }; 
    f.callCount = 0; 
    return f; 
}; 

var foo = CallCounter("foo"); 
var bar = CallCounter("bar"); 

foo(); 
foo(); 
bar(); 
foo(); 
bar(); 
bar(); 
bar(); 

console.log(foo.callCount); 
console.log(bar.callCount); 

Đầu ra:

foo has been called 1 times. 
foo has been called 2 times. 
bar has been called 1 times. 
foo has been called 3 times. 
bar has been called 2 times. 
bar has been called 3 times. 
bar has been called 4 times. 
3 
4 
-1

Bạn có thể sử dụng đóng chức năng trở về với thuộc tính đối tượng hàm được đính kèm. Các thông số của functor (đóng) có thể được thay đổi sau khi khởi tạo, có thể hữu ích khi xây dựng một số tính toán có thể chạy/cấu hình sau. Hãy xem ví dụ dưới đây. Câu trả lời này tương tự như limp_chimp.

function functor() { 
 

 
    var run = function runX() { 
 

 
    return runX.functorParam; 
 

 
    // or: 
 

 
    // return run.functorParam; 
 
    }; 
 

 
    run.functorParam = 'functor param'; // default value 
 

 
    return run; 
 
} 
 

 
var f1 = functor(); 
 

 
// call f1 
 
f1(); // 'functor param' 
 

 

 
// lets change functor parameters: 
 
f1.functorParam = 'Hello'; 
 

 

 
// call f1 
 
f1(); // 'Hello'

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