MDN์์๋ ํด๋ก์ ๋ "ํจ์์ ๊ทธ ํจ์๊ฐ ์ ์ธ๋ ๋น์์ lexical environment์ ์ํธ๊ด๊ณ์ ๋ฐ๋ฅธ ํ์" ์ด๋ผ๊ณ ์๊ฐํ๊ณ ์์ต๋๋ค.
'์ ์ธ๋ ๋น์์ LexicalEnvironment'๋ ์คํ ์ปจํ ์คํธ์ ๊ตฌ์ฑ ์์ ์ค ํ๋์ธ outerEnvironmentReference์ ํด๋นํฉ๋๋ค.
LexicalEnvironment์ environmentRecord์ outerEnvironmentReference์ ์ํด ๋ณ์์ ์ ํจ๋ฒ์์ธ ์ค์ฝํ๊ฐ ๊ฒฐ์ ๋๊ณ ์ค์ฝํ ์ฒด์ธ์ด ๊ฐ๋ฅํด์ง๋๋ค.
-
ํ๊ฒฝ๋ ์ฝ๋(environmentRecord) - ๋ชจ๋ ์ง์ญ ๋ณ์๋ฅผ ํ๋กํผํฐ๋ก ์ ์ฅํ๊ณ ์๋ ๊ฐ์ฒด. this๊ฐ ์ฐธ์กฐํ๋ ๊ฐ ๋ฑ์ ์ ๋ณด๋ ์ ์ฅ๋จ.
-
์ธ๋ถํ๊ฒฝ์ฐธ์กฐ(outerEnvironmentReference) - ์ธ๋ถ ์ฝ๋์ ์ฐ๊ด๋์ด ์์.
์ด๋ค ์ปจํ ์คํธ A์์ ์ ์ธํ ๋ด๋ถํจ์ B์ ์คํ ์ปจํ ์คํธ๊ฐ ํ์ฑํ๋ ์์ ์๋ B์ outerEnvironmentReference๊ฐ ์ฐธ์กฐํ๋ ๋์์ธ A์ LexicalEnvironment์๋ ์ ๊ทผ์ด ๊ฐ๋ฅํฉ๋๋ค. A์์๋ B์์ ์ ์ธํ ๋ณ์์ ์ ๊ทผํ ์ ์์ง๋ง B์์๋ A์์ ์ ์ธํ ๋ณ์์ ์ ๊ทผ ๊ฐ๋ฅํฉ๋๋ค.
์ฌ๊ธฐ๊น์ง ํ์ ํ ๋ด์ฉ์ ๋ฐ๋ฅด๋ฉด ํด๋ก์ ๋, "์ด๋ค ํจ์์์ ์ ์ธํ ๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ๋ด๋ถํจ์์์๋ง ๋ฐ์ํ๋ ํ์" ์ด๋ผ๊ณ ๋ณผ ์ ์๊ฒ ๋๋ฐ์. ์์ง ์๋ฟ์ง ์์ผ๋ ์์ ๋ฅผ ํตํด ์ข ๋ ๋ช ํํ ์์๋ณด๊ฒ ์ต๋๋ค. ์์ ๋ฅผ ๋ณด๊ธฐ ์ ์์ ๋ด์ฉ์ ๋ ์ ์ดํดํ๊ธฐ ์ํด ๋ฐ์์ ์ค์ฝํ์ ์ค์ฝํ์ฒด์ธ, outerEnvironmentReference์ ๋ํด ์ ๊น ์ง๊ณ ๋์ด๊ฐ๊ฒ ์ต๋๋ค.
์ค์ฝํ๋ ์๋ณ์์ ๋ํ ์ ํจ๋ฒ์์ ๋๋ค. ์ด๋ค ๊ฒฝ๊ณ A์ ์ธ๋ถ์์ ์ ์ธํ ๋ณ์๋ A์ ์ธ๋ถ๋ฟ ์๋๋ผ A์ ๋ด๋ถ์์๋ ์ ๊ทผ์ด ๊ฐ๋ฅํ์ง๋ง, A์ ๋ด๋ถ์์ ์ ์ธํ ๋ณ์๋ ์ค์ง A์ ๋ด๋ถ์์๋ง ์ ๊ทผํ ์ ์์ต๋๋ค. '์๋ณ์์ ์ ํจ๋ฒ์'๋ฅผ ์์์๋ถํฐ ๋ฐ๊นฅ์ผ๋ก ์ฐจ๋ก๋ก ๊ฒ์ํด๋๊ฐ๋ ๊ฒ์ ์ค์ฝํ ์ฒด์ธ์ด๋ผ๊ณ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋ ๊ฒ์ด ๋ฐ๋ก LexicalEnvironment์ ๋ ๋ฒ์งธ ์์ง์๋ฃ์ธ outerEnvironmentReference์ ๋๋ค.
1) ์ค์ฝํ ์ฒด์ธ
outerEnvironmentReference๋ ํ์ฌ ํธ์ถ๋ ํจ์๊ฐ ์ ์ธ๋ ๋น์์ LexicalEnvironment๋ฅผ ์ฐธ์กฐํฉ๋๋ค. ๊ณผ๊ฑฐ ์์ ์ธ '์ ์ธ๋ ๋น์'์ ์ฃผ๋ชฉํด์ผํฉ๋๋ค.
์๋ฅผ ๋ค์ด, Aํจ์ ๋ด๋ถ์ Bํจ์๋ฅผ ์ ์ธํ๊ณ ๋ค์ Bํจ์ ๋ด๋ถ์ C ํจ์๋ฅผ ์ ์ธํ ๊ฒฝ์ฐ, ํจ์ C์ outerEnvironmentReference๋ ํจ์ B์ LexicalEnvironment๋ฅผ ์ฐธ์กฐํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํจ์ B์ LexicalEnvironment์ ์๋ outerEnvironmentReference๋ ๋ค์ ํจ์ B๊ฐ ์ ์ธ ๋๋ ๋(A)์ lexicalEnvironment๋ฅผ ์ฐธ์กฐํ๊ฒ๋ฉ๋๋ค.
'์ ์ธ์์ ์ LexicalEnvironment'๋ฅผ ๊ณ์ ์ฐพ์ ์ฌ๋ผ๊ฐ๋ฉด ๋ง์ง๋ง์ ์ ์ญ ์ปจํ ์คํธ์ LexicalEnvironment๊ฐ ์์ ๊ฒ์ ๋๋ค.
๋ํ ๊ฐ outerEnvironmentReference๋ ์ค์ง ์์ ์ด ์ ์ธ๋ ์์ ์ LexicalEnvironment๋ง ์ฐธ์กฐํ๊ณ ์์ผ๋ฏ๋ก ๊ฐ์ฅ ๊ฐ๊น์ด ์์๋ถํฐ ์ฐจ๋ก๋๋ก๋ง ์ ๊ทผํ ์ ์๊ณ ๋ค๋ฅธ ์์๋ก ์ ๊ทผํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํ ๊ฒ์ ๋๋ค.
์ด๋ฐ ๊ตฌ์กฐ์ ํน์ฑ ๋๋ถ์ ์ฌ๋ฌ ์ค์ฝํ์์ ๋์ผํ ์๋ณ์๋ฅผ ์ ์ธํ ๊ฒฝ์ฐ์๋ ๋ฌด์กฐ๊ฑด ์ค์ฝํ ์ฒด์ธ ์์์ ๊ฐ์ฅ ๋จผ์ ๋ฐ๊ฒฌ๋ ์๋ณ์์๋ง ์ ๊ทผ ๊ฐ๋ฅํ๊ฒ ๋ฉ๋๋ค.
์๋ ์์๋ฅผ ํตํด ์ข ๋ ๊ตฌ์ฒด์ ์ผ๋ก ์์๋ณด๊ฒ ์ต๋๋ค
// (์์)
var a = 1; // (1)
var outer = function() { // (3)
var inner = function() { // (4) / (6)
console.log(a); // (7)
var a = 3; // (8)
}; // (9)
inner(); // (5)
console.log(a); // (10)
} // (11)
outer(); // (2)
console.log(a) // (12)
// -- ๊ฒฐ๊ณผ --
// undefined
// 1
// 1-
(์์) : ์ ์ญ ์ปจํ ์คํธ๊ฐ ํ์ฑํ ๋ฉ๋๋ค. ์ ์ญ ์ปจํ ์คํธ์ environmentRecord์ { a, outer } ์๋ณ์๋ฅผ ์ ์ฅํ๊ณ , ์ ์ญ ์ปจํ ์คํธ๋ ์ ์ธ ์์ ์ด ์์ผ๋ฏ๋ก ์ ์ญ ์ปจํ ์คํธ์ outerEnvironmentReference์๋ ์๋ฌด๊ฒ๋ ๋ด๊ธฐ์ง ์์ต๋๋ค.
-
(1) : ์ ์ญ ์ค์ฝํ์ ์๋ ๋ณ์ a์ 1์, outer์ ํจ์๋ฅผ ํ ๋นํฉ๋๋ค.
-
(2) : outer ํจ์๋ฅผ ํธ์ถํฉ๋๋ค. ์ด์ ๋ฐ๋ผ ์ ์ญ ์ปจํ ์คํธ์ ์ฝ๋๋ ์ด ์ค์์ ์์ ์ค๋จ๋๊ณ , outer ์คํ ์ปจํ ์คํธ๊ฐ ํ์ฑํ๋์ด 2๋ฒ์งธ ์ค๋ก ์ด๋ํฉ๋๋ค.
-
(3) : outer ์คํ ์ปจํ ์คํธ์ environmentRecord์ { inner } ์๋ณ์๋ฅผ ์ ์ฅํฉ๋๋ค. outerEnvironmentReference์๋ outer ํจ์๊ฐ ์ ์ธ๋ ๋น์์ LexicalEnvironment๊ฐ ๋ด๊ธฐ๋ฉฐ, outer ํจ์๋ ์ ์ญ ๊ณต๊ฐ์์ ์ ์ธ๋์ผ๋ฏ๋ก ์ ์ญ ์ปจํ ์คํธ์ LexicalEnvironment๋ฅผ ์ฐธ์กฐ๋ณต์ฌํฉ๋๋ค. [ Global, { a, outer } ] ์ฒซ ๋ฒ์งธ๋ ์คํ ์ปจํ ์คํธ์ ์ด๋ฆ, ๋ ๋ฒ์งธ๋ environmentRecord ๊ฐ์ฒด์ ๋๋ค.
-
(4) : outer ์ค์ฝํ์ ์๋ ๋ณ์ inner์ ํจ์๋ฅผ ํ ๋นํฉ๋๋ค.
-
(5) : inner ํจ์๋ฅผ ํธ์ถํฉ๋๋ค. ์ด์ ๋ฐ๋ผ outer ์คํ ์ปจํ ์คํธ์ ์ฝ๋๋ ์ด ์ค์์ ์์ ์ค๋จ๋๊ณ , inner ์คํ ์ปจํ ์คํธ๊ฐ ํ์ฑํ ๋์ด ์ธ ๋ฒ์งธ ์ค๋ก ์ด๋ํฉ๋๋ค.
-
(6) : inner ์คํ ์ปจํ ์คํธ์ environmentRecord์ { a } ์๋ณ์๋ฅผ ์ ํฉ๋๋ค. outerEnvironmentReference์๋ inner ํจ์๊ฐ ์ ์ธ๋ ๋น์์ LexicalEnvironment๊ฐ ๋ด๊ธฐ๋ฉฐ inner ํจ์๋ outer ํจ์ ๋ด๋ถ์์ ์ ์ธ๋์ผ๋ฏ๋ก outer ํจ์์ LexicalEnvironment, ์ฆ [ outer, { inner } ]๋ฅผ ์ฐธ์กฐ๋ณต์ฌํฉ๋๋ค.
-
(7) : ์๋ณ์ a์ ์ ๊ทผํ๊ณ ์ ํฉ๋๋ค. ํ์ฌ ํ์ฑํ ์ํ์ธ inner ์ปจํ ์คํธ์ environmentRecord์์ a๋ฅผ ๊ฒ์ํ์ฌ ๋ฐ๊ฒฌํ์ง๋ง ์ฌ๊ธฐ์๋ ์์ง ํ ๋ต๋ ๊ฐ์ด ์์ต๋๋ค. (undefined ์ถ๋ ฅ)
-
(8) : inner ํจ์ ์คํ์ด ์ข ๋ฃ๋ฉ๋๋ค. inner ์คํ ์ปจํ ์คํธ๊ฐ ์ฝ ์คํ์์ ์ ๊ฑฐ๋๊ณ , ๋ฐ๋ก ์๋์ outer ์คํ ์ปจํ ์คํธ๊ฐ ๋ค์ ํ์ฑํ๋๋ฉด์ 5)์์ ์ค๋จํ๋ ์ค์ ๋ค์์ผ๋ก ์ด๋ํฉ๋๋ค.
-
(9) : inner ํจ์ ์คํ์ด ์ข ๋ฃ๋ฉ๋๋ค. inner ์คํ ์ปจํ ์คํธ๊ฐ ์ฝ ์คํ์์ ์ ๊ฑฐ๋๊ณ , ๋ฐ๋ก ์๋์ outer ์คํ ์ปจํ ์คํธ๊ฐ ๋ค์ ํ์ฑํ๋๋ฉด์ (5)์์ ์ค๋จํ๋ ์ค์ ๋ค์์ผ๋ก ์ด๋ํฉ๋๋ค.
-
(10) : ์๋ณ์ a์ ์ ๊ทผํ๊ณ ์ ํฉ๋๋ค. ํ์ฑํ๋ ์คํ ์ปจํ ์คํธ์ LexicalEnvironment์ ์ ๊ทผํ๋ฉฐ ์ฒซ ์์์ environmentRecord์์ a๊ฐ ์๋์ง ์ฐพ์๋ณด๊ณ , ์์ผ๋ฉด outerEnvironmentReference์ ์๋ environmentRecord๋ก ๋์ด๊ฐ๋ ์์ผ๋ก ๊ณ์ํด์ ๊ฒ์ํฉ๋๋ค. ์์ ์์๋ ๋ ๋ฒ์งธ, ์ฆ ์ ์ญ LexicalEnvironment์ a๊ฐ ์์ผ๋ ๊ทธ a์ ์ ์ฅ๋ ๊ฐ 1์ ๋ฐํ. (1 ์ถ๋ ฅ)
-
(11) : outer ํจ์ ์คํ์ด ์ข ๋ฃ๋ฉ๋๋ค. outer ์คํ ์ปจํ ์คํธ๊ฐ ์ฝ ์คํ์์ ์ ๊ฑฐ๋๊ณ , ๋ฐ๋ก ์๋์ ์ ์ญ ์ปจํ ์คํธ๊ฐ ๋ค์ ํ์ฑํ ๋๋ฉด์ 2)์์ ์ค๋จํ๋ ์ค์ ๋ค์์ผ๋ก ์ด๋ํฉ๋๋ค.
-
(12) : ์๋ณ์ a์ ์ ๊ทผํ๊ณ ์ ํฉ๋๋ค. ํ์ฌ ํ์ฑํ ์ํ์ธ ์ ์ญ ์ปจํ ์คํธ์ environmentRecord์์ a๋ฅผ ๊ฒ์ํ๋ฉฐ ๋ฐ๋ก a๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค(1 ์ถ๋ ฅ). ์ด๋ก์จ ๋ชจ๋ ์ฝ๋์ ์คํ์ด ์๋ฃ๋์ด ์ ์ญ ์ปจํ ์คํธ๊ฐ ์ฝ ์คํ์์ ์ ๊ฑฐ๋๊ณ ์ข ๋ฃ๋ฉ๋๋ค.
outerEnvironmentReference๋ ํด๋น ํจ์๊ฐ ์ ์ธ๋ ์์น์ LexicalEnvironment๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
์ฝ๋ ์์์ ์ด๋ค ๋ณ์์ ์ ๊ทผํ๋ ค๊ณ ํ๋ฉด ํ์ฌ ์ปจํ ์คํธ์ LexicalEnvironment๋ฅผ ํ์ํด์ ๋ฐ๊ฒฌ๋๋ฉด ๊ทธ ๊ฐ์ ๋ฐํํ๊ณ , ๋ฐ๊ฒฌํ์ง ๋ชปํ ๊ฒฝ์ฐ ๋ค์ outerEnvironmentReference์ ๋ด๊ธด LexicalEnvironment๋ฅผ ํ์ํ๋ ๊ณผ์ ์ ๊ฑฐ์นฉ๋๋ค.
์ ์ญ ์ปจํ ์คํธ์ LexicalEnvironment๊น์ง ํ์ํด๋ ํด๋น ๋ณ์๋ฅผ ์ฐพ์ง ๋ชปํ๋ฉด undefined๋ฅผ ๋ฐํํฉ๋๋ค.
๋ค์ ํด๋ก์ ๋ก ๋์์, ์ธ๋ถํจ์์์ ๋ณ์๋ฅผ ์ ์ธํ๊ณ ๋ด๋ถํจ์์์ ํด๋น ๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ํํ์ ์ฝ๋๋ฅผ ๋ณด๊ฒ ์ต๋๋ค.
// ์ธ๋ถ ํจ์์ ๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ๋ด๋ถ ํจ์(1)
var outer = function() {
var a = 1;
var inner = function() {
console.log(++a);
};
inner();
}
outer();
// -- ๊ฒฐ๊ณผ --
// 2์์ ์์ ์์๋ outer ํจ์์์ ๋ณ์ a๋ฅผ ์ ์ธํ๊ณ , outer์ ๋ด๋ถํจ์์ธ inner ํจ์์์ a์ ๊ฐ์ 1๋งํผ ์ฆ๊ฐ์ํจ ๋ค์ ์ถ๋ ฅํฉ๋๋ค.
inner ํจ์ ๋ด๋ถ์์๋ a๋ฅผ ์ ์ธํ์ง ์์๊ธฐ ๋๋ฌธ์ environmentRecord์์ ๊ฐ์ ์ฐพ์ง ๋ชปํ๋ฏ๋ก outerEnvironmentReference์ ์ง์ ๋ ์์ ์ปจํ ์คํธ outer์ LexicalEnvironment์ ์ ๊ทผํ์ฌ ๋ค์ a๋ฅผ ์ฐพ์ต๋๋ค. ๋ค ๋ฒ์งธ ์ค์์๋ 2๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค.
outer ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ์ข ๋ฃ๋๋ฉด LexicalEnvironment์ ์ ์ฅ๋ ์๋ณ์๋ค(a, inner)์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ง์๋๋ค. ๊ทธ๋ฌ๋ฉด ๊ฐ ์ฃผ์์ ์ ์ฅ๋ผ ์๋ ๊ฐ๋ค์ ์์ ์ ์ฐธ์กฐํ๋ ๋ณ์๊ฐ ํ๋๋ ์๊ฒ ๋๋ฏ๋ก ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ์์ง ๋์์ด ๋ ๊ฒ์ ๋๋ค.
๋ด์ฉ์ ์กฐ๊ธ ๋ฐ๊พผ ๋ฐ ์์ ๋ฅผ ์ด์ด์ ๋ณด๊ฒ ์ต๋๋ค.
// ์ธ๋ถ ํจ์์ ๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ๋ด๋ถ ํจ์(2)
var outer = function() {
var a = 1;
var inner = function() {
return ++a;
}
return inner(); // inner ํจ์ ๊ฒฐ๊ณผ ๋ฐํ
};
var outer2 = outer();
console.log(outer2);
// -- ๊ฒฐ๊ณผ --
// 2์ ์ฝ๋์์๋ inner ํจ์ ๋ด๋ถ์์ ์ธ๋ถ ๋ณ์์ธ a๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ๊ทธ๋ฐ๋ฐ 6๋ฒ์งธ ์ค์์๋ inner ํจ์์ ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดํ๊ณ ์์ผ๋ฏ๋ก ๊ฒฐ๊ณผ์ ์ผ๋ก outer ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ์ข ๋ฃ๋ ์์ ์๋ a๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ๋์์ด ์์ด์ง๋๋ค. a, inner ๋ณ์์ ๊ฐ๋ค์ ์ธ์ ๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ์ํด ์๋ฉธํ๊ฒ๋ฉ๋๋ค.
์์ (1), (2) ์์ ๋ outer ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ์ข ๋ฃ๋๊ธฐ ์ด์ ์ inner ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ์ข ๋ฃ๋ผ ์์ผ๋ฉฐ, ์ดํ ๋ณ๋๋ก inner ํจ์๋ฅผ ํธ์ถํ ์ ์๋ค๋ ๊ณตํต์ ์ด ์์ต๋๋ค.
๊ทธ๋ ๋ค๋ฉด outer์ ์คํ ์ปจํ ์คํธ๊ฐ ์ข ๋ฃ๋ ํ์๋ inner ํจ์๋ฅผ ํธ์ถํ ์ ์๊ฒ ๋ง๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? ๋ฐ์ (3) ์์ ์ฝ๋๋ฅผ ๋ณด๊ฒ ์ต๋๋ค.
// ์ธ๋ถ ํจ์์ ๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ๋ด๋ถ ํจ์(3)
var outer = function() {
var a = 1;
var inner = function() {
return ++a;
}
return inner; // inner ํจ์ ์์ฒด ๋ฐํ
};
var outer2 = outer();
console.log(outer2());
console.log(outer2());
// -- ๊ฒฐ๊ณผ --
// 2
// 3์ด๋ฒ์๋ 6๋ฒ์งธ ์ค์์ inner ํจ์์ ์คํ ๊ฒฐ๊ณผ๊ฐ ์๋ inner ํจ์ ์์ฒด๋ฅผ ๋ฐํํ์ต๋๋ค. ๊ทธ๋ฌ๋ฉด outer ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ์ข ๋ฃ๋ ๋ outer2 ๋ณ์๋ outer์ ์คํ ๊ฒฐ๊ณผ์ธ inner ํจ์๋ฅผ ์ฐธ์กฐํ๊ฒ ๋ ๊ฒ์ ๋๋ค. ์ดํ 9๋ฒ์งธ ์ค์์ outer2๋ฅผ ํธ์ถํ๋ฉด ์์ ๋ฐํ๋ ํจ์์ธ inner๊ฐ ์คํ๋ฉ๋๋ค.
inner ํจ์ ์คํ ์ปจํ ์คํธ์ environmentRecord์๋ ์์งํ ์ ๋ณด๊ฐ ์์ต๋๋ค. outerEnvironmentReference์๋ inner ํจ์๊ฐ ์ ์ธ๋ ์์น์ LexicalEnvironment๊ฐ ์ฐธ์กฐ๋ณต์ฌ๋ฉ๋๋ค. inner ํจ์๋ outer ํจ์ ๋ด๋ถ์์ ์ ์ธ๋์ผ๋ฏ๋ก, outer ํจ์์ LexicalEnvironment๊ฐ ๋ด๊ธฐ๊ฒ ๋ฉ๋๋ค.
์ด์ ์ค์ฝํ ์ฒด์ด๋์ ๋ฐ๋ผ outer์์ ์ ์ธํ ๋ณ์ a์ ์ ๊ทผํ์ฌ 1๋งํผ ์ฆ๊ฐ์ํจ ํ ๊ทธ ๊ฐ์ธ 2๋ฅผ ๋ฐํํ๊ณ , inner ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ์ข ๋ฃ๋ฉ๋๋ค. ๋ค์ outer2๋ฅผ ํธ์ถํ๋ฉด ๊ฐ์ ๋ฐฉ์์ผ๋ก a์ ๊ฐ์ 2์์ 3์ผ๋ก 1 ์ฆ๊ฐ์ํจ ํ 3์ ๋ฐํํฉ๋๋ค.
โโโ
์ฌ๊ธฐ์, inner ํจ์์ ์คํ ์์ ์๋ outer ํจ์๋ ์ด๋ฏธ ์คํ์ด ์ข ๋ฃ๋ ์ํ์ธ๋ฐ ์ด๋ป๊ฒ outer ํจ์์ LexicalEnvironment์ ์ ๊ทผํ ์ ์๋ ๊ฑธ๊น์?
์ด๋ ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ๋์ ๋ฐฉ์ ๋๋ฌธ์ ๋๋ค. ๊ฐ๋น์ง ์ปฌ๋ ํฐ๋ ์ด๋ค ๊ฐ์ ์ฐธ์กฐํ๋ ๋ณ์๊ฐ ํ๋๋ผ๋ ์๋ค๋ฉด ๊ทธ ๊ฐ์ ์์ง ๋์์ ํฌํจ์ํค์ง ์์ต๋๋ค.
์์ ์์ ์์ outer ํจ์๋ ์คํ ์ข ๋ฃ ์์ ์ inner ํจ์๋ฅผ ๋ฐํํฉ๋๋ค. ์ธ๋ถํจ์์ธ outer์ ์คํ์ด ์ข ๋ฃ๋๋๋ผ๋ ๋ด๋ถ ํจ์์ธ innerํจ์๋ ์ธ์ ๊ฐ outer2๋ฅผ ์คํํจ์ผ๋ก์จ ํธ์ถ๋ ๊ฐ๋ฅ์ฑ์ด ์ด๋ฆฐ ๊ฒ์ ๋๋ค. ์ธ์ ๊ฐ inner ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ํ์ฑํ๋๋ฉด outerEnvironmentReference๊ฐ outer ํจ์์ LexicalEnvironment๋ฅผ ํ์๋ก ํ ๊ฒ์ด๋ฏ๋ก ์์ง ๋์์์ ์ ์ธ๋ฉ๋๋ค. ์ด ๋๋ฌธ์ inner ํจ์๊ฐ ์ด ๋ณ์์ ์ ๊ทผํ ์ ์๋ ๊ฒ์ ๋๋ค.
๐๐
ํด๋ก์ ๋ ์ด๋ค ํจ์์์ ์ ์ธํ ๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ๋ด๋ถ ํจ์์์๋ง ๋ฐ์ํ๋ ํ์์ด๋ผ๊ณ ํ์ต๋๋ค. ์์ (3)์ ๊ฒฝ์ฐ๋ ๋ณ์ a๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ํฐ ์์ง ๋์์์ ์ ์ธ๋์ต๋๋ค.
์ด์ฒ๋ผ ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ์ข ๋ฃ๋ ํ์๋ LexicalEnvironment๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ์์ง ๋์์์ ์ ์ธ๋๋ ๊ฒฝ์ฐ๋ ์์ (3)๊ณผ ๊ฐ์ด ์ง์ญ๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ๋ด๋ถ ํจ์๊ฐ ์ธ๋ถ๋ก ์ ๋ฌ๋ ๊ฒฝ์ฐ๊ฐ ์ ์ผํฉ๋๋ค.
"์ด๋ค ํจ์์์ ์ ์ธํ ๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ๋ด๋ถํจ์์์๋ง ๋ฐ์ํ๋ ํ์"์ด๋ "์ธ๋ถ ํจ์์ LexicalEnvironment๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ํ ๋์ง ์๋ ํ์"์ ๋งํ๋ ๊ฒ์ด๊ฒ ์ฃ .
์ด๋ฅผ ๋ฐํ์ผ๋ก ํด๋ก์ ์ ์ ์๋ฅผ ๋ค์ ์ ๋ฆฌํด๋ณด๋ฉด ์ด๋ ์ต๋๋ค.
ํด๋ก์ ๋ ์ด๋ค ํจ์ A์์ ์ ์ธํ ๋ณ์ a๋ฅผ ์ฐธ์กฐํ๋ ๋ด๋ถํจ์ B๋ฅผ ์ธ๋ถ๋ก ์ ๋ฌํ ๊ฒฝ์ฐ A์ ์คํ ์ปจํ ์คํธ๊ฐ ์ข ๋ฃ๋ ์ดํ์๋ ๋ณ์ a๊ฐ ์ฌ๋ผ์ง์ง ์๋ ํ์์ ๋งํฉ๋๋ค
๋ค๋ฅธ ์์ ๋ค์์๋ ํด๋ก์ ๋ฅผ ์ด๋ ๊ฒ ์ ์ํ๊ณ ์์ต๋๋ค.
-
ํจ์๋ฅผ ์ ์ธํ ๋ ๋ง๋ค์ด์ง๋ ์ ํจ๋ฒ์๊ฐ ์ฌ๋ผ์ง ํ์๋ ํธ์ถํ ์ ์๋ ํจ์ - <<์๋ฐ์คํฌ๋ฆฝํธ ๋์ ๋น๊ธ. ์ธ์ฌ์ดํธ>>
-
์ด๋ฏธ ์๋ช ์ฃผ๊ธฐ๊ฐ ๋๋ ์ธ๋ถ ํจ์์ ๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ํจ์ - <<์ธ์ฌ์ด๋ ์๋ฐ์คํฌ๋ฆฝํธ.ํ๋น๋ฏธ๋์ด>>
-
์์ ์ด ์์ฑ๋ ๋์ ์ค์ฝํ์์ ์ ์ ์์๋ ๋ณ์๋ค ์ค ์ธ์ ๊ฐ ์์ ์ด ์คํ๋ ๋ ์ฌ์ฉํ ๋ณ์๋ค๋ง์ ๊ธฐ์ตํ์ฌ ์ ์ง์ํค๋ ํจ์ - <<ํจ์ํ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ก๊ทธ๋๋ฐ.์ธ์ฌ์ดํธ>>
โโโ
์ฃผ์ํ ์ ์ด ํ ๊ฐ์ง ์์ต๋๋ค. ๋ฐ๋ก '์ธ๋ถ๋ก ์ ๋ฌ'์ด ๊ณง return๋ง์ ์๋ฏธํ๋ ๊ฒ์ ์๋๋ผ๋ ์ ์ ๋๋ค. ๋ฐ์ ์ฝ๋๋ฅผ ํตํด ํ์ธํด๋ณด๊ฒ ์ต๋๋ค.
// return ์์ด๋ ํด๋ก์ ๊ฐ ๋ฐ์ํ๋ ๋ค์ํ ๊ฒฝ์ฐ
// setInterval / setTimeout
(function() {
var a = 0;
var intervalId = null;
var inner = function() {
if(++a >= 10) {
clearInterval(intervalId);
}
console.log(a);
};
intervalId = setInterval(inner, 1000);
})
// -- ๊ฒฐ๊ณผ --
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 10์์ ์์ ๋ ๋ณ๋์ ์ธ๋ถ๊ฐ์ฒด์ธ window์ ๋ฉ์๋(setTimeout ๋๋ setInterval)์ ์ ๋ฌํ ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์์ ์ง์ญ๋ณ์๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
// return ์์ด๋ ํด๋ก์ ๊ฐ ๋ฐ์ํ๋ ๋ค์ํ ๊ฒฝ์ฐ
// eventListener
(function() {
var count = 0;
var button = document.createElement("button");
button.innerText = "Click";
button.addEventListener("click", function() {
console.log(++count, "times clicked!");
});
document.body.appendChild(button);
})
// -- ๊ฒฐ๊ณผ --
// 1 "times clicked!"
// 2 "times clicked!"
// 3 "times clicked!"
// 4 "times clicked!"
// ...์์ ๋ ๋ฒ์งธ ์์ ์์๋ ๋ณ๋์ ์ธ๋ถ๊ฐ์ฒด์ธ DOM์ ๋ฉ์๋(addEventListener)์ ๋ฑ๋กํ handler ํจ์ ๋ด๋ถ์์ ์ง์ญ๋ฒ์๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
๋ ์์ ์ฝ๋ ๋ชจ๋ ์ง์ญ๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ๋ด๋ถํจ์๋ฅผ ์ธ๋ถ์ ์ ๋ฌํ๊ธฐ ๋๋ฌธ์ ํด๋ก์ ์ ๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๋์์ ์ํ์ ์ด์ ๋ก ํด๋ก์ ์ฌ์ฉ์ ์กฐ์ฌํด์ผ ํ๋ค๊ฑฐ๋ ์ฌ์ง์ด ์ง์ํด์ผ ํ๋ค๊ณ ์ฃผ์ฅํ๋ ์ฌ๋๋ค๋ ์์ง๋ง ๋ฉ๋ชจ๋ฆฌ ์๋ชจ๋ ํด๋ก์ ์ ๋ณธ์ง์ ์ธ ํน์ฑ์ผ ๋ฟ, ์คํ๋ ค ์ด๋ฌํ ํน์ฑ์ ์ ํํ ์ดํดํ๊ณ ์ ํ์ฉํ ์ ์๋๋ก ๋ ธ๋ ฅํด์ผ ํ๋ค๊ณ ์ฑ ์์ ์ ์๊ฐ ๋งํ๊ณ ์์ต๋๋ค.
'๋ฉ๋ชจ๋ฆฌ ๋์'๋ผ๋ ํํ์ ๊ฐ๋ฐ์์ ์๋์ ๋ฌ๋ฆฌ ์ด๋ค ๊ฐ์ ์ฐธ์กฐ ์นด์ดํธ๊ฐ 0์ด ๋์ง ์์ GC(๊ฐ๋น์ง ์ปฌ๋ ํฐ)์ ์๊ฑฐ ๋์์ด ๋์ง ์๋ ๊ฒฝ์ฐ์๋ ๋ง๋ ํํ์ด์ง๋ง ๊ฐ๋ฐ์๊ฐ ์๋์ ์ผ๋ก ์ฐธ์กฐ ์นด์ดํธ๋ฅผ 0์ด ๋์ง ์๊ฒ ์ค๊ณํ ๊ฒฝ์ฐ๋ '๋์'๋ผ๊ณ ํ ์ ์์ ๊ฒ์ ๋๋ค. ์๋๋๋ก ์ค๊ฒํ '๋ฉ๋ชจ๋ฆฌ ์๋ชจ'์ ๋ํ ๊ด๋ฆฌ๋ฒ๋ง ์ ํ์ ํด์ ์ ์ฉํ๋ ๊ฒ์ผ๋ก๋ ์ถฉ๋ถํฉ๋๋ค.
๊ด๋ฆฌ ๋ฐฉ๋ฒ์ ๊ฐ๋จํฉ๋๋ค.
ํด๋ก์ ๋ ์ด๋ค ํ์์ ์ํด ์๋์ ์ผ๋ก ํจ์์ ์ง์ญ๋ณ์๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋ชจํ๋๋ก ํจ์ผ๋ก์จ ๋ฐ์ํฉ๋๋ค. ๊ทธ ํ์์ฑ์ด ์ฌ๋ผ์ง ์์ ์์ ๋๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋ชจํ์ง ์๊ฒ ํด์ฃผ๋ฉด ๋ฉ๋๋ค. ์ฐธ์กฐ ์นด์ดํธ๋ฅผ 0์ผ๋ก ๋ง๋ค๋ฉด ์ธ์ ๊ฐ GC๊ฐ ์๊ฑฐํด๊ฐ ๊ฒ์ด๊ณ , ์๋ชจ๋๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํ์๋ ๊ฒ์ ๋๋ค.
์ฐธ์กฐ ์นด์ดํธ๋ฅผ 0์ผ๋ก ๋ง๋๋ ๋ฐฉ๋ฒ์ ์๋ณ์์ ์ฐธ์กฐํ์ด ์๋ ๊ธฐ๋ณธํ ๋ฐ์ดํฐ(๋ณดํต null์ด๋ undefined)๋ฅผ ํ ๋นํ๋ฉด ๋ฉ๋๋ค.
๋ฐ์ ์์ ์ฝ๋๋ ์์์ ์ดํด๋ณธ return ์์ด๋ ํด๋ก์ ๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ์ ์์๋ค์ ๋ฉ๋ชจ๋ฆฌ ํด์ ์ฝ๋๋ฅผ ์ถ๊ฐํ ์ฝ๋์ ๋๋ค.
// return์ ์ํ ํด๋ก์ ์ ๋ฉ๋ชจ๋ฆฌ ํด์
var outer = (function() {
var a = 1;
var inner = function() {
return ++a;
};
return inner;
})();
console.log(outer());
console.log(outer());
outer = null; // outer ์๋ณ์์ inner ํจ์ ์ฐธ์กฐ๋ฅผ ๋์// setInterval์ ์ํ ํด๋ก์ ์ ๋ฉ๋ชจ๋ฆฌ ํด์
(function() {
var a = 0;
var intervalId = null;
var inner = function() {
if(++a >= 10) {
clearInterval(intervalId);
inner = null; // inner ์๋ณ์์ ํจ์ ์ฐธ์กฐ๋ฅผ ๋์
}
console.log(a);
};
intervalId = setInterval(inner, 1000);
})// eventListener์ ์ํ ํด๋ก์ ์ ๋ฉ๋ชจ๋ฆฌ ํด์
(function() {
var count = 0;
var button = document.createElement("button");
button.innerText = "Click";
var clickHandler = function() {
console.log(++count, "times clicked!");
if(count >= 10) {
button.removeEventListener("click", clickHandler);
clickHandler = null; // clickHandler ์๋ณ์์ ํจ์ ์ฐธ์กฐ๋ฅผ ๋์.
}
};
button.addEventListener("click", clickHandler);
document.body.appendChild(button);
}...?