자바스크립트의 클로져

jh_leitmotif·2022년 2월 3일
1

JS 개념 정리

목록 보기
2/4

개요

원론적인 부분을 하나 둘 씩 정리하고 있습니다.

단순히 검색만 잘하지.. 정확히 이해하고 사용하지 못한다는 기분이 계속 드네요.

특히 클로져라는 개념은 굉장히 추상적인 것 같기도 하고... 너무 헷갈립니다.

맞게 이해하고 있는지는 솔직히 잘 모르겠지만, 일단 저의 말로 정리해봅니다.

Closure를 알기 전에, Scope!

Scope는 알기 쉽습니다. '범위' 이고, 우리가 충분히 알고 있는 전역, 지역으로 구분됩니다.

let test1 = 1; // 전역(Global)

function test2Func(){
	let test2=1; // 지역 (Local)
    console.log(test1);
    console.log(test2);
}

위와 같은 js 파일이 있다고 했을 때, test1는 전역에 선언된 변수로서 변할 수 있지만, 어쨌든 초깃값이 1로 지정되어있습니다.

그리고 test2Func 라는 함수 환경은 전역에 선언된 test1에 접근할 수 있고, 그리고 지역적으로 선언된 동적 변수인 test2를 가지고 있습니다.

그런데 만약?

let test1 = 1;

function test2Func(){
	let test1 = 100;
    console.log(test1);
}

test2Func()
console.log(test1)

이렇게 된다면 어떻게 될까요?

이 경우, test2Func()는 단독의 함수 Scope로서 우선 지역 변수에 test1 이라는 것이 있는지 찾아봅니다. 만약 선언된 지역 변수가 없었다면, 전역 변수로 접근해 '1'을 출력했겠지만 여기에선 지역 변수가 있기에 100을 출력하게 됩니다.

그리고 마지막 console.log()는 전역 Scope에 있기에 1을 출력하겠죠.

Closure는 뭐야?

영어로 직역하면, '폐쇄'라는 의미를 가지고 있습니다만....

사고를 살짝 전환하면 어떠한 Scope로서 한정시켜둔다... 라고도 생각이 듭니다.

function count(){
	let count=0;
    return function(){
    	return count++;
    }
}

let counter = count()

counter()
counter()
counter()

예를 들어서... 위와 같이 함수를 반환하는 count() 함수가 있다고 가정합니다.

반환되는 함수의 반환 값은 count++입니다.

즉, 내부 함수가 외부에 선언된 count를 접근 가능한 Scope 상태입니다.

여기서, 전역에 선언된 counter라는 변수에는 반환되는 익명 함수가 할당됩니다.

어라...그러면
counter라는 전역에 선언된 변수가 count() 함수의 내부 익명 함수가 되어버리면
counter가 곧 함수 Scope화가 되어서, count()에 있는 count 변수가 유지되겠네?

function count(){
	let count=0;
    return count++;
}

let counter = count();

console.log(counter)

함수가 아니라 단순히 변수만 return 하도록 한다면?
여기에서 counter는 그저 반환된 변수일 뿐, 어떠한 Scope가 되지 않을 겁니다.

그렇다면 아무리 counter를 호출해도, 그냥 0만 출력되겠죠.

즉, 전자와 같이 중첩된 함수 구조에서 그 내부 함수가 할당된 변수는 계속해서 그 외부함수의 환경을 유지하게 되어 let count=0 이라는 지역 변수에 지속적으로 접근할 수 있게 됩니다.

이러한 형태에 대해, 'Closure' 라고 부른다고 이해했습니다.

예시 만들어보기 // 1

function sumTriple(x){
  let y = 2;
  return function(z){
    return x+y+z;
  }
}

let test1 = sumTriple(2);

test1(2)

예를 들어 단순히 3개의 숫자를 더하는 이런 함수가 있다고 합니다.

let test1 = sumTriple(2)

여기에서, test1은 함수적 Scope를 지니게 되고, x=2, y=2 라는 상태가 저장된 상태로 유지됩니다.

이 때 test1(2)를 부르면, 반환된 익명함수에서 z=2가 반영되어 2+2+2 = 6이 됩니다.

예시 만들어보기 // 2

function pet(name){
  return{
    name:function(){
      return name;
    },
    setName:function(_name){
      name=_name;
    }
  }
}

const dog = pet('초코')

dog.name()

dog.setName('누렁이')

dog.name()
const dog = pet('초코')

이를 통해 dog이라는 변수는 pet 이라는 함수의 Scope를 유지하게 되며, name에 '초코'라는 문자열을 저장하여 가지고 있습니다.

dog.name()을 호출하면 '초코'가 나오고

dog.setName('누렁이')를 호출하면 저장되어 있던 name이 '누렁이'로 바뀝니다.

마치 Java의 클래스를 다룰 때, private으로 지정된 멤버를 다루는 듯한 느낌입니다.

클로저를 사용하는 이유?

  1. 데이터의 보존이 가능하다.
  2. 캡슐화를 통해 정보를 감출 수 있다. (은닉성)
  3. 모듈형태로 분리가 가능하다.

클로저 vs 클래스

클로저는 단일 함수를 반환하나, 클래스는 해당 객체에 대해 여러가지 메소드를 선언할 수 있다는 점이 있습니다.

클로저는 여러가지 프로퍼티가 정의된 객체를 반환함으로서 그것을 모방할 수도 있습니다.

profile
Define the undefined.

0개의 댓글