2013-02-20 2 views
12

나는이 대개 깊은 구조 내에서 선언 또는 "네임 스페이스"자바 스크립트 폐쇄 성능

//global scope 
(function ($, lib) { 
    //function scope 1 
    var format = lib.format, // instead of calling lib.format all the time just call format 
    touch = lib.pointer.touch, //instead of calling lib.pointer.touch each time just touch 
    $doc = $(document), 
    log = logger.log; //not console log... 


    $doc.on('app:ready', function() { 
    //function scope 2 
    $doc.on('some:event', function (e) { 
     //function scope 3 
     //use the cached variables 
     log(format('{0} was triggered on the $doc object', e.type); 
    }); 

    $doc.on(touch, function (e) { 
     //function scope 3 
     log(format('this should be {1} and is... {0} ', e.type, touch); 
    }); 
    }); 
}(jQuery, lib)); 

I이었다되는 함수의 특성 값을 캐시 같은 것을 할 자바 스크립트 잠시 동안 작동되는 , 쓰기, 터치 공상 자동 완성 강력한 십오이에 도움이 될 경우에도, lib.pointer.touch를 작성하는 것을 더 매력적 보인다 나는대로

  • 게으른, 터치 짧은 : 그 때문에 일을.
  • 최소화 부는 단일 문자 변수에 그 하나의 개인 변수를 변환 할 수 있습니다, 그래서 또한 나를 위해 감각을했다 (너무 빨리 최적화하지, 나도 알아, 알아,하지만 내가 추측 안전 것 같다)

그런 식으로 작성된 모든 코드는 모바일 장치 및 데스크톱 브라우저에서 제대로 수행되는 것처럼 보입니다. 따라서 안전한 방법 인 것 같습니다. 함수가없는 외부 환경에서 변수 (자유 변수를 사용합니다 않습니다하지만

  • ... 나는이 폐쇄에 의존하기 때문에, 및 내부 기능이 궁금 선언 된 컨텍스트를 저장하는 폐쇄를 만들어야합니다) ... 클로저 컨텍스트가 아직 저장되어 있습니까? (또는 ia 나무가 나무에 떨어지고 아무도 그 소리를들을 수 없다면 여전히 충돌 소리를 내는가? hehe) ECMA는 저장이 필요한지에 대해 언급하지 않기 때문에 javascript 엔진간에 이러한 차이가있을 수 있음을 알고 있습니다. 외부로부터의 변수가 액세스되지 않을 때의 컨텍스트.

  • 위 표현이 맞다면 ...이 코드 블록이 더 효율적입니까? 그것은 자기 즉시 호출 함수에 해당 변수를 전달하기 때문에

    //global scope 
    (function ($, lib) { 
        //function scope 1 
        var format = lib.format, 
        touch = lib.pointer.touch, 
        $doc = $(document), 
        log = console.log; 
    
        $doc.on('app:ready', function() { 
    
        (function ($doc, touch, lib, format) { 
         // since all the variables are provided as arguments in this function 
         // there is no need to save them to the [[scope]] of this function 
         // because they are local to this self invoking function now 
         $doc.on('some:event', function (e) { 
         //function scope 3 
         //use the cached variables 
         log(format('{0} was triggered on the $doc object', e.type); 
         }); 
    
         $doc.on(touch, function (e) { 
         //function scope 3 
         log(format('this should be {1} and is... {0} ', e.type, touch); 
         }); 
        }($doc, touch, lib, format));  
    
        }); 
    
    }(jQuery, lib)); 
    

는 것이 더 효율적인가요? 그 새로운 기능을 코드에 어떤 영향을 미치게 만들 것인가? (음 또는 양수)?

  • 신뢰할 수있는 방식으로 내 자바 스크립트 라이브러리의 메모리 소비를 올바르게 측정 할 수 있습니까? 나는 전역 컨텍스트에 변수가 누출되지 않도록하기 위해 대부분 자체 자바 스크립트 모듈을 즉각적인 자체 호출 함수 안에 100 배나 가지고있다. 그래서 그들은 모두 위에서 언급 한 코드 블록과 매우 유사한 모듈로 싸여 있습니다.

  • 변수를 더 가까운 곳에 캐시하는 것이 더 효과적일까요? 그렇다면 변수 선언을 반복적으로 사용하여 어디에서 사용할지를 다시 말해야합니다.

  • 현재 로컬 컨텍스트가 아닌 변수를 찾고 엔진이 먼저 부모 범위를 조사하여 해당 레벨의 모든 변수를 반복합니다 ... 레벨 당 변수가 많을수록 아마도 변수를 찾는 성능 일 것입니다.

  • 내부 클로저에서 정의되지 않은 변수를 찾으려고하면 정의가 전역 범위까지 부모 범위에서 처음으로 검색되므로 엔진을 찾지 않아도됩니다. 글로벌 범위. 그게 사실이야? 이러한 종류의 조회를 최적화하는 엔진입니까?

결국 ...두 번째 예제로 코드를 구현하고 싶지는 않을 것이라는 것을 알고 있습니다. 왜냐하면 코드를 읽기가 더 어렵게 만들 것이고, 첫 번째 방법을 사용하여 최종 출력 크기를 최소화 할 수 있기 때문입니다. 내 질문은 호기심에 의해 동기를 부여하고 좀 더 자바 스크립트의 정말 좋은 기능을 이해하려고합니다. 이 테스트에 따라서

은 ...

http://jsperf.com/closures-js

이 두 번째 방법이 더 빠른 것 같다. 그러나 미친 번 반복 할 때만 분명합니다 ... 지금은 코드가 반복 횟수를 수행하지 않지만 ... 코딩 방법 때문에 메모리를 더 많이 소비하고 있습니다.

업데이트 : it 이 질문이 너무 큽니다. 죄송하지만 작은 부분을 부수려고합니다. 이 질문은 내가 말했듯이 대부분 호기심에 자극을 받았다. 모바일 장치에서도 성능이 무시할 수있을 것 같다. 모든 의견을 보내 주셔서 감사합니다.

+0

자세한 답변은 없지만 며칠 전에 발견했습니다. http://www.developer.nokia.com/Community/Wiki/JavaScript_Performance_Best_Practices –

+3

아주 긴 질문입니다. 문제를 해결해야 할 수도 있습니다. – Bergi

+0

그래, 아마 너무 길지만 모두 같은 문제와 관련이 있습니다. 나는 그것을 단축 시키거나 코드 예제를 jsfiddle로 이동시켜 더 짧게 만들려고 노력할 것이다. 덕분에 –

답변

8

시기상조라고 생각합니다. 대부분의 경우 성능이 문제가되지 않는다는 것을 이미 알고 있습니다. 긴밀한 루프에서도 성능이 그다지 좋지 않습니다. 클로저에서 불필요한 변수를 제거하여 Chrome이 시작하면서 JavaScript 엔진이 자체적으로 최적화되도록합니다.

중요한 것은 불필요한 최적화로 코드를 읽기 어렵게 만드는 것입니다. 귀하의 예제는 코드 개발에 상당한 어려움을 겪습니다. 경우에 따라 앱의 특정 부분이 더 많은 메모리/성능을 필요로한다는 것을 알기 때문에 코드를 읽기가 더 어렵게 만들지 만 그 시점에서해야합니다. 당신이 (크롬) 다음 코드에 중단 점을 추가하는 경우

, 당신은 범위 변수 아래에있는 '폐쇄'노드에서 찾습니다 world 변수가 폐쇄에서 최적화 된 것을 볼 수 있습니다 http://jsfiddle.net/4J6JP/1/

enter image description here.

(function(){ 
    var hello = "hello", world="world"; 
    setTimeout(function(){ 
     debugger; 
     console.log(hello); 
    }); 
})() 

해당 내부 함수에 eval을 추가하면 모든 베팅이 해제되고 클로저를 최적화 할 수 없습니다.

+0

정말 문제가되지 않는 한 폐쇄 담당자의 실적에 신경 쓰지 않는 것이 좋습니다. 그리고 브라우저는 클로저를 최적화하는 좋은 작업을하고있는 것 같습니다. 그래서 자체 호출 함수 안에 100 개 이상의 모듈을 가지고 있으면 문제가되지 않아야합니까? –

+3

숫자에 상관없이 나는 변화가 눈에 띄지 않는다고 생각합니다. 문제가 있음을 발견 할 때까지 읽는 것이 가장 쉬운 방법을 고수하십시오. 특히 메모리 또는 성능 집약적 인 코드 섹션을 다루는 경우에만 눈에 띄게됩니다 –

0

함수의 범위와 컨텍스트가 만들어 질 때 성능 비용이 발생하지만 여분의 자식 범위를 추가하면 비용이 발생하지만이 경우 무시할 수 있습니다. 이동 중에 필요한 객체 나 변수를 반복하는 것은 어휘 범위를 등반하고 검색하는 것보다 빠릅니다. http://code.tutsplus.com/tutorials/stop-nesting-functions-but-not-all-of-them--net-22315

레퍼런스를 얻을 수 있고 그것을 어휘 범위의 var 내부에 할당 할 수 있다면 부모 함수가 소멸 된 후에도 조심해야합니다. 반환 된 함수 또는 객체는 동일한 어휘 범위 내에서 선언 되었기 때문에 "longer.lib.format"에 대한 참조에 액세스 할 수 있습니다. 더 이상 참조를 사용하지 않으면 모든 경로를 제거해야합니다. 그 범위. 슬프지만 현재로서는 "lib 형식"의 "reference"를 삭제할 수 없다는 것을 이해하고 있습니다. 동일한 lib가 다른 곳에서 참조되므로 "delete format"은 허용되지 않지만 개체/lib에있는 구성원을 삭제할 수는 있습니다. 그것을 참조하십시오. 참조를 보유하고 더 이상 필요하지 않을 때이를 삭제 한 다음 삭제할 개체를 삭제할 수 있습니다.

업데이트 : 최근에 자바 스크립트에서 delete를 사용하면 천천히, 오히려 더 이상 사용하지 않을 때 membera를 {}로 지정하십시오.