[Javascript] 스코프, 클로저, 호이스팅

Dongjun Ahn·2022년 7월 13일


JavaScript에 대한 깊은 이해를 하기 위해서는 클로저(Closure), 스코프(Scope), 호이스팅(Hoisting)에 대해 알아야한다.

스코프(Scope)

scope의 사전적인 의미는 범위(유효 범위).

전역 스코프 (Global Scope)

전역 스코프는 변수가 함수 바깥이나 {}바깥에서 선언되어 있는 것을 뜻함.

var global = 'global';
function test(){
	console.log(global); // global
};

console.log(global); 	// global

지역 스코프 (Local Scope)

함수 레벨 스코프

함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.

var global = 'global';     // 전역변수

(function () {
  var local = 'local';   // 지역변수
})();

console.log(global); // global
console.log(local); // "local" is not defined

블록 레벨 스코프

최소 권한 노출의 원칙을 확장하여 정보를 함수 안에 숨기고 나아가 정보를 코드 블록안에 숨기기 위한 도구다.
우리가 변수를 {} 괄호 안에 const나 let키워드로 선언했을 때, 우리는 {}괄호 안에서만 이 변수에 접근할 수 있다. (ES6에서 새롭게 등장)

{
    const block = 'block-level-scope!'
    console.log(block) // 'block-level-scope!'
}

console.log(block) // Error, block is not defined

렉시컬 스코프 (Lexical scope)

흔히 "정적 범위", "정적 스코프"라고 번역. 렉시컬 스코프란, 함수를 어디서 호출하는지가 아니라 어떤 스코프에 선언하였는지에 따라 결정된다는 것이다.

var global = 'global';
function foo() {
	console.log(global); //
}
function bar() {
	var global = 'local';
	foo();
}

bar(); // global

bar()실행 값이 local로 나올것 같지만, foo()는 bar()에서 호출되든 어떤 함수 안에서 호출되든지 상관없이, 무조건 자기 자신의 스코프를 찾아보고 그 이후에는 전역 스코프를 찾기 때문에 global로 출력.
local이 나오게 하고싶으면 지역변수 var를 선언할 것이 아니라 전역변수 var의 값을 바꾸면 된다.

var global = 'global';
function foo() {
	console.log(global); //
}
function bar() {
	global = 'local';
	foo();
}

bar(); // local

클로저(Closure)

클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프)에 접근할 수 있는 함수이다.
쉽게 자신이 생성될때의 환경을 기억하는 함수.

var js = 'javascript';
function outer(){
    var js = 'js';
    function inner(){
  		console.log(js)
    }
    
    return inner;
}

let fn = outer();	
fn();			//js를 출력

let fn = outer(); 부분에서 outer함수는 실행 되고 종료 되어 콜스택에서 사라졌기 때문에 변수 js도 없어야한다. 하지만 fn에 할당된 inner함수를 실행 시켯을때 변수 js값이 잘 출력된다.
즉, 어떠한 외부 함수가 특정 내부 함수를 포함하고 있을 때, 외부 함수보다 내부 함수가 더 오래 살아있는 경우에는 외부 함수 밖에서 내부 함수를 호출해도 외부 함수의 지역 변수에 접근할 수 있다는 뜻이다.

클로저가 사용되는 경우

  1. 현재 상태를 기억하고 변경된 최신 상태를 유지해야 될 때
  2. 전역 변수의 사용을 줄이고 싶을 때
  3. 어떠한 정보를 숨기고 싶을 때

호이스팅(Hoisting)

함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것을 말한다.

변수 호이스팅

var 키워드를 사용해 선언했을때만 이루어진다.

console.log(hoisting); //undefined
var hoisting = "hoisting";
console.log(hoisting); // 'hoisting'

함수 호이스팅

함수 선언식일 경우에만 이루어진다.

fnHoisting1(); // fnHoisting1
fnHoisting2(); // Uncaught TypeError
// 함수 선언식
function fnHoisting1() {
  console.log("fnHoisting1");
};
// 함수 표현식
var fnHoisting2 = function() {
  console.log("fnHoisting2");
}
profile
Front-end Developer

0개의 댓글