2012-04-18 4 views
56
function foo(a) { 
    if (/*some condition*/) { 
     // perform task 1 
     // perform task 3 
    } 
    else { 
     // perform task 2 
     // perform task 3 
    } 
} 

저는 구조가 위와 유사합니다. 나는 bar() 함수로 작업 3을 추상화하려고하지만이 함수의 액세스를 foo(a)의 범위 내로 제한하고자합니다.javascript의 다른 함수 내에서 함수를 정의하십시오.

내가 원하는 것을 얻으려면 다음과 같이 변경하는 것이 맞습니까? 위가 올바른 경우

function foo(a) { 
    function bar() { 
     // perform task 3 
    } 

    if (/*some condition*/) { 
     // perform task 1 
     bar(); 
    } 
    else { 
     // perform task 2 
     bar(); 
    } 
} 

, bar() 불려갑니다 때마다 foo(a)을 재정의됩니까? (여기에 CPU 리소스 낭비 걱정)

+1

예 및 예 .... – hkf

+1

자신이 가치가 있는지 테스트하십시오 : http://jsperf.com/ 나는 그것이 task3에 달려 있다고 상상합니다. – tomByrer

+1

@tomByer - 대답을위한 도구 – tamakisquare

답변

86

예, 당신이 가지고있는 것이 옳습니다. 일부 노트 :

  • bar이 함수에 대한 모든 호출에 생성되지만이 : 최신 브라우저에
    • 이 매우 빠른 과정이다. (일부 엔진은 코드을 한 번 컴파일 한 다음 매번 다른 컨텍스트로 해당 코드를 다시 사용할 수 있지만 대부분의 경우 Google V8 엔진 (대부분의 경우 Chrome 및 기타 국가에서 사용)이 해당됩니다.
    • bar, 일부 엔진은 함수 호출을 완전히 제거하여 "인라인"할 수 있다고 판단 할 수 있습니다. V8은 이것을 수행하며, 그것이 유일한 엔진은 아니라고 확신합니다. 당연히 코드의 동작을 변경하지 않는 경우에만이를 수행 할 수 있습니다.
  • 매번 생성되는 bar의 성능에 미치는 영향은 JavaScript 엔진간에 매우 다양합니다. bar이 사소한 경우 감지 할 수없는 것부터 매우 작은 것으로 다양합니다. 행 foo (예 : mousemove 핸들러)에서 수천 번 호출하지 않는 경우 걱정하지 않아도됩니다. 비록 당신이 더 느린 엔진에 대한 문제를 본다면 걱정할 것입니다. Here's a test case involving DOM operations은 영향이 있지만 사소한 것 (아마도 DOM 항목에 의해 씻겨 나간 것)을 제안합니다. Here's a test case doing pure computation은 훨씬 더 높은 영향을 보여 주지만 솔직히 말해서 마이크로 초의 차이를 말합니다. 마이크로 초가 걸릴 확률이 92 % 증가하기 때문에 여전히 매우 빠릅니다. 실생활에 미치는 영향을 보지 못하면, 걱정할 필요가 없습니다.
  • bar은 함수 내에서만 액세스 할 수 있으며 해당 함수 호출에 대한 모든 변수와 인수에 액세스 할 수 있습니다. 이것은 이것을 매우 편리한 패턴으로 만듭니다. 당신이 함수 선언을 사용했기 때문에 당신이 선언 (상단, 하단, 또는 중간을 넣을 경우, 그것은 중요하지 않습니다
  • 참고 한 것이 아닌 내부 기능의 최상위 수준의로   — 흐름 제어 문은 구문 오류이므로) 단계별 코드의 첫 번째 줄이 실행되기 전에 정의됩니다.
+0

Thx 제안에 +1. 이것은 무시할 수있는 성능의 히트라고 말하고 있습니까? ('bar'의 복사본은'foo' 호출마다 만들어집니다) – tamakisquare

+2

@ahmoo : JavaScript 성능을 사용하면 거의 항상 대답이 달라질 수 있습니다. :-) 엔진을 실행할 엔진과 얼마나 자주 foo를 호출 할 것인가에 달려있다. 'foo'를 수천 번 연속 호출하지 않으면 (예를 들어,'mousemove' 핸들러가 아닌), 나는 전혀 걱정하지 않을 것입니다. 그리고 일부 엔진 (예를 들어 V8)은 코드를 인라인으로 처리하여 함수 호출을 완전히 제거합니다. 이렇게하면 외부에서 감지 할 수있는 방식으로 변경되지 않습니다. –

+0

감사합니다. 너는 몇 가지 중요한 점을 가지고있다. – tamakisquare

2

네, 정상적으로 작동합니다.

외부 함수를 입력 할 때마다 내부 함수가 다시 작성되지 않지만 다시 할당됩니다.

이 코드를 테스트하는 경우가 1, 2, 1, 2하지 1, 2, 2, 2 표시됩니다

function test() { 

    function demo() { alert('1'); } 

    demo(); 
    demo = function() { alert('2'); }; 
    demo(); 

} 

test(); 
test(); 

합니다.

+0

답변 해 주셔서 감사합니다. 'test()'가 실행될 때마다'demo()'를 재 할당해야 하는가? 그것은'demo()'의 복잡성에 달려 있습니까? – tamakisquare

+1

성능 테스트를했습니다. http : // jsperf.com/inner-function-vs-global-function 결론은 일반적으로 성능 문제가 아니라는 것입니다 (함수에 넣는 코드는 함수 자체를 만드는 것보다 실행하는 데 시간이 오래 걸리기 때문에). 그 추가 성능 가장자리, 당신은 다른 브라우저에 대한 다른 코드를 작성해야 할 것입니다. – Guffa

+0

테스트를 작성하고 실적에 대한 포인트를 공유하는 데 시간을 할애 한 Thx. 매우 감사. – tamakisquare

7
var foo = (function() { 
    var bar = function() { 
     // perform task 3 
    } 
    return function (a) { 

     if (/*some condition*/) { 
      // perform task 1 
      bar(); 
     } 
     else { 
      // perform task 2 
      bar(); 
     } 
    }; 
}()); 

폐쇄는 자동 실행 익명 함수로부터 새로운 함수를 반환 포함 bar()의 범위를 유지 foo() 더 가시 범위를 설정한다. 익명 자체 실행 함수는 정확히 한 번만 실행되므로 bar() 인스턴스가 하나 뿐이며 모든 실행시 foo()이이를 사용합니다.

+0

흥미 롭습니다. 그럼 폐쇄를 봐야 해. 감사. – tamakisquare

9

다음은 클로저입니다.

var foo = (function() { 
    function bar() { 
    // perform task 3 
    }; 

    function innerfoo (a) { 
    if (/* some cond */) { 
     // perform task 1 
     bar(); 
    } 
    else { 
     // perform task 2 
     bar(); 
    } 
    } 
    return innerfoo; 
})(); 

Innerfoo (폐쇄)는 막대에 대한 참조를 보유하고 innerfoo 참조 만이 폐쇄 만들 회만 호출 익명 함수로부터 복귀된다.

바는 외부에서이 방법으로 액세스 할 수 없습니다.

+0

흥미 롭습니다. 나는 자바 스크립트에 대한 노출이 제한되어 있으므로 클로저는 나에게 새로운 것이다. 그러나 당신은 종결을 연구하는 출발점을 표시했습니다. 감사. – tamakisquare

관련 문제