Closure
· 외부함수의 변수에 접근할 수 있는 내부 함수
· scope chain으로 표현되기도 한다
· 보통 함수를 return 하여 사용!
· return하는 내부 함수를 closure 함수라고 지칭
Question
각각의 함수 호출은 어떠한 결과를 콘솔에 출력할까요?
1 2 3 4 5 6 7 8 9 10 11 12 | function outer() { console.log('outer fn invoked'); function inner() { console.log('inner fn invoked'); } return inner; } outer(); // ? outer()(); // ? var innerFn = outer(); // ? innerFn(); // ? | cs |
outer(); // 'outer fn invoked' , 함수(inner)가 리턴됨
outer()(); // 'outer fn invoked' 'inner fn invoked' 바깥 함수가 실행되고 안의 함수도 실행됨
var innerFn = outer(); // 'outer fn invoked'
innerFn(); // outer()();와 같음
Closure
1 2 3 4 5 6 7 8 | function outer() { var outerVar = 'outer fn variable '; function inner() { var innerVar = 'inner fn variable '; console.log(outerVar + innerVar); // 외부 함수의 변수(outerVar)를 내부 함수, 즉 closure가 사용할 수 있음 } } | cs |
Closure가 가지는 세가지 scope chain
1. closure 자신에 대한 접근(closure function 내에 정의된 변수)
2. 외부 함수의 변수에 대한 접근
3. 전역 변수에 대한 접근
1 2 3 4 5 6 7 8 9 10 11 12 13 | var greeting = 'Hello'; // 전역 변수에 대한 접근 가능 function showName(firstName, lastName) { var nameIntro = 'My name is '; function makeFullName() { // 이 내부 함수(makeFullName)는 외부 함수(showName)의 변수뿐만 아니라 // 파라미터 까지 사용할 수 있다. return greeting + ', ' + nameIntro + firstName + ' ' + lastName; } return makeFullName(); } showName('Michael', 'Jackson'); // Hello, My name is Michael Jackson | cs |
유용한 Closure 예제
currying (Functional Programming)
함수 하나가 n개의 인자를 받는 대신, n개의 함수를 만들어 각각 인자를 받게 하는 방법
· without currying
1 2 3 4 | function add(x, y) { return x + y; } add(2, 3); // 5 | cs |
· with currying
1 2 3 4 5 6 | function adder(x) { return function(y) { return x + y; } } adder(2)(3); // 5 | cs |
무엇이 좋은가?
· closure가 저장된 parameter를 사용하므로, template 함수를 만들고자 할 때 유용
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function elementMaker(tagName) { var startTag = '<' + tagName + '>'; var endTag = '</' + tagName + '>'; return function(content) { // closer 함수 return startTag + content + endTag; } } elementMaker('div')('hello world'); // <div>hello world</div> var divMaker = elementMaker('div'); divMaker('code states'); // <div>code states</div> divMaker('great'); // <div>great</div> var h1Maker = elementMaker('h1'); h1Maker('Headline'); // <h1>Headline</h1> | cs |
Closure Module Pattern
Simple counter 예제
· 변수를 scope 안쪽에 감추어 함수 밖에서 노출시키지 않을 수 있음
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | function makeCounter() { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function() { changeBy(1); }, decrement: function() { changeBy(-1); }, getValue: function() { return privateCounter; } } } var counter1 = makeCounter(); // { increment : f, decrement : f, getValue: f } counter1.increment(); // 내부적으로 privateCounter +1 counter1.increment(); // 내부적으로 privateCounter +1 counter1.getValue(); // 2 var counter2 = makeCounter(); counter2.increment(); // privateCounter +1 counter2.decrement(); // privateCounter +1 counter2.increment(); // 2 (독립적으로 값이 나온다) | cs |
'Programing > JavaScript' 카테고리의 다른 글
[JavaScript] Function Methods, Prototype (0) | 2019.02.14 |
---|---|
[JavaScript] this / call, apply 호출 (0) | 2019.02.14 |
[JavaScript] Scope (0) | 2019.02.13 |
[JavaScript] for문, forEach(), for in, for of 차이 (0) | 2019.02.12 |
[JavaScript] Window.prompt() (0) | 2019.02.12 |