더 이상 필요하지 않은 데이터가 해제되지 못하고 메모리를 차지하고 있는 현상
window.hello = 'Hello World';
window.user = { name : "happy", age : 85 };
window 객체는 브라우저에서 항상 존재해야 하므로 window 객체의 속성으로 등록된 데이터들은 가비지 컬렉션을 통해 발견되더라도 사용하고 있다고 판단하여 메모리가 해제되지 않는다.
따라서 어떤 데이터를 등록할 때는 꼭 필요한 경우가 아니라면 window 객체의 속성으로 데이터를 저장하지 않는 것이 좋다.
const btn = document.querySelector('button')
const parent = document.querySelector('.parent')
btn.addEventListener('click', () => {
console.log(parent);
parent.remove();
})
remove 버튼을 눌러 parent 요소를 삭제했음에도 불구하고 버튼을 클릭하면 계속 parent 요소가 출력됨
그 이유는 이벤트 발생하기 전에 parent 요소의 내용을 parent
라는 이름의 변수로 메모리에 저장해놨기 때문.
그렇기 때문에 console.log(parent);
를 실행하면 html에서 parent 요소가 출력되는 것이 아니라 이미 메모리에 저장된 내용이 출력되는 것임
const btn = document.querySelector('button')
btn.addEventListener('click', () => {
const parent = document.querySelector('.parent')
console.log(parent);
parent.remove();
})
parent 요소의 내용을 메모리에 저장하는 코드를 이벤트가 발생한 후에 실행하도록 코드의 순서를 바꿔준다.
그러면 해당 이벤트가 종료된 후에 저장된 내용이 더 이상 사용되지 않는다고 판단되어 가비지 컬렉션이 알아서 메모리 해제할 것임
let a = 0
setInterval(() => {
a += 1
}, 100)
setTimeout(() => {
console.log(a)
}, 1000)
setInterval()
은 계속해서 반복되고 있는 중 ➡️ a는 계속해서 1씩 증가하고 있음
지금은 눈에 보이지 않지만 실제로 메모리는 계속 사용하고 있는 중이다.
clearInterval()
을 사용해서 타이머를 해제한다.
let a = 0
const interval = setInterval(() => {
a += 1
}, 100)
setTimeout(() => {
console.log(a)
clearInterval(interval)
}, 1000)
원하는대로 a를 출력한 후에 인터벌을 clear 하면 더 이상 메모리를 차지하지 않는다.
const getFn = () => {
let a = 0
return name => {
a += 1
console.log(a)
return `Hello ${name}~`
}
}
const fn = getFn()
console.log(fn('Happy'))
console.log(fn('Yellow'))
출력 결과
1
Hello Happy~
2
Hello Yellow~
fn 함수의 문제점은 꼭 사용하지 않아도 되는 a라는 변수를 참조한다는 것.
단순히 콘솔에 출력하기 위해 사용하는 거라면 굳이 클로저의 개념을 사용하지 않아도 됨.
a값은 계속해서 증가하고 메모리를 차지하기 때문에 잘못된 클로저 사용은 지양하는 것이 좋다.
const getFn = () => {
let a = 0
return name => {
return `Hello ${name}~`
}
}
const fn = getFn()
console.log(fn('Happy'))
console.log(fn('Yellow'))