let outer = function () {
let a = 1;
const inner = function () {
console.log(a++)
};
inner();
};
outer();
outer 함수 내에서 변수 a를 선언했고, 내부의 inner 함수에서 outer 의 변수 a를 참조 하고 있음
inner 함수 내에서는 a를 찾지 못하고, outerEnvironmentReference에 지정된 outer의 LexcialEnvironment에서 a를 찾음
outer 함수의 실행 컨텍스트가 종료되면 LexicalEnvironment에 있는 a, inner 참조를 삭제 함
각 주소에 저장된 값은 참조 하는 대상이 없으므로 가비지 컬렉터의 대상이 됨
`
let outer = function () {
let a = 1;
const inner = function () {
return ++a;
};
return inner();
};
var outer2 = outer();
console.log(outer2) // 2
console.log(outer2) // 2
inner 함수에서 a를 사용함, outer가 inner 함수의 값**을 리턴하므로 outer 함수의 실행 컨텍스트가 종료되는 시점에 a변수를 참조하는 대상이 없어짐. a, inner 변수 값들은 언젠가 가비지 컬렉터의 대상이 됨
let outer = function () {
let a = 1;
const inner = function () {
return ++a;
};
return inner;
};
var outer2 = outer();
console.log(outer2()) //2
console.log(outer2()) //3
inner 함수의 결과가 아닌 inner 함수 자체를 리턴함
inner 함수에서는 outer 함수 내부에서 선언됐으므로, outer 함수의 LexicalEnvironment가 담겨있음
outer2에서 inner 를 참조 하고 inner 에서 a를 참조 하므로, 가비지 컬렉터의 대상이 아님
함수를 선언할때 만들어지는 유효범위가 사라진 후에도 호출할수 있는 함수 (private하게 감출수 있음)
클로저의 메모리 관리
let outer = function () {
let a = 1;
const inner = function () {
return ++a;
};
return inner();
};
var outer2 = outer();
console.log(outer2); //2
console.log(outer2); //3
outer2 = null; // 연결 관계 끊어버리기, outer의 LexcialEnviromnet는 이제 가비지 컬렉터의 대상이 됨
클로저 활용 사례
콜백 함수 내부에서 외부데이터를 사용하고자 할 때
var fruits = ["apple", "banana", "peach"];
var $ul = document.createElement("ul")
fruits.forEach(function (fruit) {
var $li = document.createElement("li");
$li.innerText = fruit;
$li.addEventListener('click', function (){
alert(' your choice is ' + fruit)
$ul.appendChild($li);
})
})
document.body.appendChild($ul);
접근 제어 (정보 은닉)
어떤 모듈의 내부 로직에 대해 외부 노출을 최소화 하여 모듈 간 결합도를 낮추고, 유연성을 높인다.
클로저를 이용하여 public, private 한 값을 구분한다.
외부에 제공하고자 하는 정보들을 모아서 리턴하고, 내부에서만 사용할 정보는 return 하지 않는다. (비공개 멤버)
var createCar = function () {
var fuel = Math.ceil(Math.random() * 10 + 10);// 연료ㅗ
var power = Math.ceil(MAth.random() * 3 + 2); //연비
var moved = 0;
//Object.freeze로 변경을 막는다.
return {
get: function () {
return this.moved;
},
run: function () {
var km = Math.ceil(Math.random() + 6);
var wasteFuel = km / this.power;
if (this.fuel < wasteFuel) {
console.log("이동 불가")
return;
}
this.fuel -= wasteFuel;
this.moved += km;
console.log(km + 'km 이동 (총 ' + this.moved + 'km)')
}
}
}
var car = createCar();
car.run();
console.log(car.moved);
car.run();
부분 적용 함수 (partially applied function)
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