๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Front-end/JS

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํด๋กœ์ € Closure

by ciocio 2021. 8. 27.

๐Ÿ“Œ  ์ผ๋‹จ Lexical Scope? Dynamic Scope?

 

โ—พ Lexical Scope

 

ํ•จ์ˆ˜๋‚˜ ๋ณ€์ˆ˜์˜ ์Šค์ฝ”ํ”„๋ฅผ ์„ ์–ธ๋œ ์œ„์น˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •ํ•จ ( Compile ์‹œ์  )

 

โ—พ Dynamic Scope

 

ํ•จ์ˆ˜๋‚˜ ๋ณ€์ˆ˜์˜ ์Šค์ฝ”ํ”„๋ฅผ ํ˜ธ์ถœ๋œ ์‹œ์ ์„ ๊ธฐ์ค€์œผ๋กœ ์ •ํ•จ ( Runtime ์‹œ์  )

 

// 01 Lexical Scope์™€ Dynamic Scope ๋น„๊ต

let x = 1;

function print() {
  console.log(x);  // Lexical Scope : 1   -> ์„ ์–ธ๋œ ์œ„์น˜ ๊ธฐ์ค€ / ๋ณ€์ˆ˜ x ์ „์—ญ ์Šค์ฝ”ํ”„
}

function foo() {
  let x = 100;
  print();         // Dynamic Scope : 100 -> ํ˜ธ์ถœ๋œ ์‹œ์  ๊ธฐ์ค€ / ๋ณ€์ˆ˜ x ์ง€์—ญ ์Šค์ฝ”ํ”„
}

foo();

 

// 02 ๋‚ด๋ถ€ ํ•จ์ˆ˜์˜ Scope Chain

let name = "kim";

function init() {
  let name = "Lee";           // name์€ init์— ์˜ํ•ด ์ƒ์„ฑ๋œ ์ง€์—ญ ๋ณ€์ˆ˜์ด๋‹ค.
  function displayName() {    // displayName()์€ ๋‚ด๋ถ€ ํ•จ์ˆ˜์ด๋ฉฐ, ํด๋กœ์ €๋‹ค.
    alert(name);              // ๋ถ€๋ชจ ํ•จ์ˆ˜์—์„œ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  }
  displayName();
}

init();  // "Lee"

 

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” Lexical Scope๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

๋”ฐ๋ผ์„œ, ํ•จ์ˆ˜๋‚˜ ๋ณ€์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ์œ„์น˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•œ ๊ฒน ํ•œ ๊ฒน ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—๊ฒจ ๋‚˜๊ฐ€๋ฉด์„œ ๊ทธ ๋‚ด๋ถ€์— ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋ฅผ ์ฐพ๋Š”๋‹ค.

์œ„ ์˜ˆ์‹œ๋กœ ๋ณด๋ฉด, ์ž์‹ ์˜ scope -> ์ž์‹ ์„ ํฌํ•จํ•˜๋Š” ์™ธ๋ถ€ ํ•จ์ˆ˜ scope(์—ฌ๊ธฐ์„  init) -> ์ „์—ญ scope ์ˆœ์œผ๋กœ ๋ณ€์ˆ˜๋ฅผ ์ฐพ๊ฒŒ ๋œ๋‹ค.

์ด๋ ‡๊ฒŒ ์ผ์น˜ํ•˜๋Š” ๋ณ€์ˆ˜๋ฅผ ์ฐพ์„ ๋•Œ๊นŒ์ง€ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—๊ฒจ๋‚˜๊ฐˆ ์ˆ˜ ์žˆ๋Š” ์ด์œ ๋Š” Scope Chain ๋•Œ๋ฌธ์ด๋‹ค.

 

 

๐Ÿ“Œ  ํด๋กœ์ €?

 

์ž์‹ ์ด ์ƒ์„ฑ๋œ ์‹œ์ ์˜ ํ™˜๊ฒฝ์„ ๊ธฐ์–ตํ•˜๋Š” ํ•จ์ˆ˜

-->  ์™ธ๋ถ€ ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด ์ข…๋ฃŒ๋˜์—ˆ์Œ์—๋„ ์™ธ๋ถ€ ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜๋‚˜ ์ธ์ž์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜ !!

 

// 03 ํด๋กœ์ € ์˜ˆ์‹œ

let x = 1;

function outer(z) {
  let y = 2;
  return function inner() {
    console.log(x + y + z);
  }
}

let sum = outer(3);
sum();

 

๋ณ€์ˆ˜ sum์€ outer(3)์œผ๋กœ ์ธํ•ด ๋‚ด๋ถ€ ํ•จ์ˆ˜( inner( ) )๋ฅผ ๋ฆฌํ„ด๋ฐ›๋Š”๋‹ค.

๊ทธ๋ฆฌ๊ณ ๋Š” sum( )์— ์˜ํ•ด ํ•ด๋‹น ๋‚ด๋ถ€ ํ•จ์ˆ˜( inner( ) )๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.  -->  ์ตœ์ข…์ ์œผ๋กœ ์ถœ๋ ฅ๋˜๋Š” ๊ฐ’์€ 6 !!!

 

์™œ? Why????

 

๋ณ€์ˆ˜ sum์ด ํ• ๋‹น๋ฐ›์€ ๊ฒƒ์€ ๋ฆฌํ„ด๋œ ๋‚ด๋ถ€ ํ•จ์ˆ˜ inner( ) ๋‹ค.

์ƒ์‹์ ์œผ๋กœ ๋ณด๋ฉด inner ํ•จ์ˆ˜ ๋‚ด๋ถ€์—๋Š” x, y๊ฐ€ ์„ ์–ธ๋˜์–ด ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— NaN๊ฐ€ ๋‚˜์˜ฌ๊ฒƒ๋งŒ๊ฐ™๋‹ค.

๊ทธ๋Ÿฐ๋ฐ sum( )์€  6์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. inner ํ•จ์ˆ˜๊ฐ€ (์ด๋ฏธ ์‹คํ–‰์ด ์ข…๋ฃŒ๋œ) outer ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜ y์™€ z์— ์ ‘๊ทผํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ๋œปํ•œ๋‹ค !!

์ฆ‰์ฆ‰์ฆ‰์ฆ‰ inner ํ•จ์ˆ˜๋Š” Scope Chain์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— outer ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜ y, z๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค !! 

 

์œ„ ์˜ˆ์‹œ์˜ inner์ฒ˜๋Ÿผ ์™ธ๋ถ€ ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ์Œ์—๋„ Scope Chain์„ ์ด์šฉํ•ด ์™ธ๋ถ€ ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜, ์ธ์ž์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๋ฅผ

Closure ํด๋กœ์ € ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

 

 

๐Ÿ“Œ  ํด๋กœ์ € ํ™•์ธ

 

๊ฐ’์ด ์ €์žฅ๋˜๊ณ  ์žˆ๋‚˜ ? ๋„๋Œ€์ฒด ์–ด๋””์— ? ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•

console.dir( ) ํ™œ์šฉํ•˜๊ธฐ

 

let x = 1;

function outer(y) {
  let z = 3;
  return function middle(m) {
    let p = 5;
    return function inner() {
      console.log(x + y + z + m + p);
    }
  }
}

let middle = outer(2);
let inner = middle(4);
console.dir(inner);

// ๊ฒฐ๊ณผ

 

 

// middle ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜์™€ ์ธ์ž๋ฅผ inner ํ•จ์ˆ˜๊ฐ€ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์„ ๋•Œ

let x = 1;

function outer(y) {
  let z = 3;
  return function middle(m) {
    let p = 5;
    return function inner() {
      console.log(x + y + z);
    }
  }
}

let middle = outer(2);
let inner = middle(4);
console.dir(inner);

// ๊ฒฐ๊ณผ

 

 

 

๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด inner ํ•จ์ˆ˜์˜ Scope Chain์—์„œ middle์— ๋Œ€ํ•œ ์ •๋ณด๋Š” ์—†๋‹ค.

์ฆ‰ Scope Chain์€ ๋‚ด๋ถ€ ํ•จ์ˆ˜๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ์ •๋ณด์— ๋Œ€ํ•ด์„œ๋งŒ ์œ ์ง€ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค ~!~!

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€