변수 이름, 함수 이름, 클래스 이름과 같은 식별자가 본인이 선언된 위치에 따라 다른 코드에서 자신이 참조 될 수 있을지 없을지 결정 되는 것
function level scope(함수 레벨 스코프)
함수 레벨 스코프란 함수 내에서 선언된 변수는 함수 내에서만 유효하고 참조될 수 있으며 외부에서는 유효하지 않다.
var 키워드로 변수 선언 시 함수 레벨 스코프로 스코프가 지정된다.
block level scope(블록 레벨 스코프)
블록 단위 {} 내에서만 유효한 변수로 if, for, while, function 등의 {}가 있다.
let, const로 선언하면 해당 변수는 블록 레벨 스코프가 지정된다.
execution context가 실행중인 lexical environment에서 변수를 찾을 수 없다면 상위 lexical environment로가서 찾고 global에 도달할 때까지 계속된다.
이렇게 Environment가 연결돼있는 것을 스코프체인이라 함
일반적으로 동적 스코프와 정적 스코프로 구분한다.
자바스크립트는 정적 스코프를 사용하고 있다.
스크립트 전체, 코드블록, 호출된 함수는 모두 본인의 렉시컬 환경을 가지며 렉시컬 환경이 미치는 범위인 렉시컬 범위를 가진다.
렉시컬 환경의 구성
1. Environment Records
2. Outer Lexical Environment
더 자세히 들여다보면 아래 이미지와 같다
출처:https://meetup.nhncloud.com/posts/86
Outer Lexical Environment(외부 렉시컬 환경)은 함수가 호출될 때가 아닌 함수가 선언될 때의 외부 환경을 가리킨다.
var b;
function a (){
console.log('a');
var b = 'not b'
c()
}
function c(){
console.log(b)
}
a();
//결과는
a
undefined
왜 이렇게 출력되는지 살펴보자
function c
의 outer lexical environment는 전역이다.
전역의 변수 b는 undefined
이다.
function a
내에 var = 'not b';
로 b를 선언하긴하지만
var는 함수 레벨 스코프로 전역의 변수 b에 영향을 미치지 않는다.
클로저는 사실 자바스크립트 언어 명세에 없지만 많이 언급된다.
함수와 함수를 둘러싼 환경을 기억하고 있는 함수
함수를 둘러싼 환경이 앞에서 설명했던 렉시컬 스코프이다.
개념적으로는 모든 함수가 클로저이지만 우리는 모든 함수를 클로저로 부르지 않는다.
클로저인 사례와 아닌 사례를 보자
//1번 사례
function foo() {
var color = 'blue';
function bar() {
console.log(color);
}
bar();
}
foo();
//2번 사례
var color = 'red';
function foo() {
var color = 'blue';
function bar() {
console.log(color);
}
return bar;
}
var bad = foo();
bad();
어떤 사례가 클로저일까?
2번이다.
왜 그럴까.
1번 사례는 bar
는 foo
안에서 정의되고 호출됐을 뿐, foo
밖으로 나오지 않았기 때문에 클로저라 하지 않는다.
반대로 2번 사례는
bad
라는 변수에 foo
의 내부함수 bar
를 할당했고
bad
를 실행할 때 바로 bar
함수가 외부에서 실행됐으므로 클로저다.
bar
함수는 자신의 스코프에서 color를 찾았지만 찾을 수 없었고
outer environment인 foo
의 lexical environment에서 color
를 탐색
var color=blue
를 찾았으므로 blue를 출력했다.
여기서 다시 확인할 수 있는 것이 JS의 렉시컬 스코프는 선언 시 결정되는 것이다.
참고자료
https://meetup.nhncloud.com/posts/86 (⭐⭐)
https://velog.io/@cjkangme/JS-LexicalEnvironment-vs-VariableEnvironment
https://medium.com/@heoh06/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%A0%89%EC%8B%9C%EC%BB%AC-%ED%99%98%EA%B2%BD-9e6780022c5e (그림에 텍스트에 오류는 있으나 그림이 좋음 ⭐)
https://velog.io/@bathingape/%EC%8A%A4%EC%BD%94%ED%94%84Scope%EC%99%80-%ED%81%B4%EB%A1%9C%EC%A0%80Closure-%EC%9D%B4%ED%95%B4 ( ⭐)