Closure
- 외부 함수 안에 있는 내부 함수.
- 내부 함수가 외부 함수에 접근할 수 있는 것을 클로저라 한다.
- 클로저 함수 안에서는 지역변수(innerVar) 외부 함수의 변수(outerVar) 전역변수(glovalVar)의 접근이 전부 가능하다.
- 함수가 본인이 생성된 주변 환경을 지속적으로 기억하는것을 의미한다.
- 함수가 실행되는 위치가 어디인지 관계가 없다.
ex1)
1
2
3
4
5
6
7
8
9
10
11
12
13
| function add () {
var str1 = 'hello';
var str2 = 'world';
function strAdd () {
console.log(str1 + ' ' +str2);
}
return strAdd;
}
var a = add();
a(); // "hello world"
|
함수가 생성된 주변 환경을 지속적으로 기억하기 때문에 str1
과 str2
변수에 접근할수 있게 되면서 콘솔에 ‘hello world’를 찍게 된다.
ex4) ( 커링 )
1
2
3
4
5
6
7
8
9
10
11
| function makeAdder (x) {
return function add (y) {
return x + y;
}
}
var addFive = makeAdder(5);
var addTen = makeAdder(10);
addTen(2); // 7
addFive(1); // 11
|
풀이
var addFive
에 makeAdder(5);
을 할당한것은 function add (y) { return 5 + y; }
이 되고 var addTen
에 makeAdder(10);
을 할당한것은 function add (y) { return 5 + y; }
된다.
addTen(2);
을 실행하면 새로운 makeAdder
Scope가 생기고 콘솔에 7
이 찍히고 addFive(1);
을 실행하면 또 새로운 makeAdder
Scope가 생기고 콘솔에 11
이 찍히게 된다.
클로저 모듈 패턴
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
| function makeCounter() {
let privateCounter = 0;
return {
increment: function() {
privateCounter++;
},
decrement: function() {
privateCounter--;
},
getValue: function() {
return privateCounter;
}
}
}
// let obj = {} return obj와 같다.
let counter1 = makeCounter();
counter1.increment();
counter1.increment();
counter1.getValue(); // 2
let counter2 = makeCounter();
counter2.increment();
counter2.decrement();
counter2.increment();
counter2.getValue(); //1
|
- 객체의 key의 값이 함수일 때 메소드이다.
- 변수를 스코프 안쪽에 가두어 함수 밖으로 노출시키지 않는 방법.
- counter1, counter2 두 카운터에 각기 다른 privateCounter를 다루면서 PrivateCounter를 밖으로 노출시키지 않는다.
이를 통해서 객체의 내부에서만 사용해야 하는 값이 노출됨으로서 생길 수 있는 오류를 줄일 수 있다.
for loop closure
closure example
1
2
3
4
5
| for (var i = 1; i < 6; i++) {
setTimeout(function () {
console.log(i);
}, i * 1000);
}
|
1
2
3
4
5
6
| 시간 로그
1초 1
2초 2
3초 3
4초 4
5초 5
|
클로저
1
2
3
4
5
6
7
8
9
10
11
| function test () {
for (var i = 1; i < 6; i++) {
(function(ct) {
setTimeout(function () {
console.log(ct);
}, ct * 1000);
})(i);
}
}
test();
|
블록 스코프 let 사용
1
2
3
4
5
| for (let i = 1; i < 6; i++) {
setTimeout(function () {
console.log(i);
}, i * 1000);
}
|