본문 바로가기
Javascript

JS 스코프와 클로저

by SeanK 2021. 10. 21.

 

 

오늘은 자바스크립트의 스코프와 클로저에 대해 알아보자. 

사실 이부분 공부하면서 머리에 쥐가...

 

 

중요한 개념인데 겁나 헷갈린다.

 

 

스코프란?

 

 

Scope in JavaScript refers to the current context of code, which determines the accessibility of variables to JavaScript. The two types of scope are local and global:


스코프란 현재 코드의 문맥을 의미하며 자바스크립트 변수의 접근성을 결정한다.
스코프는 로컬과 글로벌로 나뉜다.

 

Global variables are those declared outside of a block
블록 밖에서 선언된 변수는 글로벌
Local variables are those declared inside of a block
블록 안에서 선언된 변수는 로컬

 

 

 

함수/블록 스코프

 

 

스코프에는 함수/블록 스코프 이렇게 두가지 종류로 나뉜다. (혹은 글로벌/로컬/블록 요렇게 세개로 나눈다.)

 

 

함수스코프(로컬스코프)

 

Variables declared inside a function is inside the local scope. They can only be accessed from within that function, that means they can’t be accessed from the outside code.

 

 

블록스코프 (화살표 함수 포함)

 

ES6 introduced let and const variables, unlike var variables, they can be scoped to the nearest pair of curly braces. That means, they can’t be accessed from outside that pair of curly braces.

 

 

 

이렇게 스코프의 종류를 구분하는 이유는 변수의 종류에 따라 특정 스코프는 따르되, 

어떤 스코프는 무시하는 경우가 발생하기 때문이다. 

 

위의 블록스코프의 설명을 보면 Var변수에 대한 언급이 나오는데 'unlike var variables'라며 Var변수는 블록스코프의 설명에서 제외시키는 것을 볼 수 있다. 

 

왜냐하면 var은 아래와 같은 특징을 가지기 때문이다. 

 

  • var는 블록스코프를 무시한다. 
  • var는 함수스코프를 따른다.
  • var는 화살표 함수의 블록스코프를 따른다.

블록스코프 무시한다며... 왜 화살표 함수 블록스코프는 따르는건데...

 

표로 정리하자면 아래와 같다.

 

  let const  var
유효 범위 블록 스코프 및 함수 스코프 블록 스코프 및 함수 스코프 함수 스코프
값 재할당 가능 불가능 가능
재선언 불가능 불가능 가능

 

 

 

이해가 잘 안되니 예제를 살펴보자.

수업자료중 괜찮은 예제를 뽑아왔다. 

 

 

아래 코드에서 변수 result의 값이 무엇일까?

let x = 30;

function get () { return x; }
function set (value) { x = value; }

set(10);
let result = get(20);

정답: 10

 

 

 

 

 

클로저란?

 

 

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment).

 

 

 

클로저의 개념은 한 번에 이해하기가 힘들다. MDN의 정이마저도 굉장히 추상적이다. "Lexical environment" 언어적 환경을 참조하는 함수 뭉치의 혼합...?

 

 

 

개인적인 느낌을 말하자면... 클로저란 포스트잇 같은 존재랄까... 작업할 때 참고해야할 정보들이 있는데 A4로 인쇄해서 폴더에 넣긴 애매한 정보들이라 포스트잇으로 따로 붙여준다는 느낌이 있다. 

그리고 다른 서류작업을 할 때 포스트잇 정보가 필요하면 벽에 붙여뒀던걸 떼와서 서류에 같이 합쳐주는...!

(지극히 개인적인 견해입니다...)

 

 

 

클로저 함수의 특징

 

  • 함수를 리턴하는 함수
  • 내부함수는 외부함수에 선언된 변수에 접근 가능

 

원래라면 계산이 끝난 외부함수의 변수데이터는 사라져야 정상이지만 내부함수의 언어적 환경을 보존하기 위해 외부함수의 변수를 기억한다.

 

 

활용

 

데이터 보존 혹은 정보의 접근 제한

 

그렇다면 클로저는 왜 사용하는 것일까? 그것은 바로 데이터 보존과 정보의 접근 제한에 유용하기 때문이다. 

아래의 예제를 살펴보자.

 

const makeCounter = () => {
	let value = 0;
    
    return {
    	increase: () => {
        	value = value + 1
        },
        decrease: () => {
        	value = value - 1
        },
        getValue: () => value
    }
}

const counter1 = makeCounter();

 

위의 코드에서 내부스코프에 위치한 value값을 외부에서 직접적으로 변경할 수 없게 된다. 왜냐하면 선언과 할당이 makeCounter라는 내부함수에서 이루어 졌기 때문이다. (블록스코프)

 

즉 정보의 접근이 제한되며 (캡슐화) 데이터가 보존된다.

 

따라서 클로저를 이용하면 불필요한 전역변수 사용을 줄이고 데이터를 안전하게 다룰 수 있게 된다

 

 

예제

 

function Person(firstname, lastname) {
	let fullName = firstname + " " + lastname;

	this.getFirstName = function () { return firstname; };
	this.getLastName = function () { return lastname; };
	this.getFullName = function () { return fullName; };
}

let aPerson = new Person ("John", "Smith");

console.log(aPerson); // --> 1번

aPerson.firstname = "Penny";
aPerson.lastname = "Andrews";
aPerson.fullName = "Penny Andrews";

console.log(aPerson); // --> 2번
console.log(aPerson.getFirstName()); // --> 3번
console.log(aPerson.getLastName()); // --> 4번
console.log(aPerson.getFullName()); // --> 5번

1번 출력값

Person {getFirstName: ƒ, getLastName: ƒ, getFullName: ƒ}
	firstname: "Penny"
	fullName: "Penny Andrews"
	getFirstName: ƒ ()
	getFullName: ƒ ()
	getLastName: ƒ ()
	lastname: "Andrews"
	[[Prototype]]: Object

 

 

 

 

 

'Javascript' 카테고리의 다른 글

JS 내장 고차함수  (0) 2021.10.24
JS Reduce 메소드  (0) 2021.10.21
JS 원시타입과 참조타입  (0) 2021.10.20
JS 배열과 객체  (0) 2021.10.16
JS 반복문  (0) 2021.10.08