์๋ฐ์คํฌ๋ฆฝํธ ์คํํ๊ฒฝ์ผ๋ก ์คํํ ์ฝ๋์ ์ ๊ณตํ ํ๊ฒฝ ์ ๋ณด๋ค์ ๋ชจ์๋์ ๊ฐ์ฒด๋ฅผ ์๋ฏธ
1 ) ๋์ผํ ํ๊ฒฝ์ ์๋ ์ฝ๋๋ค์ ์คํํ ๋ ํ์ํ ํ๊ฒฝ์ ๋ณด๋ค์ ๋ชจ์ ์ปจํ
์คํธ๋ฅผ ๊ตฌ์ฑํฉ๋๋ค.
๐ ๋์ผํ ํ๊ฒฝ
: ์คํ์ ์ปจํ
์คํธ๋ฅผ ๊ตฌ์ฑํ ์ ์๋ ์ ์ญ๊ณต๊ฐ, eavl() ํจ์, ํจ์ ํธ์ถ, { } ์ฝ๋ ๋ธ๋ญ ์ฌ์ฉ ์ (๋ธ๋ก ์ค์ฝํ) ์
๋๋ค.
2 ) ์ด๋ฅผ callStack
์ ์์ ์ฌ๋ ธ๋ค๊ฐ ๊ฐ์ฅ ์์ ์์ฌ์๋ ์ปจํ
์คํธ์ ๊ด๋ จ์๋ ์ฝ๋๋ค์ ์คํํ๋ ๋ฐฉ์์ผ๋ก ์ ์ฒด ์ฝ๋์ ํ๊ฒฝ๊ณผ ์์๋ฅผ ๋ณด์ฅํฉ๋๋ค. (ํ์
์ ์ถ ๋ฐฉ์)
๐ callStack
: ํจ์ ํธ์ถ์ ์์๋ฅผ ๊ธฐ๋กํ๋ ์๋ฃ ๊ตฌ์กฐ
var a = 1;
function outer() {
function inner() {
console.log(a); // undefined => TDZ
var a = 3;
}
inner(); // ํจ์ ์คํ => ํ์ฌ ์คํ์ ๋ฉ์ถ๊ณ , ํจ์ ์ ์ธ๋ฌธ ์์ผ๋ก ๋ค์ด๊ฐ
console.log(a); // inner()ํจ์๊ฐ ์ข
๋ฃ๋ ํ ํธ์ถ 1
}
outer(); // outer ํจ์ ํธ์ถ => ํ์ฌ ์คํ์ ๋ฉ์ถ๊ณ outer ํจ์ ์ ์ธ๋ฌธ ์์ผ๋ก ๋ค์ด๊ฐ
console.log(a); // outer ํจ์ ์ข
๋ฃ ํ ํธ์ถ 1
// ์ ์ญ ์ปจํ
์คํธ => outer => innter ์์ผ๋ก ์ฝ ์คํ
์์
// ์ดํ ํจ์ ์ข
๋ฃ ๋ง๋ค inner => outer => ์ ์ญ ์ปจํ
์คํธ ์์ผ๋ก ์ฝ ์คํ
์ด ์ ๊ฑฐ
// => ํ์
์ ์ถ
1 ) VariableEnvironment(๋ณ์ ํ๊ฒฝ)
EnviromentRecord(ํ๊ฒฝ๋ ์ฝ๋, ํ์ฌ ์ปจํ ์คํธ ๋ด์ ์๋ณ์๋ค์ ๋ํ ์ ๋ณด), OuterEnviromentReference(์ธ๋ถํ๊ฒฝ์ฐธ์กฐ, ์์ Lexical Environment๋ฅผ ์ฐธ์กฐ)๊ฐ ๋ด๊ฒจ์์ต๋๋ค.
2 ) LexicalEnvironment(์ ์ ํ๊ฒฝ)
EnviromentRecord(ํ๊ฒฝ๋ ์ฝ๋, ํ์ฌ ์ปจํ ์คํธ ๋ด์ ์๋ณ์๋ค์ ๋ํ ์ ๋ณด), ์ธ๋ถํ๊ฒฝ์ฐธ์กฐ(OuterEnviromentReference, ์์ Lexical Environment๋ฅผ ์ฐธ์กฐ)๊ฐ ๋ด๊ฒจ์์ต๋๋ค.
์ด๊ธฐ์๋ VariableEnvironment์ LexicalEnvironment๊ฐ ๊ฐ์ง๋ง LexicalEnvironment์ ์ฝ๋ ์คํ ์ดํ ๋ณ๊ฒฝ ์ฌํญ์ด ์ค์๊ฐ์ผ๋ก ๋ฐ์๋ฉ๋๋ค.
๐ VariableEnvironment์ LexicalEnvironment ์ฐจ์ด์
3 ) ThisBinding
this๊ฐ์ด ๊ฒฐ์ ๋๋ ๊ณณ ์ ๋๋ค.
ํจ์ ์คํ ์ปจํ ์คํธ์์๋ this ๊ฐ์ ์ด๋ป๊ฒ ํจ์๊ฐ ํธ์ถ ๋ฐฉ๋ฒ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค. ๋ง์ฝ ํจ์๊ฐ ๊ฐ์ฒด์ ์ฐธ์กฐ๋ก ํธ์ถ๋์๋ค๋ฉด this๋ ํด๋น ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด this๋ ๊ธ๋ก๋ฒ ๊ฐ์ฒด(window)๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋๊ณ , strict mode์์๋ undefined ๋ฅผ ๊ฐ๋ฅดํค๊ฒ ๋ฉ๋๋ค.
ํ์ฌ ์ปจํ ์คํธ๋ด์ ์ฝ๋์ ์๋ณ์ ์ ๋ณด๋ค์ด ์ ์ฅ๋ฉ๋๋ค.
Scope : ์๋ณ์์ ๋ํ ์ ํจ๋ฒ์๋ฅผ ์๋ฏธํฉ๋๋ค.
Scope Chain์ด๋ ์๋ณ์์ ์ ํจ๋ฒ์๋ฅผ ์์์๋ถํฐ ๋ฐ๊นฅ์๋ก ์ฐจ๋ ๋ก ๊ฒ์ํด ๋๊ฐ๋ ๊ฒ์ ๋งํฉ๋๋ค.
OuterEnvironmentReference(์ธ๋ถ ํ๊ฒฝ ์ฐธ์กฐ)๋ ํ์ฌ ํธ์ถ๋ ํจ์๊ฐ ์ ์ธ๋ ๋น์์ LexicalEnvironment(์ ์ ํ๊ฒฝ)๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
์ธ๋ถ ํ๊ฒฝ ์ฐธ์กฐ๋ ์ค์ง ์์ ์ด ์ ์ธ๋ ์์ ์ ์ ์ ํ๊ฒฝ๋ง ์ฐธ์กฐํ๊ณ ์์ผ๋ฏ๋ก ๊ฐ์ฅ ๊ฐ๊น์ด ์์๋ถํฐ ์ฐจ๋ก๋๋ก ์ ๊ทผํ๊ฒ ๋ฉ๋๋ค. => (ํ์
์ ์ถ ๋ฐฉ์)
์ฆ, ์ค์ฝํ ์ฒด์ธ ์์์ ๊ฐ์ฅ ๋จผ์ ๋ฐ๊ฒฐ๋ ์๋ณ์์๋ง ์ ๊ทผ์ด ๊ฐ๋ฅํฉ๋๋ค.
var a = 1;
let outer2 = function () {
let inner2 = function () {
console.log(a); // undefined : ์๋ var์ ์ํด inner2 ํจ์ ์ค์ฝํ ์์์ ํธ์ด์คํ
๋๋์ด
// ์ ์ธ์ ๋์์ง๋ง ์ด๊ธฐํ๋์ง ์์์ผ๋ฏ๋ก undefined๊ฐ ๋ฐํ๋จ
var a = 3; // ๋ณ์์ ์๋ํ ์ ์ญ ๋ณ์(a)์ ์ ๊ทผํ์ง ๋ชปํจ
};
inner2();
console.log(a); // 1
};
outer2();
console.log(a); // 1
1 ) ์ ์ญ ์ปจํ ์คํธ ์์ฑ
์ ์ญ ๋ณ์ a๊ฐ ์ ์ธ๋๊ณ ์ด๊ธฐํ๋ฉ๋๋ค. a์ ์ด๊ธฐ๊ฐ์ 1์ ๋๋ค.
outer2 ํจ์๊ฐ ์ ์ญ ์ค์ฝํ์ ์ ์ธ๋ฉ๋๋ค.
2 ) outer2 ํจ์ ํธ์ถ
outer2 ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ์์ฑ๋ฉ๋๋ค.
outer2 ํจ์ ๋ด๋ถ์์ inner2 ํจ์ ํธ์ถ๋ฉ๋๋ค.
3 ) inner2 ํจ์ ํธ์ถ
inner2 ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ์์ฑ๋ฉ๋๋ค.
inner2 ํจ์ ๋ด๋ถ์์ console.log(a) ๋ฌธ์ด ์คํ๋ฉ๋๋ค.
4 ) console.log(a) ์คํ
inner2 ํจ์ ๋ด๋ถ์์ ๋ณ์ a๋ฅผ ์ฐพ์ต๋๋ค.
๋ณ์ a๋ ํ์ฌ ์ค์ฝํ ๋ด์์ ํธ์ด์คํ ๋์ด ์ ์ธ๋์์ง๋ง, ๊ฐ์ด ํ ๋น๋๊ธฐ ์ ์ ํธ์ถ๋์ด undefined๋ฅผ ๋ฐํํฉ๋๋ค.
undefined๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค.
5 ) var a = 3 ์ฌํ ๋น
inner2 ํจ์ ๋ด๋ถ์์ ํธ์ด์คํ ๋์ด์๋ ๋ณ์ a๊ฐ์ 3์ผ๋ก ์ฌํ ๋นํฉ๋๋ค.
6 ) inner2 ํจ์๊ฐ ์ข ๋ฃ
inner2 ํจ์๊ฐ ์ข ๋ฃ๋์ด ์คํ ์ปจํ ์คํธ์์ ์ ๊ฑฐ๋ฉ๋๋ค.
7) console.log(a) ์คํ
outer2 ํจ์ ๋ด๋ถ์์ ๋ณ์ a๋ฅผ ์ฐพ์ต๋๋ค.
๋ณ์ a๊ฐ outer2 ํจ์ ๋ด๋ถ์ ์กด์ฌํ์ง ์๊ธฐ ๋๋ฌธ์ ScopeChain๋ฅผ ํตํด a๋ฅผ ์ฐพ์ต๋๋ค.
OuterEnvironmentReference๋ฅผ ํตํด ์์ ์ค์ฝํ์ LexicalEnvironment์ ์ ๊ทผํ์ฌ a๋ฅผ ์ฐพ์ต๋๋ค.
์์ ์ค์ฝํ๋ ์ ์ญ ์ปจํ ์คํธ์ด๋ฉฐ, a ๊ฐ์ 1๋ก ์ ์ธ๋์ด ์์ต๋๋ค.
๋ฐ๋ผ์ a์ 1์ด๋ผ๋ ๊ฐ์ ์ฐพ๊ฒ๋ฉ๋๋ค.
1์ด ์ฝ์์ ์ถ๋ ฅ๋ฉ๋๋ค.
8 ) console.log(a) ์คํ
์ ์ญ ์ค์ฝํ์์ ๋ณ์ a๊ฐ์ ์ฐพ์ต๋๋ค.
๋ณ์ a๋ ์ ์ญ ์ค์ฝํ์์ ์ ์ธ๋์์ผ๋ฉฐ, ๊ฐ์ 1์ ๋๋ค.
1์ด ์ฝ์์ ์ถ๋ ฅ ๋ฉ๋๋ค.
9 ) outer2 ํจ์๊ฐ ์ข ๋ฃ
outer2 ํจ์๊ฐ ์ข ๋ฃ๋์ด ์คํ ์ปจํ ์คํธ์์ ์ ๊ฑฐ๋ฉ๋๋ค.
10 ) console.log(a) ์คํ
์ ์ญ ์ปจํ ์คํธ์์ ๋ณ์ a๋ฅผ ์ฐพ์ต๋๋ค.
๋ณ์ a๋ ์ ์ญ ์ค์ฝํ์์ ์ ์ธ๋์์ผ๋ฉฐ, ๊ฐ์ 1์ ๋๋ค.