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

Dongjun Ahn·2022년 7월 13일
0


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개의 댓글