진짜 끝내주게 클로저 정리해놨는데 실수로 삭제했다. 다시 해야지.
클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경과의 조합.
스코프는 함수를 호출할 때가 아니라 함수를 어디에 선언했는지에 따라 달라진다. 이를 렉시컬 스코핑이라고 한다.
function outer(){
let x = 10;
let inner = function (){
console.log(x)
}
return inner
}
const innerFn = outer()
innerFn()
요것이 클로저. 클로저는 반환된 내부함수가 자신이 선언됐을 때 렉시컬 환경인 스코프를 기억하여 스코프 밖에서 호출되어도 스코프에 접근할 수 있는 함수. 즉, 클로저는 자신이 생성될 때의 렉시컬 환경을 기억하는 함수다.
let counter = 0;
function increase() {
return ++counter;
}
incleaseBtn.onclick = function () {
count.innerHTML = increase();
};
위 코드는 전역 변수를 지니고 있다. 변수 counter는 increse 함수가 관리하는 것이 옳다.
function increase() {
// 카운트 상태를 유지하기 위한 지역 변수
let counter = 0;
return ++counter;
}
incleaseBtn.onclick = function () {
count.innerHTML = increase();
};
increase 함수가 호출될 때마다 지역 변수가 초기화되어 변경 이전 상태를 기억 못 한다. 클로저로 고치장
const increase = (function () {
// 카운트 상태를 유지하기 위한 자유 변수
let counter = 0;
// 클로저를 반환
return function () {
return ++counter;
};
}());
incleaseBtn.onclick = function () {
count.innerHTML = increase();
};
즉시실행함수가 호출되고 변수 increase에 function () { return ++counter; }
가 할당된다. 변수 counter는 외부에서 직접 접근할 수 없는 private 변수가 되었다.
function Counter(){
let cnt = 0;
this.incre = function(){
return ++cnt
}
this.decre = function(){
return --cnt
}
}
const counter = new Counter()
console.log(counter.incre()) // 1
console.log(counter.incre()) // 2
console.log(counter.decre()) // 1
생성자 함수가 생성한 객체의 메소드는 객체의 프로퍼티에만 접근할 수 있는 것이 아니라 자신이 기억하는 렉시컬 환경의 변수에도 접근할 수 있다. 이때 생성자 함수 Counter의 변수 cnt는 this에 바인딩된 프로퍼티가 아니라 변수다. cnt가 this에 바인딩된 프로퍼티면 인스턴스를 통해 접근이 가능하지만 생성자 함수 내 변수라 외부 접근 불가능이다. 하지만 생성자 함수 Counter의 인스턴스의 메소드들은 클로저라서 자신이 생설됐을 때의 렉시컬 환경인 생성자 함수의 변수에 접근 가능!
참고 : https://poiemaweb.com/js-closure
코어 자바스크립트