๋ณธ๋ฌธ์œผ๋กœ ๋ฐ”๋กœ๊ฐ€๊ธฐ

์Šค์ฝ”ํ”„๋ž€, ๋ณ€์ˆ˜ ์ด๋ฆ„, ํ•จ์ˆ˜ ์ด๋ฆ„, ํด๋ž˜์Šค ์ด๋ฆ„๊ณผ ๊ฐ™์€ ์‹๋ณ„์ž๊ฐ€ ๋ณธ์ธ์ด ์„ ์–ธ๋œ ์œ„์น˜์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์ฝ”๋“œ์—์„œ ์ž์‹ ์ด ์ฐธ์กฐ๋  ์ˆ˜ ์žˆ์„์ง€ ์—†์„์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์‹๋ณ„์ž์— ๋Œ€ํ•œ ์œ ํšจ๋ฒ”์œ„๋ผ๊ณ ๋„ ๊ฐ„๋‹จํžˆ ๋งํ•œ๋‹ค.

 

ํฌ๋กฌ ๋””๋ฒ„๊ฑฐ๋กœ ๋ณด๋Š” ์Šค์ฝ”ํ”„

var globalVariable1 = 1;
const globalVariable2 = 2;

const outerConst = function () {
  console.log();
};

var outerVar = function () {
  console.log();
};

function outerFunc2() {
  console.log();
}

function outerFunc1() {
  let outerVariable = 999;
  function innerFunc() {
    const innerVariable = 1;
    outerVariable += 1;
  }
  inner();
}

์Šค์ฝ”ํ”„๋Š” ์ปจํ…์ŠคํŠธ์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์‹๋ณ„์ž๋“ค์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ด๋‹ค. ์œ„์˜ ์‚ฌ์ง„์€ innerFunc() ์ปจํ…์ŠคํŠธ์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์‹๋ณ„์ž๋“ค์„ ์Šค์ฝ”ํ”„๋ณ„๋กœ ๋ชจ์•„๋†“์€ ๊ฒƒ์ด๋‹ค. (anonymous) ์ปจํ…์ŠคํŠธ๋Š” ์ „์—ญ ์ปจํ…์ŠคํŠธ๋ฅผ ๋œปํ•œ๋‹ค.

 

 

๋‚ด๊ฐ€ ๊ถ๊ธˆํ–ˆ๋˜ ๊ฒƒ

Q. ์ปจํ…์ŠคํŠธ๊ฐ€ ์ƒ๊ธธ๋•Œ๋งˆ๋‹ค Global, Script, Local ์‹๋ณ„์ž๊ฐ€ ์ƒ๊ธฐ๋Š”๋ฐ, Global, Script๋Š” ์ปจํ…์ŠคํŠธ๋งˆ๋‹ค ๋™์ผํ•œ ๊ฒƒ์„ ๋ฐ”๋ผ๋ณด๊ณ  Local ์‹๋ณ„์ž๋Š” ์ปจํ…์ŠคํŠธ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฑด๊ฐ€?

 

A. Scope์— ๋‚˜์™€์žˆ๋Š” Global, Script, Local์€ ์‹๋ณ„์ž๋ผ๊ธฐ ๋ณด๋‹จ, ์ปจํ…์ŠคํŠธ๋งˆ๋‹ค ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์‹๋ณ„์ž๋“ค์„ ํฌ๋กฌ ๋””๋ฒ„๊ฑฐ๊ฐ€ ์Šค์ฝ”ํ”„๋ณ„๋กœ ๋ชจ์•„๋†“์€ ๋ถ„๋ฅ˜๋ช…์œผ๋กœ ๋ณด๋Š” ๊ฒƒ์ด ์ ์ ˆํ•˜๋‹ค. ๋”ฐ๋ผ์„œ ์–ด๋–ค ์ปจํ…์ŠคํŠธ๊ฑด Global, Script๋กœ ๋ถ„๋ฅ˜ํ•ด๋†“์€ ์‹๋ณ„์ž๋Š” ์ „์—ญ ์ปจํ…์ŠคํŠธ์˜ VO์•ˆ์— ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋™์ผํ•  ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ Global์€ window๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ&๋ฉ”์†Œ๋“œ(var)๊ฐ€ ๋“ค์–ด๊ฐ€์žˆ๊ณ , Script๋Š” ์Šคํฌ๋ฆฝํŠธ ์•ˆ์—์„œ ์ƒ์„ฑํ•œ ์‹๋ณ„์ž(const, let)๊ฐ€, Local์€ ํ•ด๋‹น ์ปจํ…์ŠคํŠธ์—์„œ ์ƒ์„ฑ๋œ ์‹๋ณ„์ž๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค.

 

ํ•จ์ˆ˜ ์Šค์ฝ”ํ”„

  • ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด ์ƒˆ๋กœ์šด ์Šค์ฝ”ํ”„๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
  • ํ•จ์ˆ˜์—์„œ ์„ ์–ธํ•œ ๋ณ€์ˆ˜๋“ค์€ ํ•ด๋‹น ํ•จ์ˆ˜ ๋‚ด์—์„œ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” var ํ‚ค์›Œ๋“œ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ์˜ค๋กœ์ง€ ํ•จ์ˆ˜ ์ฝ”๋“œ๋ธ”๋ก๋งŒ์„ ์ง€์—ญ ์Šค์ฝ”ํ”„๋กœ ์ธ์ •ํ•œ๋‹ค.
if(5 > 4) {
	var secret = '12345';
}
secret // '12345'
function a() {
	var secret = '12345';
}
secret; //ReferenceError

aํ•จ์ˆ˜์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ƒ์„ฑ๋˜๊ณ , ์ด ์‹คํ–‰ ์ปจํ…์ŠคํŠธ ๋‚ด๋ถ€์— ์กด์žฌํ•˜๋Š” ๋ณ€์ˆ˜ํ™˜๊ฒฝ(variable environment)์— secret๋ณ€์ˆ˜๊ฐ€ ์ €์žฅ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ํ•จ์ˆ˜ ์™ธ๋ถ€์—์„œ secret์— ์ ‘๊ทผํ•˜๋ ค๊ณ  ํ•  ๊ฒฝ์šฐ ์Šค์ฝ”ํ”„๊ฐ€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ๋ณ€์ˆ˜์— ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ํ•จ์ˆ˜์™ธ๋ถ€๋Š” global scope์ด๊ณ , ํ•จ์ˆ˜ ๋‚ด๋ถ€๋Š” aํ•จ์ˆ˜์˜ scope์ธ๋ฐ ๋ถ€๋ชจ์Šค์ฝ”ํ”„๋Š” ์ž์‹์Šค์ฝ”ํ”„์—์„œ ๊ฐ„์„ญํ•  ์ˆ˜ ์—†๊ธฐ ๋–„๋ฌธ์— ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

๋ธ”๋ก ์Šค์ฝ”ํ”„

  • ๋ธ”๋ก์ด ์ƒ์„ฑ๋ ๋•Œ ์ƒˆ๋กœ์šด ์Šค์ฝ”ํ”„๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
  • ํ•จ์ˆ˜๋ฟ๋งŒ์•„๋‹ˆ๋ผ, if๋ฌธ, for๋ฌธ...์—์„œ๋„ ์Šค์ฝ”ํ”„๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
  • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์›๋ž˜ ํ•จ์ˆ˜์Šค์ฝ”ํ”„๋ฅผ ๋”ฐ๋ฅด์ง€๋งŒ, let๊ณผ const์˜ ๋“ฑ์žฅ์ดํ›„๋กœ ๋ธ”๋ก ์Šค์ฝ”ํ”„ ํ˜•์„ฑ๋„ ๊ฐ€๋Šฅํ•ด์กŒ๋‹ค.
function  loop() { 
	for (var j = 0; j < 3; j++) { 
		console.log(j); 
	} 
	console.log('final', j); 
} 

loop();

// 0
// 1
// 2
// final 3
function  loop() { 
	for (let j = 0; j < 3; j++) { 
		console.log(j); 
	} 
	console.log('final', j); 
} 

loop();

// 0
// 1
// 2
// Uncaught ReferenceError: j is not defined

let์œผ๋กœ ์„ ์–ธํ•œ ๋ณ€์ˆ˜๋Š” for๋ฌธ ๋‚ด(๋ธ”๋ก ์Šค์ฝ”ํ”„)์—์„œ๋งŒ ์ข…์†๋˜๋ฉฐ, for๋ฌธ ์™ธ๋ถ€์—์„œ๋Š” ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค.

 

Lexical Scope

๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„๋Š” ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ ์œ„์น˜์™€ ์ƒ๊ด€ ์—†์ด, ํ•จ์ˆ˜๊ฐ€ ์–ด๋””์„œ ์„ ์–ธ๋˜์—ˆ๋Š”์ง€์— ๋”ฐ๋ผ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค. ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ, ์Šค์ฝ”ํ”„ ์ฒด์ธ์— ์ƒ์œ„ ์Šค์ฝ”ํ”„๋ฅผ ์ €์žฅํ•œ ํ›„์— ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„๋Š” ์ฝ”๋“œ๊ฐ€ ์“ฐ์—ฌ์ง„ ์ˆœ๊ฐ„ ์Šค์ฝ”ํ”„๋Š” ์ด๋ฏธ ์ •ํ•ด์ง€๊ธฐ ๋•Œ๋ฌธ์— ์ •์  ์Šค์ฝ”ํ”„๋ผ๊ณ ๋„ ๋ถˆ๋ฆฐ๋‹ค.

์˜ˆ์ œ ์ฝ”๋“œ1) 

var x = 1; // global

function first() {
  var x = 10;
  second();
}

function second() {
  console.log(x);
}

first(); // ?
second(); // ?

๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„์—์†Œ๋Š” ๋™์  ์Šค์ฝ”ํ”„์˜ ํŠน์ง•์ธ "ํ•จ์ˆ˜๋ฅผ ์–ด๋””์—์„œ ํ˜ธ์ถœํ•˜์˜€๋Š”์ง€"๋Š” ์Šค์ฝ”ํ”„ ๊ฒฐ์ •๊ณผ ์ „ํ˜€ ๋ฌด๊ด€ํ•˜๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์—, second() ํ•จ์ˆ˜๊ฐ€ first() ํ•จ์ˆ˜ ์•ˆ์—์„œ ํ˜ธ์ถœ๋œ ๊ฒƒ๊ณผ ์ƒ๊ด€์—†์ด, second() ํ•จ์ˆ˜๋Š” ์ „์—ญ ์ปจํ…์ŠคํŠธ์—์„œ ์„ ์–ธ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ, ์ „์—ญ ์ปจํ…์ŠคํŠธ์˜ ๋ณ€์ˆ˜ x์˜ ๊ฐ’ 1์ด ๋‘ ๋ฒˆ ์ถœ๋ ฅ๋œ๋‹ค.

์˜ˆ์ œ ์ฝ”๋“œ2) 

const x = 1

function outer() {
    const x = 10
    const inner = function() {
        console.log(x)
    }    
    return inner;
}

const junha = outer()

junha() // ?

innerํ•จ์ˆ˜๊ฐ€ ์ •์˜๋˜๋Š” ์‹œ์ ์— ์Šค์ฝ”ํ”„ ์ฒด์ธ์˜ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋Š” outer ์ปจํ…์ŠคํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, x๋Š” outer์˜ x๋ฅผ ๋จผ์ € ์ฐธ์กฐํ•ด 10์„ ์ถœ๋ ฅํ•œ๋‹ค. outer๊ฐ€ ์ฝœ์Šคํƒ์—์„œ ์‚ฌ๋ผ์กŒ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , inner๊ฐ€ outer์˜ x๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— inner๋Š” ํด๋กœ์ €์ด๋‹ค.

์˜ˆ์ œ ์ฝ”๋“œ3)

var c = 999

let arr = []

for(let i= 0 ; i<5 ; i++) {
	let c = i * 2
    arr.push(function inner() {console.log(c)})
}

arr.forEach(func => func())

// ?

ES6์—์„œ๋Š” ๋ธ”๋Ÿญ์ด ์ƒ์„ฑ๋˜๋ฉด์„œ๋„ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. innerํ•จ์ˆ˜๊ฐ€ ์ •์˜๋˜๋Š” ์‹œ์ ์€(= inner ์‹คํ–‰์ปจํ…์ŠคํŠธ๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ์‹œ์ ์€) ์ด ๋ธ”๋Ÿญ์—์„œ ์„ ์–ธ๋˜๊ธฐ ๋•Œ๋ฌธ์—, inner์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ์˜  ์Šค์ฝ”ํ”„์ฒด์ธ์€ ๋ธ”๋ก์„ ์ฐธ์กฐํ•˜๊ฒŒ ๋œ๋‹ค. ๋”ฐ๋ผ์„œ innerํ•จ์ˆ˜๊ฐ€ ์ฐธ์กฐํ•˜๋Š” c๋Š” ๋ธ”๋ก์•ˆ์˜ c๊ฐ€ ๊ฐ€์žฅ ๋จผ์ € ์Šค์ฝ”ํ•‘์ด ๋œ๋‹ค.

 

๋งŒ์•ฝ, ๋ธ”๋ก์•ˆ์— ์ง€์—ญ๋ณ€์ˆ˜ c๊ฐ€ ์—†์—ˆ๋‹ค๋ฉด?? innerํ•จ์ˆ˜์˜ ์Šค์ฝ”ํ•‘ ๋‹จ๊ณ„๋Š” VO(inner) -> SC(๋ธ”๋ก) -> SC(์ „์—ญ)์„ ํ†ตํ•ด ์ „์—ญ๋ณ€์ˆ˜ c๋ฅผ ์ฐธ์กฐํ•˜์—ฌ, 999๋ฅผ 5๋ฒˆ ์ถœ๋ ฅํ•œ๋‹ค.

๋ฐ˜์‘ํ˜•