클로저는 어떤 함수에서 선언한 변수를 참조하는 내부함수에서만 발생하는 현상이다.
어떤 함수 A에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달할 경우 A의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상
var outer = function () {
var a = 1;
var inner = function () {
return ++a;
};
return inner;
};
var outer2 = outer();
console.log(outer2()); // 2
console.log(outer2()); // 3
inner 함수의 실행 시점에는 outer 함수는 이미 실행이 종료된 상태인데 outer 함수의 LexicalEnvironment
에 어떻게 접근한 걸까?
-> 가비지 컬렉터의 동작 방식 때문이다.
outerEnvironmentReference
가 outer 함수의 LexicalEnvironment
를 필요로 할 것이므로 수집 대상에서 제외클로저는 어떤 필요에 의해 의도적으로 함수의 지역변수를 메모리를 소모하도록 함으로써 발생한다.
그렇다면 그 필요성이 사라진 시점에는 더는 메모리를 소모하지 않게 해주면 된다. (참조 카운트를 0으로)
var outer = function () {
var a = 1;
var inner = function () {
return ++a;
};
return inner;
};
var outer2 = outer();
console.log(outer2());
console.log(outer2());
outer = null; // outer 식별자의 inner 함수 참조를 끊음
var fruits = ["apple", "banana", "peach"];
var $ul = document.createElement("ul");
var afb = function (fruit) {
return function () {
alert("your choice is" + fruit);
};
};
fruits.forEach(function (fruit) {
var $li = document.createElement("li");
$li.innerText = fruit;
$li.addEventListener("click", afb(fruit));
$ul.appendChild($li);
});
클릭 이벤트가 발생하면 afb
함수의 실행 컨텍스트가 열리면서 afb
의 인자로 넘어온 fruit를 outerEnvironmentReference
에 의해 참조할 수 있다. 즉 afb
의 실행 결과로 반환된 함수에는 클로저가 존재
정보 은닉은 어떤 모듈의 내부 로직에 대해 외부로의 노출을 최소화해서 모듈간의 결합도를 낮추고 유연성을 높이고자 하는 개념.
접근 권한에는 public, private, protected가 있다.
var outer = function () {
var a = 1;
var inner = function () {
return ++a;
};
return inner;
};
var outer2 = outer();
console.log(outer2());
console.log(outer2());
위 예시에서 return한 변수는 공개(public), 그렇지 않은 변수는 비공개(private)
부분 적용 함수란 n개의 인자를 받는 함수에 미리 m개의 인자만 넘겨 기억시켰다가, 나중에 (n-m)개의 인자를 넘기면 비로소 원래 함수의 실행 결과를 얻을 수 있게끔 하는 함수이다.
var add = function () {
var result = 0;
for (var i = 0; i < arguments.length; i++) {
result += arguments[i];
}
return result;
};
var addPartial = add.bind(null, 1, 2, 3, 4, 5);
console.log(addPartial(6, 7, 8, 9, 10)); // 55
addPartial
함수는 인자 5개를 미리 적용하고, 추후 추가적으로 인자들을 전달하면 모든 인자를 모아 원래의 함수가 실행되는 부분 적용 함수이다.
커링 함수란 여러 개의 인자를 받는 함수를 하나의 인자만 받는 함수로 나눠서 순차적으로 호출될 수 있게 체인 형태로 구성한 것을 말한다. (커링은 한 번에 하나의 인자만 전달하는 것을 원칙으로 한다.)
const logger = (store) => (next) => (action) => {
console.log("dispatching", action);
console.log("next state", store.getState());
return next(action);
};
위 예제는 store, next, action 순서로 인자를 받는다. 이 중 store, next는 프로젝트 내에서 한 번 생성된 이후로는 바뀌지 않는 속성이지만 action의 경우는 매번 달라진다.
즉, store와 next의 값이 결정되면 logger에 store와 next를 미리 넘겨서 반환된 함수를 저장시켜놓고, 이후에는 action만 받아서 처리할 수 있게 한다.