자바스크립트를 비롯한 C,Java,Python등 대부분의 언어는 렉시컬 스코프를 따르고 있습니다.
렉시컬 스코프란 함수가 선언이 되는 위치에 따라서 상위 스코프가 결정되는 스코프입니다. 함수가 선언이 될 때! 스코프가 생성됩니다.
let x = 'global'
function foo(){
let x ='local'
bar()'
}
function bar(){
console.log(x)
}
foo() //global
bar() //global
위의 코드를 보면 foo() 의 지역변수에 x를 local이라 설정해 줬음에도 bar 함수는 선언될 당시 전역 스코프에 있기 때문에 전역변수인 x를 참조하게 됩니다.
다음을 보고 결과값을 예상해보세요
let funcArr =[]
for(let i = 0; i < 5; i++) {
let c = i *2;
funcArr.push( function inner() {console.log(c)})
}
funcArr.forEach( fn => fn() )
정답 아래와 같다.
0
2
4
6
8
당연하다고 생각되시나요? 아래의 과정을 살펴봅시다.
ES6에서는 블럭이 생성되면서도 실행 컨텍스트가 실행됩니다. 실행 컨텍스트가 생성되면서 당연히 lexical environment도 생성되게 됩니다.
이때 선언되고 push 되는 () => console.log(c)
함수는 블럭의 실행 컨텍스트에서 선언되기 때문에 그때의 변수 c의 값을 참조한다.
그리고 각각의 c값을 참조하는 () => console.log(c)
함수를 funcArr에 push 해주는 겁니다.
이해가 쉽지 않으니 funcArr을 살펴봅시다.
위의 그림과 같이 funcArr의 함수들은 각각의 스코프를 갖게 되는 것입니다.
사실 렉시컬 스코프란 함수가 선언이 될 때 어디에 위치하느냐를 파악하면 되는 것이기 때문에 결과만 생각하면 간단하다.