본문 바로가기

필사적 필사

자바스크립트 문법 (9) 클로저

본 게시글은 아래의 글을 필사하였습니다.

https://webdoli.tistory.com/71?category=833233

 

자바스크립트 문법 (9) 클로저

(9) 클로저 클로저는 자바스크립트 함수의 꽃이라는 표현을 많이 사용한다. 아마도 다른 프로그램 언어에서 찾아볼 수 없는 자바스크립트만의 유연함과 독특함이 접목된 부분이 클로저이기 때문이 아닐까한다. 기..

webdoli.tistory.com

클로저는 자바스크립트 함수의 꽃이라는 표현을 많이 사용한다. 아마도 다른 프로그램 언어에서 찾아 볼 수 없는 자바스크립트많의 유연함과 독특함이 접목된 부분이 클로저이기 때문이 아닐까한다. 기존 프로그래밍 언어의 상식에서, 함수 내의 변수값은 함수 내에서만 사용할 수 있다. 함수 밖에서 함수내의 함수값에 접근할 수가 없다.

하지만 자바스크립트의 클로저를 사용하면 함수 밖에서 함수안의 변수값을 사용하고, 임시 저장을 할 수가 있게 된다. 단, 클로저를 사용하려면, 익명함수를 사용해서 함수 안의 변수를 밖으로 return 해야 한다. 아래의 클로저 예시를 보자.

function closure(value) {
  var data1 = value;
  return function() {
    return ++data1;
  }
}

var myClosure = closure(10); //#1

console.log(myClosure()); // 결과 : 11
console.log(myClosure()); // 결과 : 12

 

위의 closure 함수가 return 값으로 같은 '함수'를 사용하고 있다는 점을 주목하자. 익명함수는 return값으로 closure 함수의 data1변수값을 사용한다.

클로저를 사용하려면 주의해야할 부분이 #1이다. 만일 console.log(myClosure);이라고 입력한다면, function() { ...... } 값이 console에 나온다. 함수값이 반환되는 것이다. 또한, 리턴값으로 익명함수를 사용하지 않으면, 다음과 같은 결과가 나온다.

function closure(val) {
  var result = val;
  result++;
  return result;
}

var myClosure = closure(10);

console.log(myClosure); // 결과 : 11
console.log(myClosure); // 결과 : 11
console.log(myClosure); // 결과 : 11

따라서 클로저를 사용하려면, myClosure이란 변수를 생성한 뒤에, 이 변수의 값을 함수로 사용해야 하며, 클로저 구문의 return 값을 익명함수로, return이 두 번 나와야 한다. 익명함수가 리턴될때, call 객체가 myClosure 변수에 저장되고, 그 속에 있는 data1 값이 저장이 되는 원리다. 그 결과, myClosure 변수를 함수로 호출했을 때, data1값은 myClosure 변수에 저장되어 계속 사용할 수 있게 된다.

클로저의 핵심은 '함수를 반환하고' 이를 변수에 저장해서 메모리로 사용하는 데에 있다. 클로저와 관련된 흥미로운 예시를 또 하나 살펴보자.

function closure( value ){
  var data1 = value;
  return function( ){
    return ++data1;
  }
}

var myClosure1 = closure(1); 
var myClosure2 = closure(100);

console.log( myClosure1( ) );
console.log( myClosure2( ) );
console.log( myClosure1( ) );
console.log( myClosure2( ) );

// 결과: 
// 1
// 101
// 2
// 102

myClosure1과 myClosure2는 익명함수를 반환받았다. myClosure1과 2를 호출할 때마다 그 속에 저장된 변수인 data1은 계속 사용된다. (NO 갱신) 만일, 클로저의 인수값을 활용하고 싶다면 아래처럼 작성해도 된다.

function closure(value) {
  var data1 = value;
  return function(data2) {
    var data3 = data2 + 100;
    return [++data1, data3]
  }
}

var closure1 = closure(1);
var closure2 = closure(300);

console.log(closure1(1));
console.log(closure2(3));
console.log(closure1(10));
console.log(closure2(50));

// 결과 
// [2, 101]
// [301, 103]
// [3, 110]
// [302, 150]