[javascript] 익명 함수를 사용하면 성능에 영향을 줍니까?

Javascript에서 명명 된 함수와 익명 함수를 사용하는 것 사이에 성능 차이가 있는지 궁금합니다.

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = function() {
        // do something
    };
}

vs

function myEventHandler() {
    // do something
}

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = myEventHandler;
}

첫 번째는 거의 사용되지 않는 함수로 코드를 복잡하게 만들지 않기 때문에 더 깔끔하지만 해당 함수를 여러 번 다시 선언하는 것이 중요합니까?



답변

여기서 성능 문제는 익명 함수를 사용한다는 사실이 아니라 루프가 반복 될 때마다 새 함수 객체를 만드는 비용입니다.

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = function() {
        // do something    
    };
}

코드 본문이 같고 어휘 범위 ( closure )에 대한 바인딩이 없더라도 수천 개의 고유 한 함수 개체를 만들고 있습니다. 반면에 다음은 루프 전체의 배열 요소에 동일한 함수 참조를 할당하기 때문에 더 빠릅니다 .

function myEventHandler() {
    // do something
}

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = myEventHandler;
}

루프에 들어가기 전에 익명 함수를 만든 다음 루프 내부에있는 동안 배열 요소에 대한 참조 만 할당하면 명명 된 함수 버전과 비교할 때 성능이나 의미 적 차이가 전혀 없음을 알 수 있습니다.

var handler = function() {
    // do something    
};
for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = handler;
}

요컨대 이름이 지정된 함수에 대해 익명을 사용하는 데 따른 성능 비용은 관찰 할 수 없습니다.

제쳐두고 위에서 보면 다음과 같은 차이가없는 것처럼 보일 수 있습니다.

function myEventHandler() { /* ... */ }

과:

var myEventHandler = function() { /* ... */ }

전자는 함수 선언 이고 후자는 익명 함수에 대한 변수 할당입니다. 동일한 효과가있는 것처럼 보일 수 있지만 JavaScript는 약간 다르게 처리합니다. 차이점을 이해하기 위해“ JavaScript 함수 선언 모호성 ”을 읽는 것이 좋습니다 .

모든 접근 방식의 실제 실행 시간은 대개 브라우저의 컴파일러 및 런타임 구현에 의해 결정됩니다. 최신 브라우저 성능을 완전히 비교 하려면 JS Perf 사이트를 방문하십시오 .


답변

내 테스트 코드는 다음과 같습니다.

var dummyVar;
function test1() {
    for (var i = 0; i < 1000000; ++i) {
        dummyVar = myFunc;
    }
}

function test2() {
    for (var i = 0; i < 1000000; ++i) {
        dummyVar = function() {
            var x = 0;
            x++;
        };
    }
}

function myFunc() {
    var x = 0;
    x++;
}

document.onclick = function() {
    var start = new Date();
    test1();
    var mid = new Date();
    test2();
    var end = new Date();
    alert ("Test 1: " + (mid - start) + "\n Test 2: " + (end - mid));
}

결과 :
테스트 1 : 142ms 테스트 2 : 1983ms

JS 엔진이 Test2에서 동일한 기능임을 인식하지 못하고 매번 컴파일하는 것으로 보입니다.


답변

일반적인 디자인 원칙으로 동일한 코드를 여러 번 구현하지 않아야합니다. 대신 일반적인 코드를 함수로 가져와 여러 위치에서 해당 (일반적이고 잘 테스트되었으며 수정하기 쉬운) 함수를 실행해야합니다.

(귀하의 질문에서 추론 한 것과 달리) 내부 함수를 한 번 선언하고 해당 코드를 한 번 사용하는 경우 (그리고 프로그램에서 다른 항목이 동일하지 않은 경우) 아마도 익명 함수 (추측 사람들)가 동일한 방식으로 처리됩니다. 일반적인 명명 된 함수로 컴파일러.

특정 경우에 매우 유용한 기능이지만 많은 상황에서 사용해서는 안됩니다.


답변

나는 큰 차이를 기대하지 않지만 만약 있다면 스크립팅 엔진이나 브라우저에 따라 다를 것입니다.

코드를 쉽게 찾을 수 있다면 함수를 수백만 번 호출 할 것으로 예상하지 않는 한 성능은 문제가되지 않습니다.


답변

성능에 영향을 미칠 수있는 부분은 함수 선언 작업입니다. 다음은 다른 함수의 컨텍스트 내부 또는 외부에서 함수를 선언하는 벤치 마크입니다.

http://jsperf.com/function-context-benchmark

Chrome에서는 함수를 외부에서 선언하면 작업이 더 빠르지 만 Firefox에서는 그 반대입니다.

다른 예에서 내부 함수가 순수 함수가 아닌 경우 Firefox에서도 성능이 부족함을 알 수 있습니다.
http://jsperf.com/function-context-benchmark-3


답변

다양한 브라우저, 특히 IE 브라우저에서 루프를 더 빠르게 만드는 것은 다음과 같이 반복됩니다.

for (var i = 0, iLength = imgs.length; i < iLength; i++)
{
   // do something
}

루프 조건에 임의의 1000을 넣었지만 배열의 모든 항목을 살펴보고 싶다면 내 드리프트를 얻습니다.


답변

참조는 거의 항상 참조하는 것보다 느립니다. 이렇게 생각해보세요. 1 + 1을 더한 결과를 인쇄한다고 가정 해 보겠습니다.

alert(1 + 1);

또는

a = 1;
b = 1;
alert(a + b);

나는 그것이 그것을 보는 매우 단순한 방법이라는 것을 알고 있지만 그것은 예시적인 것입니다. 여러 번 사용할 경우에만 참조를 사용하십시오. 예를 들어, 다음 예제 중 어느 것이 더 의미가 있습니까?

$(a.button1).click(function(){alert('you clicked ' + this);});
$(a.button2).click(function(){alert('you clicked ' + this);});

또는

function buttonClickHandler(){alert('you clicked ' + this);}
$(a.button1).click(buttonClickHandler);
$(a.button2).click(buttonClickHandler);

두 번째는 더 많은 줄이 있더라도 더 나은 연습입니다. 이 모든 것이 도움이 되었기를 바랍니다. (그리고 jquery 구문은 누구도 버리지 않았습니다)