[JS] ๐ ํด๋ก์ (Closure) ๊ฐ๋ ์๋ฒฝ ์ ๋ฆฌ
ํด๋ก์ (closure) ๋?
ํด๋ก์ ๋ ๋ฐํ๋ ๋ด๋ถํจ์๊ฐ ์์ ์ด ์ ์ธ๋์ ๋์ ํ๊ฒฝ(Lexical environment)์ธ ์ค์ฝํ๋ฅผ ๊ธฐ์ตํ์ฌ, ๋ง์ผ ์์ ์ด ์ ์ธ๋์ ๋์ ํ๊ฒฝ(์ค์ฝํ) ๋ฐ์์ ํธ์ถ๋์ด๋ ์ค์ฝํ์ ์ ๊ทผํ ์ ์๋ ํจ์๋ฅผ ๋งํ๋ค.
function outerFunc() {
var x = 10;
var innerFunc = function () { console.log(x); };
innerFunc();
}
outerFunc(); // 10
- โํจ์ outerFunc ๋ด์์ ๋ด๋ถํจ์ innerFunc๊ฐ ์ ์ธ๋๊ณ ํธ์ถ๋์๋ค.
- ์ด๋ ๋ด๋ถํจ์ innerFunc๋ ์์ ์ ํฌํจํ๊ณ ์๋ ์ธ๋ถํจ์ outerFunc์ ๋ณ์ x์ ์ ๊ทผํ ์ ์๋ค.
- ์ด๋ ํจ์ innerFunc๊ฐ ํจ์ outerFunc์ ๋ด๋ถ์ ์ ์ธ๋์๊ธฐ ๋๋ฌธ์ด๋ค.
โ์ค์ฝํ๋ ํจ์๋ฅผ ํธ์ถํ ๋๊ฐ ์๋๋ผ ํจ์๋ฅผ ์ด๋์ ์ ์ธํ์๋์ง์ ๋ฐ๋ผ ๊ฒฐ์ ๋๋ค.
์ด๋ฅผ ๋ ์์ปฌ ์ค์ฝํ(Lexical scoping)๋ผ ํ๋ค.
โ
์ ์์ ์ ํจ์ innerFunc๋ ํจ์ outerFunc์ ๋ด๋ถ์์ ์ ์ธ๋์๊ธฐ ๋๋ฌธ์ ํจ์ innerFunc์ ์์ ์ค์ฝํ๋ ํจ์ outerFunc์ด๋ค.
๋ฐ๋ผ์ ํจ์ innerFunc๊ฐ ํจ์ outerFunc์ ๋ด๋ถ์ ์ ์ธ๋ ๋ด๋ถํจ์์ด๋ฏ๋ก ํจ์ innerFunc๋ ์์ ์ด ์ํ ๋ ์์ปฌ ์ค์ฝํ(์ ์ญ, ํจ์ outerFunc, ์์ ์ ์ค์ฝํ)๋ฅผ ์ฐธ์กฐํ ์ ์๋ค.
๋ง์ผ ํจ์ innerFunc๊ฐ ์ ์ญ์ ์ ์ธ๋์๋ค๋ฉด ํจ์ innerFunc์ ์์ ์ค์ฝํ๋ ์ ์ญ ์ค์ฝํ๊ฐ ๋๋ค.
โ์ด๊ฒ์ ์คํ ์ปจํ ์คํธ ์ ๊ด์ ์์ ์ค๋ช ํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
1) innerFunc ํจ์ ์ค์ฝํ(ํจ์ ์์ ์ ์ค์ฝํ๋ฅผ ๊ฐ๋ฆฌํค๋ ํ์ฑ ๊ฐ์ฒด) ๋ด์์ ๋ณ์ x๋ฅผ ๊ฒ์ํ๋ค. ๊ฒ์์ด ์คํจํ์๋ค.
2) innerFunc ํจ์๋ฅผ ํฌํจํ๋ ์ธ๋ถ ํจ์ outerFunc์ ์ค์ฝํ(ํจ์ outerFunc์ ์ค์ฝํ๋ฅผ ๊ฐ๋ฆฌํค๋ ํจ์ outerFunc์ ํ์ฑ ๊ฐ์ฒด)์์ ๋ณ์ x๋ฅผ ๊ฒ์ํ๋ค. ๊ฒ์์ด ์ฑ๊ณตํ์๋ค.
โ
์ด๋ฒ์๋ ๋ด๋ถํจ์ innerFunc๋ฅผ ํจ์ outerFunc ๋ด์์ ํธ์ถํ๋ ๊ฒ์ด ์๋๋ผ ๋ฐํํ๋๋ก ๋ณ๊ฒฝํด ๋ณด์.
function outerFunc() {
var x = 10;
var innerFunc = function () { console.log(x); };
return innerFunc;
}
/**
* ํจ์ outerFunc๋ฅผ ํธ์ถํ๋ฉด ๋ด๋ถ ํจ์ innerFunc๊ฐ ๋ฐํ๋๋ค.
* ๊ทธ๋ฆฌ๊ณ ํจ์ outerFunc์ ์คํ ์ปจํ
์คํธ๋ ์๋ฉธํ๋ค.
*/
var inner = outerFunc();
inner(); // 10
ํจ์ outerFunc๋ ๋ด๋ถํจ์ innerFunc๋ฅผ ๋ฐํํ๊ณ ์์ ๋ง๊ฐํ๋ค.
์ฆ, ํจ์ outerFunc๋ ์คํ๋ ์ดํ ์ฝ์คํ(์คํ ์ปจํ ์คํธ ์คํ)์์ ์ ๊ฑฐ๋์์ผ๋ฏ๋ก ํจ์ outerFunc์ ๋ณ์ x ๋ํ ๋์ด์ ์ ํจํ์ง ์๊ฒ ๋์ด ๋ณ์ x์ ์ ๊ทผํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ฌ๋ฆฌ ์์ด ๋ณด์ธ๋ค.
๊ทธ๋ฌ๋ ์ ์ฝ๋์ ์คํ ๊ฒฐ๊ณผ๋ ๋ณ์ x์ ๊ฐ์ธ 10์ด๋ค.
์ด๋ฏธ life-cycle์ด ์ข ๋ฃ๋์ด ์คํ ์ปจํ ์คํธ ์คํ์์ ์ ๊ฑฐ๋ ํจ์ outerFunc์ ์ง์ญ๋ณ์ x๊ฐ ๋ค์ ๋ถํ์ด๋ผ๋ ํ ๋ฏ์ด ๋์ํ๊ณ ์๋ค.
๋์๋ ๋ณด์ด์ง ์์ง๋ง ๋ญ๊ฐ ํน๋ณํ ์ผ์ด ์ผ์ด๋๊ณ ์๋ ๊ฒ์ด๋ค.
โ
์ด์ฒ๋ผ ์์ ์ ํฌํจํ๊ณ ์๋ ์ธ๋ถํจ์๋ณด๋ค ๋ด๋ถํจ์๊ฐ ๋ ์ค๋ ์ ์ง๋๋ ๊ฒฝ์ฐ, ์ธ๋ถ ํจ์ ๋ฐ์์ ๋ด๋ถํจ์๊ฐ ํธ์ถ๋๋๋ผ๋ ์ธ๋ถํจ์์ ์ง์ญ ๋ณ์์ ์ ๊ทผํ ์ ์๋๋ฐ ์ด๋ฌํ ํจ์๋ฅผ ํด๋ก์ (Closure)๋ผ๊ณ ๋ถ๋ฅด๋ ๊ฒ์ด๋ค.
ํด๋ก์ ธ์ ํ์ฉ
โ
์ํ ์ ์ง
ํด๋ก์ ธ๊ฐ ๊ฐ์ฅ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋๋ ์ํฉ์ ํ์ฌ ์ํ๋ฅผ ๊ธฐ์ตํ๊ณ ๋ณ๊ฒฝ๋ ์ต์ ์ํ๋ฅผ ์ ์งํ๋ ๊ฒ์ด๋ค.
- closure ๋ผ๋ ์ด๋ฆ์ ํจ์๋ฅผ ๋ง๋ค๊ณ toggle ๋ณ์์ ํจ์๋ฅผ ์คํํ ๋ฆฌํด๊ฐ์ธ ๋ด๋ถ ํจ์๋ฅผ ๋ฐํํ๋ค.
๋ฐํํ ํจ์๋ ์์ ์ด ์์ฑ๋์ ๋์ ๋ ์์ปฌ ํ๊ฒฝ(Lexical environment)์ ์ํ ๋ณ์ isShow๋ฅผ ๊ธฐ์ตํ๋ ํด๋ก์ ๋ค. ํด๋ก์ ๊ฐ ๊ธฐ์ตํ๋ ๋ณ์ isShow๋ box ์์์ ํ์ ์ํ๋ฅผ ๋ํ๋ธ๋ค. - ํด๋ก์ ๋ฅผ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ก์ ์ด๋ฒคํธ ํ๋กํผํฐ์ ํ ๋นํ๋ค.
์ด๋ฒคํธ ํ๋กํผํฐ์์ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ธ ํด๋ก์ ๋ฅผ ์ ๊ฑฐํ์ง ์๋ ํ ํด๋ก์ ๊ฐ ๊ธฐ์ตํ๋ ๋ ์์ปฌ ํ๊ฒฝ์ ๋ณ์ isShow๋ ์๋ฉธํ์ง ์๋๋ค.
๋ค์ ๋งํด ํ์ฌ ์ํ๋ฅผ ๊ธฐ์ตํ๋ค. - ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ด๋ฒคํธ ํ๋กํผํฐ์ ํ ๋นํ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ธ ํด๋ก์ ๊ฐ ํธ์ถ๋๋ค.
์ด๋ .box ์์์ ํ์ ์ํ๋ฅผ ๋ํ๋ด๋ ๋ณ์ isShow์ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ค.
๋ณ์ isShow๋ ํด๋ก์ ์ ์ํด ์ฐธ์กฐ๋๊ณ ์๊ธฐ ๋๋ฌธ์ ์ ํจํ๋ฉฐ ์์ ์ ๋ณ๊ฒฝ๋ ์ต์ ์ํ๋ฅผ ๊ฒ์ํด์ ์ ์งํ๋ค.
<!DOCTYPE html>
<html>
<body>
<button class="toggle">toggle</button>
<div class="box" style="width: 100px; height: 100px; background: red;"></div>
<script>
var box = document.querySelector('.box');
var toggleBtn = document.querySelector('.toggle');
function closure() {
var isShow = false;
// โ ํด๋ก์ ๋ฅผ ๋ฐํ
return function () {
box.style.display = isShow ? 'block' : 'none';
// โข ์ํ ๋ณ๊ฒฝ
isShow = !isShow;
};
}
var toggle = closure(); // ํด๋ก์ ๋ฐํ
// โก ์ด๋ฒคํธ ํ๋กํผํฐ์ ํด๋ก์ ๋ฅผ ํ ๋น
toggleBtn.onclick = toggle;
</script>
</body>
</html>
์ด์ฒ๋ผ ํด๋ก์ ๋ ํ์ฌ ์ํ(์ ์์ ์ ๊ฒฝ์ฐ .box ์์์ ํ์ ์ํ๋ฅผ ๋ํ๋ด๋ isShow ๋ณ์)๋ฅผ ๊ธฐ์ตํ๊ณ ์ด ์ํ๊ฐ ๋ณ๊ฒฝ๋์ด๋ ์ต์ ์ํ๋ฅผ ์ ์งํด์ผ ํ๋ ์ํฉ์ ๋งค์ฐ ์ ์ฉํ๋ค.
๋ง์ฝ ์๋ฐ์คํฌ๋ฆฝํธ์ ํด๋ก์ ๋ผ๋ ๊ธฐ๋ฅ์ด ์๋ค๋ฉด ์ํ๋ฅผ ์ ์งํ๊ธฐ ์ํด ์ ์ญ ๋ณ์๋ฅผ ์ฌ์ฉํ ์ ๋ฐ์ ์๋ค.
๊ทธ๋ฌ๋ ์ ์ญ ๋ณ์๋ ์ธ์ ๋ ์ง ๋๊ตฌ๋ ์ ๊ทผํ ์ ์๊ณ ๋ณ๊ฒฝํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ง์ ๋ถ์์ฉ์ ์ ๋ฐํด ์ค๋ฅ์ ์์ธ์ด ๋๋ฏ๋ก ์ฌ์ฉ์ ์ต์ ํด์ผ ํ๋ค.
โ
โ
์ ์ญ ๋ณ์์ ์ฌ์ฉ ์ต์
๋ฒํผ์ด ํด๋ฆญ๋ ๋๋ง๋ค ํด๋ฆญํ ํ์๊ฐ ๋์ ๋์ด ํ๋ฉด์ ํ์๋๋ ์นด์ดํฐ๋ฅผ ๋ง๋ค์ด๋ณด์.
์ด ์์ ์ ํด๋ฆญ๋ ํ์๊ฐ ๋ฐ๋ก ์ ์งํด์ผํ ์ํ์ด๋ค.
// ์นด์ดํธ ์ํ๋ฅผ ์ ์งํ๊ธฐ ์ํ ์ ์ญ ๋ณ์
var counter = 0;
function increase() {
return ++counter;
}
Button.onclick = function () {
count.innerHTML = increase();
};
์ ์ฝ๋๋ ์ ๋์ํ์ง๋ง ์ค๋ฅ๋ฅผ ๋ฐ์์ํฌ ๊ฐ๋ฅ์ฑ์ ๋ดํฌํ๊ณ ์๋ ์ข์ง ์์ ์ฝ๋๋ค.
๋ณ์ counter๋ ์ ์ญ ๋ณ์์ด๊ธฐ ๋๋ฌธ์ ์ธ์ ๋ ์ง ๋๊ตฌ๋ ์ ๊ทผํ ์ ์๊ณ ๋ณ๊ฒฝํ ์ ์๋ค. ์ด๋ ์๋์น ์๊ฒ ๊ฐ์ด ๋ณ๊ฒฝ๋ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
๋ง์ฝ ๋๊ตฐ๊ฐ์ ์ํด ์๋์น ์๊ฒ ์ ์ญ ๋ณ์ counter์ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ค๋ฉด ์ด๋ ์ค๋ฅ๋ก ์ด์ด์ง๋ค.
๋ฐ๋ผ์ ๋ณ์ counter๋ ์นด์ดํฐ๋ฅผ ๊ด๋ฆฌํ๋ increase ํจ์๊ฐ ๊ด๋ฆฌํ๋ ๊ฒ์ด ๋ฐ๋์งํ๋ค.
์ ์ญ ๋ณ์ counter๋ฅผ increase ํจ์์ ์ง์ญ ๋ณ์๋ก ๋ฐ๊พธ์ด ์๋์น ์์ ์ํ ๋ณ๊ฒฝ์ ๋ฐฉ์งํด๋ณด์.
function increase() {
// ์นด์ดํธ ์ํ๋ฅผ ์ ์งํ๊ธฐ ์ํ ์ง์ญ ๋ณ์
var counter = 0;
return ++counter;
}
Button.onclick = function () {
count.innerHTML = increase(); // ๋ฌด์กฐ๊ฑด 1์ด ๋ฐํ ๋๋ค
};
์ ์ญ๋ณ์๋ฅผ ์ง์ญ๋ณ์๋ก ๋ณ๊ฒฝํ์ฌ ์๋์น ์์ ์ํ ๋ณ๊ฒฝ์ ๋ฐฉ์งํ๋ค.
ํ์ง๋ง increase ํจ์๊ฐ ํธ์ถ๋ ๋๋ง๋ค ์ง์ญ๋ณ์ counter๋ฅผ 0์ผ๋ก ์ด๊ธฐํํ๊ธฐ ๋๋ฌธ์ ์ธ์ ๋ 1์ด ํ์๋๋ค.
๋ค์ ๋งํด ๋ณ๊ฒฝ๋ ์ด์ ์ํ๋ฅผ ๊ธฐ์ตํ์ง ๋ชปํ๋ค.
์ด์ ์ํ๋ฅผ ๊ธฐ์ตํ๋๋ก ํด๋ก์ ๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด๋ณด์.
var increase = (function() { // (function() { ... })(); ์ฆ์์คํํจ์
var counter = 0;
return function(){ // ํด๋ก์
return ++counter;
}
})();
Button.onclick = function () {
count.innerHTML = increase(); // 1 .. 2 .. 3
};
์คํฌ๋ฆฝํธ๊ฐ ์คํ๋๋ฉด ์ฆ์์คํํจ์(immediately-invoked function expression)๊ฐ ํธ์ถ๋๊ณ ,
๋ณ์ increase์๋ ํจ์ function () { return ++counter; }๊ฐ ํ ๋น๋๋ค.
โ์ด ํจ์๋ ์์ ์ด ์์ฑ๋์ ๋์ ๋ ์์ปฌ ํ๊ฒฝ(Lexical environment)์ ๊ธฐ์ตํ๋ ํด๋ก์ ๋ค.
์ฆ์์คํํจ์๋ ํธ์ถ๋ ์ดํ ์๋ฉธ๋์ง๋ง ์ฆ์์คํํจ์๊ฐ ๋ฐํํ ํจ์๋ ๋ณ์ increase์ ํ ๋น๋์ด inclease ๋ฒํผ์ ํด๋ฆญํ๋ฉด ํด๋ฆญ ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ด๋ถ์์ ํธ์ถ๋๋ค.
โ
์ด๋ ํด๋ก์ ์ธ ์ด ํจ์๋ ์์ ์ด ์ ์ธ๋์ ๋์ ๋ ์์ปฌ ํ๊ฒฝ์ธ ์ฆ์์คํํจ์์ ์ค์ฝํ์ ์ํ ์ง์ญ๋ณ์ counter๋ฅผ ๊ธฐ์ตํ๋ค.
๋ฐ๋ผ์ ์ฆ์์คํํจ์์ ๋ณ์ counter์ ์ ๊ทผํ ์ ์๊ณ ๋ณ์ counter๋ ์์ ์ ์ฐธ์กฐํ๋ ํจ์๊ฐ ์๋ฉธ๋ ๋๊ฐ์ง ์ ์ง๋๋ค.
๋ณ์ counter๋ ์ธ๋ถ์์ ์ง์ ์ ๊ทผํ ์ ์๋ ์๋ฐ์ private ๋ณ์์ ๋น์ทํ๋ฏ๋ก ์ ์ญ ๋ณ์๋ฅผ ์ฌ์ฉํ์ ๋์ ๊ฐ์ด ์๋๋์ง ์์ ๋ณ๊ฒฝ์ ๊ฑฑ์ ํ ํ์๋ ์๊ธฐ ๋๋ฌธ์ด ๋ณด๋ค ์์ ์ ์ธ ํ๋ก๊ทธ๋๋ฐ์ด ๊ฐ๋ฅํ๋ค.
๋ณ์์ ๊ฐ์ ๋๊ตฐ๊ฐ์ ์ํด ์ธ์ ๋ ์ง ๋ณ๊ฒฝ๋ ์ ์์ด ์ค๋ฅ ๋ฐ์์ ๊ทผ๋ณธ์ ์์ธ์ด ๋ ์ ์๋ค.
์ํ ๋ณ๊ฒฝ์ด๋ ๊ฐ๋ณ(mutable) ๋ฐ์ดํฐ๋ฅผ ํผํ๊ณ ๋ถ๋ณ์ฑ(Immutability)์ ์งํฅํ๋ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์์ ๋ถ์ ํจ๊ณผ(Side effect)๋ฅผ ์ต๋ํ ์ต์ ํ์ฌ ์ค๋ฅ๋ฅผ ํผํ๊ณ ํ๋ก๊ทธ๋จ์ ์์ ์ฑ์ ๋์ด๊ธฐ ์ํด ํด๋ก์ ๋ ์ ๊ทน์ ์ผ๋ก ์ฌ์ฉ๋๋ค.
ํด๋ก์ ธ ์ค์ ์์ )
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์์ ํด๋ก์ ๋ฅผ ํ์ฉ
function makeCounter(predicate) {
var counter = 0; // ์นด์ดํธ ์ํ๋ฅผ ์ ์งํ๊ธฐ ์ํ ์์ ๋ณ์
// ํด๋ก์ ๋ฅผ ๋ฐํ
return function () {
counter = predicate(counter);
return counter;
};
}
// ๋ณด์กฐ ํจ์
function increase(n) {
return ++n;
}
// ๋ณด์กฐ ํจ์
function decrease(n) {
return --n;
}
const increaser = makeCounter(increase);
/*
= function () {
counter = function increase(counter) {
return ++counter;
}
return counter;
};
*/
console.log(increaser()); // 1
console.log(increaser()); // 2
// increaser ํจ์์๋ ๋ณ๊ฐ์ ๋
๋ฆฝ๋ ๋ ์์ปฌ ํ๊ฒฝ์ ๊ฐ๊ธฐ ๋๋ฌธ์ ์นด์ดํฐ ์ํ๊ฐ ์ฐ๋ํ์ง ์๋๋ค.
const decreaser = makeCounter(decrease);
console.log(decreaser()); // -1
console.log(decreaser()); // -2
ํจ์ makeCounter๋ ๋ณด์กฐ ํจ์๋ฅผ ์ธ์๋ก ์ ๋ฌ๋ฐ๊ณ ํจ์๋ฅผ ๋ฐํํ๋ ๊ณ ์ฐจ ํจ์์ด๋ค.
ํจ์ makeCounter๊ฐ ๋ฐํํ๋ ํจ์๋ ์์ ์ด ์์ฑ๋์ ๋์ ๋ ์์ปฌ ํ๊ฒฝ์ธ ํจ์ makeCounter์ ์ค์ฝํ์ ์ํ ๋ณ์ counter์ ๊ธฐ์ตํ๋ ํด๋ก์ ๋ค.
โ
์ ์์ ์์ ๋ณ์ increaser์ ๋ณ์ decreaser์ ํ ๋น๋ ํจ์๋ ๊ฐ๊ฐ ์์ ๋ง์ ๋ ๋ฆฝ๋ ๋ ์์ปฌ ํ๊ฒฝ์ ๊ฐ๊ธฐ ๋๋ฌธ์ ์นด์ดํธ๋ฅผ ์ ์งํ๊ธฐ ์ํ ์์ ๋ณ์ counter๋ฅผ ๊ณต์ ํ์ง ์์ ์นด์ดํฐ์ ์ฆ๊ฐ์ด ์ฐ๋ํ์ง ์๋๋ค.
โ
๋ฐ๋ผ์ ๋ ๋ฆฝ๋ ์นด์ดํฐ๊ฐ ์๋๋ผ ์ฐ๋ํ์ฌ ์ฆ๊ฐ์ด ๊ฐ๋ฅํ ์นด์ดํฐ๋ฅผ ๋ง๋ค๋ ค๋ฉด ๋ ์์ปฌ ํ๊ฒฝ์ ๊ณต์ ํ๋ ํด๋ก์ ๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค.
์ ๋ณด์ ์๋
โ์์ฑ์ ํจ์ Counter๋ฅผ ์์ฑํ๊ณ ์ด๋ฅผ ํตํด counter ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด๋ณด์.
function Counter() {
// ์นด์ดํธ๋ฅผ ์ ์งํ๊ธฐ ์ํ ์์ ๋ณ์
var counter = 0; // this.counter๋ก ์ํ๊ธฐ ๋๋ฌธ์ new ์์ฑ์๋ก ์ด๊ธฐํํด๋ ์ด ๋ณ์๋ ๊ฐ์ฒด์ ๋ด๊ธฐ์ง ์๋๋ค.
// ํด๋ก์
this.increase = function () {
return ++counter;
};
// ํด๋ก์
this.decrease = function () {
return --counter;
};
}
const counter = new Counter(); // counter๊ฐ์ฒด๋ increase decreaseํจ์ ๋๊ฐ๋ง ๊ฐ๊ฒ ๋๋ค.
console.log(counter.increase()); // 1
console.log(counter.decrease()); // 0
์์ฑ์ ํจ์ Counter๋ increase, decrease ๋ฉ์๋๋ฅผ ๊ฐ๋ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ค.
์ด ๋ฉ์๋๋ค์ ๋ชจ๋ ์์ ์ด ์์ฑ๋์ ๋์ ๋ ์์ปฌ ํ๊ฒฝ์ธ ์์ฑ์ ํจ์ Counter์ ์ค์ฝํ์ ์ํ ๋ณ์ counter๋ฅผ ๊ธฐ์ตํ๋ ํด๋ก์ ์ด๋ฉฐ ๋ ์์ปฌ ํ๊ฒฝ์ ๊ณต์ ํ๋ค.
์์ฑ์ ํจ์๊ฐ ํจ์๊ฐ ์์ฑํ ๊ฐ์ฒด์ ๋ฉ์๋๋ ๊ฐ์ฒด์ ํ๋กํผํฐ์๋ง ์ ๊ทผํ ์ ์๋ ๊ฒ์ด ์๋๋ฉฐ ์์ ์ด ๊ธฐ์ตํ๋ ๋ ์์ปฌ ํ๊ฒฝ์ ๋ณ์์๋ ์ ๊ทผํ ์ ์๋ค.
โ
์ด๋ ์์ฑ์ ํจ์ Counter์ ๋ณ์ counter๋ this์ ๋ฐ์ธ๋ฉ๋ ํ๋กํผํฐ๊ฐ ์๋๋ผ ๊ทธ๋ฅ ๋ณ์๋ค.
counter๊ฐ this์ ๋ฐ์ธ๋ฉ๋ ํ๋กํผํฐ๋ผ๋ฉด ์์ฑ์ ํจ์ Counter๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ํตํด ์ธ๋ถ์์ ์ ๊ทผ์ด ๊ฐ๋ฅํ public ํ๋กํผํฐ๊ฐ ๋์ง๋ง
์์ฑ์ ํจ์ Counter ๋ด์์ ์ ์ธ๋ ๋ณ์ counter๋ ์์ฑ์ ํจ์ Counter ์ธ๋ถ์์ ์ ๊ทผํ ์ ์๋ค.
โ
์์ฑ์ ํจ์ Counter๊ฐ ์์ฑํ ์ธ์คํด์ค์ ๋ฉ์๋์ธ increase, decrease๋ ํด๋ก์ ์ด๊ธฐ ๋๋ฌธ์ ์์ ์ด ์์ฑ๋์ ๋์ ๋ ์์ปฌ ํ๊ฒฝ์ธ ์์ฑ์ ํจ์ Counter์ ๋ณ์ counter์ ์ ๊ทผํ ์ ์๋ค.
โ
์ด๋ฌํ ํด๋ก์ ์ ํน์ง์ ์ฌ์ฉํด ํด๋์ค ๊ธฐ๋ฐ ์ธ์ด์ private ํค์๋๋ฅผ ํ๋ด๋ผ ์ ์๋ค.
์์ฃผ ๋ฐ์ํ๋ ํด๋ก์ ์ค์
var arr = [];
for (var i = 0; i < 5; i++) {
arr[i] = function () { return i; };
}
for (var j = 0; j < arr.length; j++) {
console.log(arr[j]()); // 5 5 5 5 5
}
๋ฐฐ์ด arr์ 5๊ฐ์ ํจ์๊ฐ ํ ๋น๋๊ณ ๊ฐ๊ฐ์ ํจ์๋ ์์ฐจ์ ์ผ๋ก 0, 1, 2, 3, 4๋ฅผ ๋ฐํํ ๊ฒ์ผ๋ก ๊ธฐ๋ํ๊ฒ ์ง๋ง ๊ฒฐ๊ณผ๋ ๊ทธ๋ ์ง์๋ค.
for ๋ฌธ์์ ์ฌ์ฉํ ๋ณ์ i๋ ์ ์ญ ๋ณ์์ด๊ธฐ ๋๋ฌธ์ด๋ค.
var i= 110;
for (var i = 0; i < 5; i++) {
}
console.log(i) // 5
โ
์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๋ก์ ๋ฅผ ์ฌ์ฉํด ๋ฐ๋ฅด๊ฒ ๋์ํ๋ ์ฝ๋๋ก ๋ง๋ค์ด๋ณด์.
var arr = [];
for (var i = 0; i < 5; i++){
arr[i] = (function (id) { // โก
return function () {
return id; // โข
};
}(i)); // โ
}
for (var j = 0; j < arr.length; j++) {
console.log(arr[j]());
}
- ๋ฐฐ์ด arr์๋ ์ฆ์์คํํจ์์ ์ํด ํจ์๊ฐ ๋ฐํ๋๋ค.
- ์ด๋ ์ฆ์์คํํจ์๋ i๋ฅผ ์ธ์๋ก ์ ๋ฌ๋ฐ๊ณ ๋งค๊ฐ๋ณ์ id์ ํ ๋นํ ํ ๋ด๋ถ ํจ์๋ฅผ ๋ฐํํ๊ณ life-cycle์ด ์ข ๋ฃ๋๋ค. ๋งค๊ฐ๋ณ์ id๋ ์์ ๋ณ์๊ฐ ๋๋ค.
- ๋ฐฐ์ด arr์ ํ ๋น๋ ํจ์๋ id๋ฅผ ๋ฐํํ๋ค. ์ด๋ id๋ ์์ ์ค์ฝํ์ ์์ ๋ณ์์ด๋ฏ๋ก ๊ทธ ๊ฐ์ด ์ ์ง๋๋ค.
โ
์ ์์ ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ํจ์ ๋ ๋ฒจ ์ค์ฝํ ํน์ฑ์ผ๋ก ์ธํด for ๋ฃจํ์ ์ด๊ธฐ๋ฌธ์์ ์ฌ์ฉ๋ ๋ณ์์ ์ค์ฝํ๊ฐ ์ ์ญ์ด ๋๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ ํ์์ด๋ค.
์ฌ์ค โES6์ let ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ด์ ๊ฐ์ ๋ฌธ์ ๋ ๋ง๋ํ ํด๊ฒฐ๋๋ค.
const arr = [];
for (let i = 0; i < 5; i++) {
arr[i] = function () {
return i;
};
}
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]());
}
๋๋ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ๋ฒ์ธ ๊ณ ์ฐจ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
์ด ๋ฐฉ๋ฒ์ ๋ณ์์ ๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉ์ ์ต์ ํ ์ ์๊ธฐ ๋๋ฌธ์ ์ํ๋ฆฌ์ผ์ด์ ์ ์ค๋ฅ๋ฅผ ์ค์ด๊ณ ๊ฐ๋ ์ฑ์ ์ข๊ฒ ๋ง๋ ๋ค.
const arr = new Array(5).fill(); // Array.prototype.fill() ์ธ์๋ฅผ ๋ฐฐ์ด ์ธ์๋ก
// [undefined, undefined, undefined, undefined, undefined]
// fill()์ ์๋ถ์ผ๊ฒฝ์ฐ -> [empty x 5]
arr.forEach((v, i, array) => array[i] = () => i); // ๊ฐ ๋ฐฐ์ด์์์ ํด๋ก์ ํจ์(์ธ๋ถ i ์ฐธ์กฐ)๋ฅผ ๋ฃ๋๋ค.
arr.forEach(f => console.log(f())); // 0 1 2 3 4
// ๊ฐ ๋ฐฐ์ด์์์ ์๋ ์ต๋ช
ํจ์๋ค์ด ๊ฐ๊ฐ ์ธ๋ถ ๋ณ์ i๋ฅผ ๊ฐ๊ฐ ๋ฐ๋ก๋ฐ๋ก ๋
๋ฆฝ์ ์ผ๋ก ์ฐธ์กฐํ๊ณ ์๋ค.
ํด๋ก์ ๋ ํจ์์์ ๋ด๋ถํจ์๋ก์ ์ธ๋ถํจ์์ ๋ณ์๋ฅผ ์ฐธ์กฐ ํ ์์๋ ๋์ด๋ค.
๋ฐ๋ผ์ ํด๋ก์ ๋ฅผ ๋ง๋ค๋ ค๋ฉด, ๋จผ์ ์ธ๋ถํจ์๋ฅผ ๋ง๋ค๊ณ ๋ณ์๋ฅผ ์ ์ธํ๋ค.
๊ทธ๋ฆฌ๊ณ ํด๋ก์ ํจ์๊ฐ ๊ทธ ๋ณ์๋ฅผ ์ฐธ์กฐํ๋๋ก ํ๋ฉด, ๋ง์น static ์ ์ ๋ณ์๋ private ๋ณ์๋ฅผ ๋ง๋ค์ ์๊ฒ ๋๋ค. โ
์ฌ๊ธฐ์ ํด๋ก์ ์ง์ญ ๋ณ์๋ ํจ์๋ด์์ ์ ์ธํด๋ ๋๊ณ , ์๊ท๋จผํธ๋ก ์ง์ ํด๋ ๋๋ค.