클로저는 외부함수의 실행 컨텍스트가 제거되어도 내부함수가 외부함수의 변수를 기억하고 있는데 이는 추후에 메모리 누수가 발생할 수 있다.
예를 들어 리액트에서 useEffect 함수를 사용하여 렌더링 이후에 이벤트를 등록하였을 때, 이를 다시 렌더링이 되었을 때, 기존 이벤트를 클린업 해주지 않는 다면 같은 역할을 하는 이벤트가 중복등록이 되고 이는 성능상 문제를 일으킬 수 있으므로 이러한 점을 주의해야한다.
📌 정리
클로저는 보다 안전하게 객체를 다루기 위해 사용한다.
하지만 ES6에서 클래스가 도입되어 다른 객체지향 프로그래밍 언어처럼 private 접근 제한자가 생겨나 객체를 안전하게 관리할 수 있게 되었다.
예전에 페어프로그래밍을 하면서 DOM 요소를 참조하고 변경하는 클로저함수만 외부로 빼내어 해당 함수로만 DOM 요소를 조작할 수 있도록 코드를 구현해본 경험이 있습니다.
// getName 메서드를 호출한 객체는 anotherPerson이다. console.log(anotherPerson.getName()); // Kim
위와 같이 getName 메서드를 anotherPerson 객체의 메서드로 할당한 경우, getName 메서드 내부의 this는 자신을 호출한 객체에 바인딩 되기 때문에 anotherPerson.name을 참조하게 된다.
4. apply,call,bind 함수에 의한 간접 호출
이 경우 함수 내부의 this는 인수로 전달된 객체에 바인딩된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
functiongetThisBinding() { returnthis; }
// this로 사용할 객체 const thisArg = { a: 1 };
console.log(getThisBinding()); // window
// getThisBinding 함수를 호출하면서 인수로 전달한 객체를 getThisBinding 함수의 this에 바인딩한다. console.log(getThisBinding.apply(thisArg)); // {a: 1} console.log(getThisBinding.call(thisArg)); // {a: 1}
// bind 메서드는 첫 번째 인수로 전달한 thisArg로 this 바인딩이 교체된 // getThisBinding 함수를 새롭게 생성해 반환한다. console.log(getThisBinding.bind(thisArg)); // getThisBinding // bind 메서드는 함수를 호출하지는 않으므로 명시적으로 호출해야 한다. console.log(getThisBinding.bind(thisArg)()); // {a: 1}
call, apply의 반환값은 호출한 함수의 반환값이다.
bind는 함수를 호출하지 않고 인수로 전달받은 객체로 this 바인딩이 교체된 함수를 새롭게 생성하여 반환한다.