Scope와 Closure

임경섭·2023년 4월 18일
0
post-custom-banner

Scope란?

Scope란?
영어 단어의 뜻 자체는 영역, 범위를 말한다. 하지만 프로그램 언어에서의 유효범위는 어느 범위까지 참조하는지, 변수와 매개변수의 접근성과 생존기간을 뜻한다. 자바스크립트는 이 규칙대로 식별자를 찾는다.

예제로 알아보는 스코프

let username="kimcoding";
if(username){
	let message=`Hello, ${username}!`;
    console.log(message);
}

console.log(message);

첫번째 콘솔 출력은 "Hello, kimcoding!"으로 잘 나오지만, 두번째 콘솔 출력은 에러를 발생한다. 그 이유는 message라는 변수가 중괄호 안쪽에서 선언 되었기 때문이다.
그래서 두번째 콘솔 출력에서는 message라는 변수에 접근할 수 없기 때문에, 에러가 발생한다.

이처럼 변수에 접근할 수 있는 범위가 있다. 중괄호 안쪽은 안쪽 스코프라 부르고, 전체 부분은 바깥쪽 스코프라 부른다.

바깥쪽 스코프에서 선언한 변수는 안쪽 스코프에서 사용이 가능하다.
하지만, 안쪽 스코프에서 선언한 변수는 바깥쪽 스코프에서 사용할 수 없다.

전역 스코프(Global Scope), 지역 스코프(Local Scope)

스코프는 중첩이 가능하다.
가장 바깥쪽의 스코프는 전역 스코프(Global Scope)라 부르고, 나머지 스코프들은 지역 스코프(Local Scope)라 부른다.

전역 스코프에서 선언한 변수는 전역 변수이고, 지역 스코프에서 선언한 변수는 지역 변수이다.

자바스크립트 스코프의 특징

대부분의 C-family language는 블록 레벨 스코프를 따른다. 블록 레벨 스코프란 코드 블록내에서 유효한 스코프를 말한다.
자바스크립트는 함수 레벨 스코프를 따른다. 함수 레벨 스코프란 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다는 것이다.
하지만 ECMAScript 6에서 도입된 let 키워드를 통해 블록 레벨 스코프를 사용할 수 있다.

또한 유의할 점이 있는데, 화살표 함수를 사용하면 블록 스코프로 취급된다.

Closure란?

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;
}
  1. 함수 outerFn에서는 변수 globalVar에 접근할 수 있다.
  2. 함수 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); // ?

innerFnOnGlobalouter내부의 innerFn의 주소값을 가진다.
innerFnOnGlobal을 호출할 때, innerFn밖에 있기 때문에 outerFnVar에 접근하지 못한다 생각할 수 있지만, 실제로 접근할 수 있다.

그 이유는, innerFn함수가 최초 선언되었던 환경에서는 outerFnVar에 접근할 수 있기 때문이다. 이러한 클로저의 개념으로 콘솔 출력이 잘 되는걸 확인할 수 있다.

profile
즐겁게 코딩 ૮₍ •̀ᴥ•́ ₎ა
post-custom-banner

0개의 댓글