5

최근에 나는 performance guide Let's make the web faster을 읽었으며 "가변적 인 범위 지정이 동적 인 CommonLisp 사용자에게 주어진 것처럼 조언을 통해 함정 피하기"권장 사항에 의문을 표시했습니다.자바 스크립트 : 클로저 변수에 대한 액세스가 느릴 수있는 이유

f가 호출 될 때
var a = 'a'; 
function createFunctionWithClosure() { 
    var b = 'b'; 
    return function() { 
    var c = 'c'; 
    a; 
    b; 
    c; 
    }; 
} 

var f = createFunctionWithClosure(); 
f(); 

a를 참조하면 c를 참조보다 느린 b를 참조보다 느립니다.

그것은 지역 변수를 C를 참조하면 B보다 더 빠르다는 것을 매우 분명,하지만 iterpreter이 제대로 작성된 경우 (동적 범위 지정하지 않고 - 체인 해시 테이블 조회 같은 ..) 속도 차이는해야한다 가장자리 가의. 안 그래요?

답변

4

네가 맞아. 최신 JS 엔진은 scope chain lookupprototype chain lookup을 많이 최적화합니다. AFAIK 엔진은 액세스 노드가있는 일종의 해시 테이블을 유지하려고 시도합니다. 거기에 더 eval() (명시 적 또는 암시 적으로, 예를 들어, setTimeout)입니다 또는 try-catch 절 또는 a with statement 호출하면

에만 작동합니다. 그런 구조 때문에 통역사는 데이터에 액세스하는 방법을 확신 할 수 없으며 실제로는 모든 부모 컨텍스트 variable/activation objects을 크롤링하고 검색된 변수 이름을 분석해야한다는 것을 의미하는 고전적인 scope chain lookup으로 "폴백 (fallback)"해야합니다. 이 과정은 물론 처리 된 조회가 시작된 곳으로부터 "멀리 떨어져있는"대상/이름에 더 많은 시간이 소요됩니다. 즉, global object의 데이터 액세스는 항상 가장 느릴 것입니다. 기술 된 검색 절차는 ECMAScript 버전 (262) 제 3 판입니다


anonymous function -> Execution Context -> Activation Object (not found) 
anonymous function -> Execution Context -> [[ Scope ]] 
    - createFunctionWithClosure 
    - global scope 
createFunctionWithClosure -> Activation Object (not found) 
global scope -> Variable Object (found) 

처럼 조각에서

a에 대한 조회 프로세스가 갈 것입니다. ECMAscript Edition 5에는 몇 가지 근본적인 변화가 있습니다.

+0

장수와 호기심에 대해 v5에서 어떻게 변화하는지 설명 할 수 있습니까? – Hogan

+0

익명 함수 내에서'var d = eval ("this");'를 수행하면 범위 체인 룩업은 모든 컨텍스트를 크롤링하여 'a'참조를 얻습니다. 아니면 그냥'this'를'd '에 할당 할 것인가? – headacheCoder

+0

@headacheCoder : 그 코드가 일종의 "oldish"브라우저에서 실행되면 매우 가능합니다. 그러나, 어쨌든 이런 끔찍한 진술은 절대로해서는 안됩니다. 최첨단 브라우저는'eval'을 사용하여 물건을 최적화 할 수있을 것이며 심지어 엄격 모드에서도 피해야 할 것입니다. 그러나 이러한 브라우저는 어쨌든 ES5 사양을 따릅니다. – jAndy

관련 문제