외부함수에서 자신이 선었됬을떄의 (lexical environment)을 기억해 외부함수의 scope에 접근할 수 있는것을 말한다.자바스크립트에서 클로저는 함수가 생성될때마다 생성된다.
var base = 'Hello, ';
function sayHelloTo(name) { //외부함수
var text = base + name;
return function() { //자기자신 함수
console.log(text);
};
}
var hello1 = sayHelloTo('승민');
var hello2 = sayHelloTo('현섭');
var hello3 = sayHelloTo('유근');
hello1(); // 'Hello, 승민'
hello2(); // 'Hello, 현섭'
hello3(); // 'Hello, 유근'
출력된 결과를 보면 text 변수가 동적으로 변화하고 있는 것처럼 보인다.
실제로는 text라는 변수 자체가 여러 번 생성된 것이다.
즉, hello1()과 hello2(), hello3()은 서로 다른 환경을 가지고 있다
힘수의 실행 컨텍스트가 생성될 때 ,함수의 lexical environment도 생성된다.
이 실행컨텍스트의 lexical environment에는 함수의 지역변수의 정보, 이 함수의 상위 스코프의 대한 정보가 들어있다.
외부함수의 생명 주기가 종료되더라도 내부함수가 선언되었을때의 렉시컬 환경을 기억해 외부함수의 스코프에 접근할 수 있기 떄문이다,
클로저는 상태(state)를 안전하게 변경하고 유지하기 위해 사용한다.
상태가 의도치 않게 변경되지 않도록 상태를 안전하게 은닉(information hiding)하고,
특정 함수에게만 상태변경을 허용하기 위해 사용한다.
전역변수가 많으면 어디에서든 실수로라도 접근을 할 수 있기 때문에 최대한 전역변수를 줄여서 코드를 해야합니다.
클로저 함수는 외부 함수의 실행이 끝나더라도 외부 함수 내 변수를 사용할 수 있다.
클로저는 이처럼 특정 데이터를 스코프 안에 가두어 둔 채로 계속 사용할 수 있게하는 폐쇄성을 갖는다
const btn = document.querySelector('button')
btn.addEventListener('click',handleClick())
function handleCilck(){
let count = 0
return function (){
count++
return count
}
}
클로저 함수를 각각의 변수에 할당하면 각자 독립적으로 값을 사용하고 보존할 수 있다.
이와 같이 함수의 재사용성을 극대화로 함수 하나를 독립적인 부품의 형태로 분리하는 것을 모듈화라고한다.
클로저를 통해 데이터와 메소드를 묶어다닐 수 있기에 클로저는 모듈화에 유리하다
const newTag = function(open, close) {
return function(content) {
return open + content + close
}
}
const bold = newTag('<b>', '</b>')
const italic = newTag('<i>', '</i>')
console.log(bold(italic("This is my content!"))) //<b><i>This is my content!</i></b>
값을 확인할 수 있고 변경도 할 수 있다
캡슐화를 통한 은닉화로 정보의 접근을 제한할 수 있다.
const myObj = {
count: 0,
up() {
this.count++;
console.log(this.count);
},
};
myObj.up(); // 1
myObj.up(); // 2
myObj.up(); // 3
myObj.count = 0;
myObj.up(); // 1
up을 호출할 때마다 숫자가 올라가는 것을 확인할 수 있다.
하지만 객체 내부 프로퍼티인 count에 직접 접근하여 숫자를 임의로 변경시킬 수 있다.
만약 악의적인 코드나 실수로 외부에서 내부 프로퍼티를 조작하면 프로젝트에 손상을 줄 수도 있는 것이다.
function counter() {
let count = 0;
return {
up() {
count++;
console.log(count);
},
};
}
const myCount1 = counter();
myCount1.up(); // 1
myCount1.up(); // 2
myCount1.up(); // 3
myCount1.count = 0;
myCount1.up(); // 4
myCount1.count = 0; 으로 새로운 프로퍼티를 추가하였다.
하지만 up메서드는 기존에 참조하던 외부환경의 count를 여전히 사용하여 원하는 결과를 출력하는 것을 볼 수 있다.
가비지콜렉터에 정리 대상이 되어야 할 것들이 메모리 상에 남아 있게 되므로, 남발 시 비효율적인 메모리 사용을 하게 된다.