5. 클로저
정의
- 컨텍스트 A에서 선언한 변수 a를 참조하는 내부함수 B를 A의 외부로 전달할 경우, A가 종료된 이후에도 a가 사라지지 않는 현상.
var outer = function() { var a = 1; var inner = function() { return ++a; }; return inner; } var outer2 = outer(); console.log(outer2()); console.log(outer2());
- outer 함수의 실행이 종료돼도 inner 함수가 a를 참조하므로 변수 a는 사라지지 않는다.
클로저의 장점
: 함수 종료 후에도 사라지지 않는 지역변수를 만들 수 있다.
초기화 세팅할 때 편리!
초기화 세팅 용도로 클로저를 하나 만들고 계속 들고 있어야 할 값들을 리턴시키면 초기화 함수 종료되는 순간에 나머지는 모두 사라지고 필요한 값만 남아있다.
클로저 활용 사례
콜백 함수 내부에서 외부 데이터를 사용하고자 할 때
콜백 함수를 내부함수로 선언해서 외부변수를 직접 참조 (클로저)
var fruits = ['apple', 'banana', 'peach']; var $ul = document.createElement('ul'); fruits.forEach(function (fruit) { //(A) var $li = document.createElement('li); $li.innerText = fruit; $li.addEventListener('click', function() { //(B) alert('your choice is '+fruit); }); $ul.appendchild($li); }); docunent.body.appendChild($ul);
- addEventListener의 콜백 함수(B)에는
fruit
라는 외부 변수를 참조하고 있으므로 클로저가 있다.
bind 메소드로 값을 직접 넘겨주기 (클로저 X)
var fruits = ['apple', 'banana', 'peach']; var $ul = document.createElement('ul'); var alertFruit = function(fruit) { alert('your choice is '+ fruit); } fruits.forEach(function (fruit) { var $li = document.createElement('li); $li.innerText = fruit; $li.addEventListener('click', alertFruit.bind(null, fruit)); $ul.appendchild($li); }); docunent.body.appendChild($ul);
- (B)를 외부로 분리.
- addEventListnenr가 콜백함수(
alertFruit
)의 제어권을 가지게 되고, 첫 번째 인자에 이벤트 객체를 주입하기 때문에 bind 없이는[object MouseEvent]
가 출력된다. => bind 메소드로 this(null
)와 인자(fruit
)를 지정해 줌.
고차함수 활용 (클로저)
- 고차 함수 : 함수를 인자로 받거나 함수를 반환(return)함으로써 작동하는 함수.
var fruits = ['apple', 'banana', 'peach']; var $ul = document.createElement('ul'); var alertFruitBuilder = function(fruit) { return function () { alert('your choice is '+ fruit); } }; fruits.forEach(function (fruit) { var $li = document.createElement('li); $li.innerText = fruit; $li.addEventListener('click', alertFruitBuilder(fruit)); $ul.appendchild($li); }); docunent.body.appendChild($ul);
addEventListener
의 콜백함수는alertFruitBuilder
에fruit
를 인자로 주고 실행시킨 값(=익명함수. 기존의alertFruit
함수)
접근 권한 제어(정보 은닉)
- 정보 은닉 : 어떤 모듈의 내부 로직에 대해 외부로의 노출을 최소화해서 모듈간의 결합도를 낮추고 유연성을 높이고자 하는 개념.
- 접근 권한 : public(외부에서 접근 가능), private(내부에서만 사용. 외부에 노출X), protected 세 종류.
클로저(return) 활용한 접근 권한 제어
- return한 변수들은 공개 멤버, 그렇지 않는 변수들은 비공개 멤버.
(return 값이 외부에 정보를 제공하는 유일한 수단.)
getter, setter 메소드
- return 값을 getter, setter 메소드로 설정해 접근 권한 제어.
( 어떤 변수에 getter만을 부여하면 읽기 전용 속성. setter까지 있어야 변수 변경 가능.)
Object.freeze() 메소드
- 객체를 동결. 더 이상 변경될 수 없음.
부분 적용 함수
-
고차함수를 한 번 호출하면 (계속 사용할 수 있는) 새로운 함수가 반환된다는 장점. (재활용 측면)
-
부분 적용 함수(partially applied function) : n개의 인자를 받는 함수에 미리 m개의 인자만 넘겨 기억시켰다가, 나중에 (n-m)개의 인자를 넘기면 비로소 원래 함수의 실행 결과를 얻을 수 있게끔 하는 함수.
ex) 디바운스 Debounce
: 짧은 시간 동안 동일한 이벤트가 많이 발생할 경우 이를 전부 처리하지 않고 처음 또는 마지막에 발생한 이벤트에 대해 한 번만 처리하는 것. 프런트엔드 성능 최적화에 큰 도움을 주는 기능 중 하나.
var debounce = (eventName, func, wait) => { var timeoutId = null; return function(event) { var self = this; console.log(eventName, 'event 발생'); clearTimeout(timeoutId); timeoutId = setTimeout(func.bind(self, event), wait); }; }; var moveHandler = (e) => { console.log('move event 처리'); }; var wheelHandler = (e) => { console.log('wheel evnet 처리'); } document.body.addEventListener('mousemove',debounce('move', moveHandler, 500)); document.body.addEventListener('mousewheel',debounce('wheel', moveHandler, 700));
- 클로저로 처리된 것 : 변수 eventName, func, wait, timeoutId
커링 함수
- 커링 함수(currying fucntion): 여러 개의 인자를 받는 함수를 하나의 인자만 받는 함수로 나눠서 순차적으로 호출될 수 있게 체인 형태로 구성한 것.
var curry3 = function (func) { return function (a) { return function (b) { return func(a, b); }; }; }; var getMaxWith10 = curry3(Math.max)(10); console.log(getMaxWith10(8)); // 10 console.log(getMaxWith10(25)); // 25
필요한 인자의 개수만큼 함수를 만들어 계속 리턴해주다가 마지막에 조합해서 리턴. (인자가 많아질수록 가독성이 떨어진다는 단점)
화살표 함수를 써서 간단하게 표기할 수 있다(ES6)
var curry = func => a => b => c => d => e => func(a, b, c, d, e);
- 각 단계에서 받은 인자들을 모두 마지막 단계에서 참조할 것이므로 가비지 컬렉팅 되지 않고 메모리에 쌓였다가 마지막 호출로 실행 컨텍스트가 종료된 후에 한꺼번에 수거.
지연 실행, 함수의 매개변수가 일부만 바뀔 때 유용
- 커링 함수는 지연실행에 유용. (당장 필요한 정보만 받아서 전달하고, 또 필요한 정보가 들어오면 전달하는 식으로 결국 마지막 인자가 넘어갈 때까지 함수 실행을 미루는 것)
- 프로젝트 내에서 자주 쓰이는 함수의 매개변수가 항상 비슷하고 일부만 바뀌는 경우에도 커링 함수가 유용.
Author And Source
이 문제에 관하여(5. 클로저), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@pika/클로저-d9wf0zr0저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)