# Closure(폐쇠)

변수의 유효범위에 대한 이해가 필요하다(Lexical scoping)

Javascript는 함수도 리턴할 수 있다. ⇒ 함수를 포함하고 있는 상태인 Closure (함수 공장)

function outerFn() {
	let outerVar = 'outer';
	console.log(outerVar);

	function innerFn() {
	let innerVar = 'inner';
	console.log(innerVar);
	}
	return innerFn;
}

let out = outerfn();
/* 
	outer
<return
	innerFn() {
	let innerVar = 'inner';
	console.log(innerVar);
	} 
*/

결론적으로 오직 하나의 메소드를 가지고 있는 객체를 일반적으로 사용하는 모든 곳에 클로저를 사용할 수 있다. - MDN

# 유용한 클로저

동적 웹페이지를 구현 할때 기능적인 함수를 내장하여 편리하게 사용할 수 있다.

function makeSizer(size) {
  return function() {
    document.body.style.fontSize = size + 'px';
  };
}

# 클로저를 이용해서 프라이빗 메소드(private method) 흉내 내기

모듈 패턴 (opens new window)으로 이용할 수 있다

var counter = (function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  };
})();

console.log(counter.value()); // logs 0
counter.increment();
counter.increment();
console.log(counter.value()); // logs 2
counter.decrement();
console.log(counter.value()); // logs 1

변수에 할당하여 각각 독립적인 함수로 활용할 수 있다.

유효 Scope 의 차이로 인한 서로의 변수를 침해하지 않기에 정보를 은닉하고 캡슐화 할 수 있는 이점을 가져온다

예시를 보자

var makeCounter = function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  }
};

var counter1 = makeCounter();
var counter2 = makeCounter();
alert(counter1.value()); /* 0 */
counter1.increment();
counter1.increment();
alert(counter1.value()); /* 2 */
counter1.decrement();
alert(counter1.value()); /* 1 */
alert(counter2.value()); /* 0 */

그렇다면 clousure의 스코프 체인을 알아볼 필요가 있다

# clousure Scope chain

모든 클로저에는 세가지 스코프(범위)가 있다.

  • 지역 범위 (Local Scope, Own scope)
  • 외부 함수 범위 (Outer Functions Scope)
  • 전역 범위 (Global Scope)
function showHelp(help) {
  document.getElementById('help').innerHTML = help;
}

// 아래 주석을 참조하면 아래 func을 통과하지 않고도 구현 가능하다
function makeHelpCallback(help) { 
  return function() {
    showHelp(help);
  };
}

function setupHelp() {
  var helpText = [
      {'id': 'email', 'help': 'Your e-mail address'},
      {'id': 'name', 'help': 'Your full name'},
      {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];

  for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];  /// var keyword 를 let 으로 변경하여 Scope를 변경하자
    document.getElementById(item.id).onfocus = makeHelpCallback(item.help);
  }
}

setupHelp();
© Devlog from jeong