2009-07-14 2 views
15

상태를 유지하지만 foo()로 호출되는 함수를 만들려고합니다.
가능합니까?JavaScript로 펑터를 만들 수 있습니까?

+2

Spolsky 조엘 자바 스크립트 펑에 정말 좋은 기사를 가지고 : http://www.joelonsoftware.com/items/2006/08/01.html – peirix

+0

이 문서는 펑터에없는, 그것은 기능에 있습니다. –

+0

@torazaburo Javascript에는 펑터가 없습니다. 그러나 객체이기 때문에 함수를 사용하여 동일한 C++ 기능을 에뮬레이트 할 수 있습니다. –

답변

28

나는이 당신이 원하는 것을 믿습니다 :

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

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

또는를 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 

자바 스크립트, 일류 시민으로서의 기능 IMHO, 우수한 지원이 그 언어 중 하나입니다 .

+0

두 번 정의되지 않은 값을 반환합니다. –

+0

"어느 것". foo() 예제는 실제로 undefined를 반환합니다. 이것은 단지 예일뿐입니다. 누산기 예제는 예상대로 작동해야합니다. 간단한 사용 사례를 추가했습니다. –

+0

감사. foo 예제. 나는 두 번째 예 앞에 논평했다. –

4

자바 스크립트 기능이 일류 객체이기 때문에,이 그것을 할 수있는 방법은 다음과 같습니다

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

state 변수는 로컬 폐쇄에 myFunctor 기능을 사용할 수 있습니다. (이 예제에서는 Global). 이 질문에 대한 다른 대답은보다 정교한 예입니다.

일부 기존 개체에는 "연산자 구현"과 동일한 기능이 없습니다.

2

함수를 객체로 취급하고 "멤버 변수"를 제공 할 수 있습니다. 여기서 우리는 fact에 내부 함수를 사용하고 있지만, 로컬 변수 (var loop = ...)로만 선언하는 대신 객체 구문 (fact.loop = ...)을 사용하여 함수 외부에서 정의를 적용합니다. 이렇게하면 내부 loop 기능이 fact으로 "내보내기"되므로 기능 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 

같은 생각을 사용하여 상태를 유지할 수 있습니다. 여러 사람을 인스턴스화 할 수있게하려면

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. 

, 자신의 상태와 각이 시도 :

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); 

출력을 :

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

당신이 기능을 반환 폐쇄를 사용할 수 있습니다 첨부 된 함수 객체 속성. 초기화 후 해당 펑터 (클로저)의 매개 변수는 나중에 실행/구성 할 수있는 계산을 빌드 할 때 유용 할 수있는 후에 변경할 수 있습니다. 아래 예를 살펴보십시오. 이 대답은 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'