Skip to content

Latest commit

ย 

History

History
117 lines (83 loc) ยท 5.26 KB

closure.md

File metadata and controls

117 lines (83 loc) ยท 5.26 KB

๐Ÿ’ป ํด๋กœ์ €(Closure)


๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป ํด๋กœ์ €(Closure)

  • ํด๋กœ์ €(closure) ๋Š” ํ•จ์ˆ˜์™€ ๊ทธ ํ•จ์ˆ˜๊ฐ€ ์„ ์–ธ๋์„ ๋•Œ์˜ ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ(Lexical environment)๊ณผ์˜ ์กฐํ•ฉ์ด๋ผ๊ณ  ๋ถ€๋ฅด๋ฉฐ, ๋‚ด๋ถ€ ํ•จ์ˆ˜๊ฐ€ ์™ธ๋ถ€ํ•จ์ˆ˜ ๋ณ€์ˆ˜์— ์•ก์„ธ์Šค(์ ‘๊ทผ) ํ•  ์ˆ˜ ์žˆ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๊ธฐ๋Šฅ์„ ๋งํ•œ๋‹ค.
  • ํด๋กœ์ €(closure)๋Š” ๋ฐ˜ํ™˜๋œ ๋‚ด๋ถ€ ํ•จ์ˆ˜๊ฐ€ ์ž์‹ ์ด ์„ ์–ธ๋˜์—ˆ์„ ๋•Œ์˜ ๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„ ํ™˜๊ฒฝ์„ ๊ธฐ์–ตํ•˜์—ฌ, ์ž์‹ ์ด ์„ ์–ธ๋์„ ๋•Œ์˜ ํ™˜๊ฒฝ(์Šค์ฝ”ํ”„) ๋ฐ–์—์„œ ํ˜ธ์ถœ๋˜์–ด๋„ ๊ทธ ํ™˜๊ฒฝ(์Šค์ฝ”ํ”„)์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜
    • ์™œ? ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์—ฌ์ „ํžˆ ๊ธฐ์–ตํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ

๐Ÿƒ ๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„(Lexical scope) ์˜ˆ์‹œ

  • ๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„๋Š” ํ•จ์ˆ˜๋ฅผ ์–ด๋””์„œ ์„ ์–ธํ•˜์˜€๋Š”์ง€์— ๋”ฐ๋ผ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.
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)์—์„œ ์„ ์–ธํ•œ ๋ณ€์ˆ˜์—๋„ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿƒ ํด๋กœ์ €(Closure) ์˜ˆ์‹œ1

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2023-04-03 แ„‹แ…ฉแ„’แ…ฎ 3 47 42

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๋ณ€์ˆ˜์— ๋” ์ด์ƒ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๊ฒŒ ๋  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค.
  • ํ•˜์ง€๋งŒ, ์œ„์˜ ์˜ˆ์‹œ์™€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๊ฒฝ์šฐ๋Š” ๋‹ค๋ฅด๋‹ค. ๊ทธ ์ด์œ ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•˜๊ณ , ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ํด๋กœ์ €๋ฅผ ํ˜•์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ํด๋กœ์ €๋Š” ํ•จ์ˆ˜์™€ ํ•จ์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ์˜ ์กฐํ•ฉ์ด๋‹ค. ์ด ํ™˜๊ฒฝ์€ ํด๋กœ์ €๊ฐ€ ์ƒ์„ฑ๋œ ์‹œ์ ์˜ ์œ ํšจ ๋ฒ”์œ„ ๋‚ด์— ์žˆ๋Š” ๋ชจ๋“  ์ง€์—ญ ๋ณ€์ˆ˜๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

๐Ÿƒ ํด๋กœ์ €(Closure) ์˜ˆ์‹œ2

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๋ฒˆ ์ถœ๋ ฅ๋œ๋‹ค.

๐Ÿƒ ํด๋กœ์ €(Closure) ์˜ˆ์‹œ2์˜ ํ•ด๊ฒฐ๋ฐฉ์•ˆ

  • ๋ธ”๋ก ๋ ˆ๋ฒจ ์Šค์ฝ”ํ”„๋กœ ํ•ด๊ฒฐํ•˜๊ธฐ
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