- ํด๋ก์ (closure) ๋ ํจ์์ ๊ทธ ํจ์๊ฐ ์ ์ธ๋์ ๋์
๋ ์์ปฌ ํ๊ฒฝ(Lexical environment)
๊ณผ์์กฐํฉ
์ด๋ผ๊ณ ๋ถ๋ฅด๋ฉฐ, ๋ด๋ถ ํจ์๊ฐ ์ธ๋ถํจ์ ๋ณ์์ ์ก์ธ์ค(์ ๊ทผ) ํ ์ ์๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๊ธฐ๋ฅ์ ๋งํ๋ค. - ํด๋ก์ (closure)๋ ๋ฐํ๋ ๋ด๋ถ ํจ์๊ฐ ์์ ์ด
์ ์ธ
๋์์ ๋์ ๋ ์์ปฌ ์ค์ฝํ ํ๊ฒฝ์๊ธฐ์ต
ํ์ฌ, ์์ ์ด ์ ์ธ๋์ ๋์ ํ๊ฒฝ(์ค์ฝํ) ๋ฐ์์ ํธ์ถ๋์ด๋ ๊ทธ ํ๊ฒฝ(์ค์ฝํ)์ ์ ๊ทผํ ์ ์๋ ํจ์- ์? ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ฌ์ ํ ๊ธฐ์ตํ๊ณ ์๊ธฐ ๋๋ฌธ
- ๋ ์์ปฌ ์ค์ฝํ๋ ํจ์๋ฅผ
์ด๋์ ์ ์ธ
ํ์๋์ง์ ๋ฐ๋ผ ์์ ์ค์ฝํ๋ฅผ ๊ฒฐ์ ํ๋ ๋ฐฉ์์ด๋ค.
function init() {
var name = "Mozilla"; // name์ init์ ์ํด ์์ฑ๋ ์ง์ญ ๋ณ์์ด๋ค.
function displayName() {
// displayName() ์ ๋ด๋ถ ํจ์์ด๋ฉฐ, ํด๋ก์ ๋ค.
alert(name); // ๋ถ๋ชจ ํจ์์์ ์ ์ธ๋ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ค.
}
displayName();
}
init();
- init()์
์ง์ญ ๋ณ์ name
๊ณผํจ์ displayName()
์ ์์ฑํ๋ค. - displayName()์ init() ์์ ์ ์๋ ๋ด๋ถ ํจ์์ด๋ฉฐ, init() ํจ์ ๋ณธ๋ฌธ์์๋ง ์ฌ์ฉํ ์ ์๋ค.
- ์ฌ๊ธฐ์ ์ฃผ์ํ ์ ์ displayName() ๋ด๋ถ์ ์์ ๋ง์ ์ง์ญ ๋ณ์๊ฐ ์๋ค๋ ์ ์ด๋ค. ๊ทธ๋ฐ๋ฐ ํจ์ ๋ด๋ถ์์ ์ธ๋ถ ํจ์์ ๋ณ์์ ์ ๊ทผํ ์ ์๊ธฐ ๋๋ฌธ์ displayName() ์ญ์ ๋ถ๋ชจ ํจ์ init()์์ ์ ์ธ๋ ๋ณ์ name์ ์ ๊ทผํ ์ ์๋ค.
- ์ ์์๋ฅผ ํตํด ํจ์๊ฐ ์ค์ฒฉ๋ ์ํฉ์์
ํ์
๊ฐ ์ด๋ป๊ฒ ๋ณ์๋ฅผ ์ฒ๋ฆฌํ๋์ง ์ ์ ์๋ค. ์ด๋๋ ์์ปฌ ์ค์ฝํ(lexical scoping)
์ ํ ์์ด๋ค. - ์ฌ๊ธฐ์ ์ค์ฒฉ๋ ํจ์๋ ์ธ๋ถ ๋ฒ์(scope)์์ ์ ์ธํ ๋ณ์์๋ ์ ๊ทผํ ์ ์๋ค.
const x = 1;
function outer() {
const x = 10;
const inner = function () {
console.log(x);
};
return inner;
}
const func = outer();
func(); // 10
- ์ ์์ ์์ outer๊ฐ ํธ์ถ ๋ ์ดํ์๋
GC(Garbage Collector)
์ ์ํดouter
์ ์ฐธ์กฐ๊ฐ ์ ๊ฑฐ๋ ๊ฒ ๊ฐ์ง๋ง, ๋ด๋ถ ํจ์์ธinner
๊ฐ outer์ ๋ณ์์ธx
๋ฅผ ์ฐธ์กฐํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์์ ์ง ์๋๋ค. - ๋ฐ๋ผ์, ์ค์ฝํ ์ธ๋ถ์์
inner()
๊ฐ ์คํ๋๋outer์ ์ค์ฝํ๋ฅผ ๊ธฐ์ตํ๊ธฐ ๋๋ฌธ์ 10๋ฅผ ์ถ๋ ฅ
ํ๊ฒ ๋๋ค. ์ฆ, ์ฌ๊ธฐ์ํด๋ก์
๋inner
๊ฐ ๋๋ฉฐ ๋ณ์ func์ ๋ด๊ฒจ outer ๋ฐ์์๋ ์คํ๋๋ outer์ ๋ ์์ปฌ ์ค์ฝํ๋ฅผ ๊ธฐ์ตํ๋ค.
- ํ ๋์ ๋ด์๋ ์ด ์ฝ๋๊ฐ ์ฌ์ ํ ์๋ํ๋ ๊ฒ์ด ์ง๊ด์ ์ผ๋ก ๋ณด์ด์ง ์์ ์ ์๋ค. ๋ช๋ช ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์, ํจ์ ์์ ์ง์ญ ๋ณ์๋ค์ ๊ทธ ํจ์๊ฐ ์ฒ๋ฆฌ๋๋ ๋์์๋ง ์กด์ฌํ๋ค. ์ฆ,
outer
์คํ์ด ๋๋๋ฉด (innerํจ์๊ฐ ๋ฆฌํด๋๊ณ ๋๋ฉด) x๋ณ์์ ๋ ์ด์ ์ ๊ทผํ ์ ์๊ฒ ๋ ๊ฒ์ผ๋ก ์์ํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ค. - ํ์ง๋ง, ์์ ์์์ ์๋ฐ์คํฌ๋ฆฝํธ์ ๊ฒฝ์ฐ๋ ๋ค๋ฅด๋ค. ๊ทธ ์ด์ ๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ ํจ์๋ฅผ ๋ฆฌํดํ๊ณ , ๋ฆฌํดํ๋ ํจ์๊ฐ
ํด๋ก์
๋ฅผ ํ์ฑํ๊ธฐ ๋๋ฌธ์ด๋ค. ํด๋ก์ ๋ํจ์์ ํจ์๊ฐ ์ ์ธ๋ ๋ ์์ปฌ ํ๊ฒฝ์ ์กฐํฉ
์ด๋ค. ์ด ํ๊ฒฝ์ ํด๋ก์ ๊ฐ์์ฑ๋ ์์ ์ ์ ํจ ๋ฒ์ ๋ด์ ์๋ ๋ชจ๋ ์ง์ญ ๋ณ์
๋ก ๊ตฌ์ฑ๋๋ค.
function func() {
for (var i = 1; i < 5; i++) {
setTimeout(() => {
console.log(i);
}, i * 500);
}
}
func(); // 5 5 5 5
- ์ ์์๋ ํด๋ก์ ๋ฅผ ์ฌ์ฉํ๋ ๋ํ์ ์ธ ์์์ด๋ค.
- ์ฝ๋์ ์๋ํ ๋ฐ๋ 1๋ถํฐ 4๊น์ง ๊ฐ๊ฒฉ์ ๋๊ณ ์ถ๋ ฅํ๋ ๊ฒ์ด์์ง๋ง 5๊ฐ 4๋ฒ ์ถ๋ ฅ๋๋ค.
- ๊ทธ ์ด์ ๋? setTimeout() ์ ๋ฐ๋ณต๋ฌธ ์์์ ๋๋ฆฌ๋ฉด ์ฝ๋ฐฑํจ์๊ฐ ๊ณ์ํด์
task queue
์ ์์ด๊ฒ ๋๊ณ ๋ฐ๋ณต๋ฌธ์ด ๋๋๊ณ ๋์!!call stack
์ผ๋ก ๋์์์ ์คํ๋๋ค. - ์ฝ๋ฐฑ ํจ์๋
ํด๋ก์
์ด๊ธฐ ๋๋ฌธ์ ์์ ์ค์ฝํ์๊ฒ i์ ๊ฐ์ ๋ฌผ์ด๋ณด๊ณ ์์ ์ค์ฝํ์ธ func ์ ์ค์ฝํ์์ i๊ฐ 5๊น์ง ์ฆ๊ฐํ๊ธฐ ๋๋ฌธ์ 5๊ฐ 4๋ฒ ์ถ๋ ฅ๋๋ค.
- ๋ธ๋ก ๋ ๋ฒจ ์ค์ฝํ๋ก ํด๊ฒฐํ๊ธฐ
function func() {
for (let i = 1; i < 5; i++) {
setTimeout(() => {
console.log(i);
}, i * 500);
}
}
func(); // 1 2 3 4
- ํจ์ ๋ ๋ฒจ ์ค์ฝํ๊ฐ ์๋ ๋ธ๋ก ๋ ๋ฒจ ์ค์ฝํ์ธ
let
์ ์ฌ์ฉํ๋ค. let
์ ์ฌ์ฉํ๋ฉด for๋ฌธ ๋ด์ ์๋ก์ด ์ค์ฝํ๋ฅผ ๊ฐ๊ธฐ ๋๋ฌธ์ ๋งค ๋ฐ๋ณต๋ง๋ค ์๋ก์ด i ๊ฐ ์ ์ธ๋๊ณ , ๋ฐ๋ณต์ด ๋๋ ์ดํ์ ๊ฐ์ผ๋ก ์ด๊ธฐํ๊ฐ ๋๋ค.- ๋ฐ๋ผ์, setTimeout()์ ํด๋ก์ ์ธ ์ฝ๋ฐฑํจ์๊ฐ i๋ฅผ ์ฐธ์กฐํ๊ธฐ ์ํด ์์ ์ค์ฝํ๋ฅผ ๊ฒ์ํ ๋
๋ธ๋ก ๋ ๋ฒจ ์ค์ฝํ
์์ ๋งค ๋ฐ๋ณต๋ง๋ค ์ ์ธ ๋ฐ ์ด๊ธฐํ ๋ i๋ฅผ ์ฐธ์กฐํ๋ ๊ฒ์ด๋ค.
https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/closure.md
https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures
https://jhleed.tistory.com/150