스코프와 클러저 호이스팅은 자바스크립트에서 중요한 개념이다. 자바스크립트 개발하는데 위 개념을 몰라도 크게 상관없지만 프로젝트 크기가 커지고 개발의 범위가 넓어지면 변수참조에 대해 어려움을 겪기때문에 반드시 알아야하는 개념중 하나이다.
스코프는 참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 구분하여 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙이다.
스코프는 식별자의 유효범위이다.
전역 스코프는 변수가 함수 바깥이나 {}바깥에서 선언되어 있는 것을 뜻한다.
var globalvalue = 'test';
function test(){
console.log(globalvalue); //test
};
console.log(globalvalue); //test
자바스크립트는 초기에는 함수 레벨 스코프(function-level scope)를 따른다. 하지만 자바스크립트(ES6)는 함수 레벨과 블록 레벨의 렉시컬 스코프규칙을 따른다. (let, const)
var a = 10; // 전역변수
(function () {
var b = 20; // 지역변수
})();
console.log(a); // 10
console.log(b); // "b" is not defined
자바스크립트는 기본적으로 함수레벨스코프를 따른다.
{
const hello = 'Hello CSS-Tricks Reader!'
console.log(hello) // 'Hello CSS-Tricks Reader!'
}
console.log(hello) // Error, hello is not defined
함수의 상위 스코프를 결정하는데에는 두 가지 방법이 있다. 첫 번째 방법은 동적 스코프로 함수가 어디서 호출했는지에 따라 상위 스코프를 결정하고, 두 번째 방법은 렉시컬 스코프로 함수가 어디서 선언되었는지에 따라 상위 스코프를 결정한다.
아래 코드를 보자.
var x = 1;
function foo() {
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo(); // 1
bar(); // 1
위 예제의 함수 bar는 전역에 선언되었다. 따라서 함수 bar의 상위 스코프는 전역 스코프이고 위 예제는 전역 변수 x의 값 1을 두번 출력한다.
클로저는 독립적인 (자유) 변수를 가리키는 함수이다. 또는, 클로저 안에 정의된 함수는 만들어진 환경을 ‘기억한다’.
클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프)에 접근할 수 있는 함수
function outerFunc() {
var x = 10;
var innerFunc = function () { console.log(x); };
innerFunc();
}
outerFunc(); // 10
/**
* 함수 outerFunc를 호출하면 내부 함수 innerFunc가 반환된다.
* 그리고 함수 outerFunc의 실행 컨텍스트는 소멸한다.
*/
var inner = outerFunc();
inner(); // 10
함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것을 말한다.
아래 코드를 보자.
- 변수 호이스팅
console.log(hoisting); //undefined var hoisting = "success"; console.log(hoisting); // 'success'
- 함수 호이스팅
a(); function a() { console.log("a is not a function"); };