Scope란?
영어 단어의 뜻 자체는 영역, 범위를 말한다. 하지만 프로그램 언어에서의 유효범위는 어느 범위까지 참조하는지, 변수와 매개변수의 접근성과 생존기간을 뜻한다. 자바스크립트는 이 규칙대로 식별자를 찾는다.
let username="kimcoding";
if(username){
let message=`Hello, ${username}!`;
console.log(message);
}
console.log(message);
첫번째 콘솔 출력은 "Hello, kimcoding!"으로 잘 나오지만, 두번째 콘솔 출력은 에러를 발생한다. 그 이유는 message라는 변수가 중괄호 안쪽에서 선언 되었기 때문이다.
그래서 두번째 콘솔 출력에서는 message라는 변수에 접근할 수 없기 때문에, 에러가 발생한다.
이처럼 변수에 접근할 수 있는 범위가 있다. 중괄호 안쪽은 안쪽 스코프라 부르고, 전체 부분은 바깥쪽 스코프라 부른다.
바깥쪽 스코프에서 선언한 변수는 안쪽 스코프에서 사용이 가능하다.
하지만, 안쪽 스코프에서 선언한 변수는 바깥쪽 스코프에서 사용할 수 없다.
스코프는 중첩이 가능하다.
가장 바깥쪽의 스코프는 전역 스코프(Global Scope)라 부르고, 나머지 스코프들은 지역 스코프(Local Scope)라 부른다.
전역 스코프에서 선언한 변수는 전역 변수이고, 지역 스코프에서 선언한 변수는 지역 변수이다.
대부분의 C-family language는 블록 레벨 스코프를 따른다. 블록 레벨 스코프란 코드 블록내에서 유효한 스코프를 말한다.
자바스크립트는 함수 레벨 스코프를 따른다. 함수 레벨 스코프란 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다는 것이다.
하지만 ECMAScript 6에서 도입된 let 키워드를 통해 블록 레벨 스코프를 사용할 수 있다.
또한 유의할 점이 있는데, 화살표 함수를 사용하면 블록 스코프로 취급된다.
Closure란?
“A closure is the combination of a function and the lexical environment within which that function was declared.”
클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경(Lexical environment)과의 조합이다.
MDN에서 정의하는 내용이지만, 무슨 의미인지 이해하기 어렵다.
코드를 통해서 이해해보도록 하자.
const globalVar = '전역 변수';
function outerFn() {
const outerFnVar = 'outer 함수 내의 변수';
const innerFn = function() {
return 'innerFn은 ' + outerFnVar + '와 ' + globalVar + '에 접근할 수 있습니다.';
}
return innerFn;
}
outerFn
에서는 변수 globalVar
에 접근할 수 있다.innerFn
에서는 변수 globalVar
과 함수 outerFn
내부의 outerFnVar
에 접근할 수 있다.즉, 두 가지 조합을 찾을 수 있었다.
클로저는 함수와 그 함수가 접근할 수 있는 변수의 조합이라 생각하면 된다.
const globalVar = '전역 변수';
function outerFn() {
const outerFnVar = 'outer 함수 내의 변수';
const innerFn = function () {
return (
'innerFn은 ' + outerFnVar + '와 ' + globalVar + '에 접근할 수 있습니다.'
);
};
return innerFn;
}
const innerFnOnGlobal = outerFn();
const message = innerFnOnGlobal();
console.log(message); // ?
innerFnOnGlobal
은outer
내부의innerFn
의 주소값을 가진다.
innerFnOnGlobal
을 호출할 때,innerFn
밖에 있기 때문에outerFnVar
에 접근하지 못한다 생각할 수 있지만, 실제로 접근할 수 있다.
그 이유는,
innerFn
함수가 최초 선언되었던 환경에서는outerFnVar
에 접근할 수 있기 때문이다. 이러한 클로저의 개념으로 콘솔 출력이 잘 되는걸 확인할 수 있다.