closure에 대해 알아보자!

jinn2u·2021년 8월 8일
0

js

목록 보기
1/4

MDN의 정의


말이 조금 어렵다...! 풀어서 이해해보자!


렉시컬 스코프란?

  • JS엔진은 함수를 어디서 호출했는지가 아니라 함수를 어디에 정의했는지에 따라 상위 스코프를 결정한다. 이를 렉시컬 스코프(정적스코프)라 한다.
  • 정확히 말하면 렉시컬 환경의 "외부 렉시컬환경(outer lexical scope)에 대한 참조"에 저장할 참조값, 즉 상위 스코프에 대한 참조는 함수가 정의되어 평가될 시점의 환경에 의해 결정된다. 이것이 렉시컬 스코프이다!
function init() {
  var name = "Mozilla"; 
  function displayName() { // displayName() 은 내부 함수이며, 클로저다.
	console.log(name) //Mozilla
  }
  displayName();
}
init();

위의 코드에서 보면 displayName 함수는 name이라는 지역변수를 가지고 있지 않다. 하지만 init을 실행한다면 mozilla는 잘 출력된다. 이는 displayName이 정의되는 시점에서 외부 렉시컬 환경 참조에 상위 스코프를 저장하였기 때문이다
따라서 자신만의 지역 변수를 가지고 있지 않기 때문에 this.name대신 상위 스코프의 name을 불러온다.


맛보기

function makeAdder(x) {
  var y = 1;
  return function(z) {
    y = 100;
    return x + y + z;
  };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2));  // 107 (x:5 + y:100 + z:2)
console.log(add10(2)); // 112 (x:10 + y:100 + z:2)

add5와 add10은 같은 makeAdder를 사용하지만 다른 맥락적 환경을 사용하기 때문에 다른 결과가 나온다!


활용하기

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

counter는 즉시실행함수이기 때문에 counter의 privateCounter에 접근할 방법이 없다. 하지만 내부함수changeBy는 상위 스코프의 변수인 privateCounter를 외부 렉시컬 환경 참조에 저장하고 있기 때문에 접근 할 수 있다.

참고-mdn

0개의 댓글