๐Ÿ“‹ ๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Deep Dive | 24์žฅ ํด๋กœ์ €

waterglassesยท2022๋…„ 5์›” 21์ผ
0
post-thumbnail

๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Deep Dive ๋„์„œ์˜ 24์žฅ์„ ์ •๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.

ํด๋กœ์ €
MDN์—์„œ

A closure is the combination of a function and the lexical environment within which that function was declared.
ํด๋กœ์ €๋Š” ํ•จ์ˆ˜์™€ ๊ทธ ํ•จ์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ๊ณผ์˜ ์กฐํ•ฉ์ด๋‹ค.

24.1 ๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„

// 24-03
const x = 1; 
function foo() {
  const x = 10;
  
  // ์ƒ์œ„ ์Šค์ฝ”ํ”„๋Š” ํ•จ์ˆ˜ ์ •์˜ ํ™˜๊ฒฝ(์œ„์น˜)์— ๋”ฐ๋ผ ๊ฒฐ์ •๋œ๋‹ค.
  // ํ•จ์ˆ˜ ํ˜ธ์ถœ ์œ„์น˜์™€ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋Š” ์•„๋ฌด๋Ÿฐ ๊ด€๊ณ„๊ฐ€ ์—†๋‹ค. 
  bar();
}

// ํ•จ์ˆ˜ bar๋Š” ์ž์‹ ์˜ ์ƒ์œ„ ์Šค์ฝ”ํ”„, ์ฆ‰ ์ „์—ญ ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ์„ [[Environment]]์— ์ €์žฅํ•˜์—ฌ ๊ธฐ์–ตํ•œ๋‹ค.
function bar() {
  console.log(x); 
}

foo(); // 1
bar(); // 1

foo ํ•จ์ˆ˜์™€ bar ํ•จ์ˆ˜๋Š” ๋ชจ๋‘ ์ „์—ญ์—์„œ ์ •์˜๋œ ์ „์—ญ ํ•จ์ˆ˜์ด๋‹ค. ํ•จ์ˆ˜์˜ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋Š” ํ•จ์ˆ˜๋ฅผ ์–ด๋””์„œ ์ •์˜ํ–ˆ๋Š๋ƒ์— ๋”ฐ๋ผ ๊ฒฐ์ •๋˜๋ฏ€๋กœ foo ํ•จ์ˆ˜์™€ bar ํ•จ์ˆ˜์˜ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋Š” ์ „์—ญ์ด๋‹ค.

๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ์˜ "์™ธ๋ถ€ ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ์— ๋Œ€ํ•œ ์ฐธ์กฐ"์— ์ €์žฅํ•  ์ฐธ์กฐ๊ฐ’, ์ฆ‰ ์ƒ์œ„ ์Šค์ฝ”ํ”„์— ๋Œ€ํ•œ ์ฐธ์กฐ๋Š” ํ•จ์ˆ˜ ์ •์˜๊ฐ€ ํ‰๊ฐ€๋˜๋Š” ์‹œ์ ์— ํ•จ์ˆ˜๊ฐ€ ์ •์˜๋œ ํ™˜๊ฒฝ(์œ„์น˜)์— ์˜ํ•ด ๊ฒฐ์ •๋œ๋‹ค. ์ด๊ฒƒ์ด ๋ฐ”๋กœ ๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„๋‹ค.

24.2 ํ•จ์ˆ˜ ๊ฐ์ฒด์˜ ๋‚ด๋ถ€ ์Šฌ๋กฏ [[Environment]]

๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„๊ฐ€ ๊ฐ€๋Šฅํ•˜๋ ค๋ฉด ํ•จ์ˆ˜๋Š” ์ž์‹ ์ด ํ˜ธ์ถœ๋˜๋Š” ํ™˜๊ฒฝ๊ณผ๋Š” ์ƒ๊ด€์—†์ด ์ž์‹ ์ด ์ •์˜๋œ ํ™˜๊ฒฝ, ์ฆ‰ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋ฅผ ๊ธฐ์–ตํ•ด์•ผ ํ•œ๋‹ค. ํ•จ์ˆ˜๋Š” ์ž์‹ ์˜ ๋‚ด๋ถ€ ์Šฌ๋กฏ [[Environment]]์— ์ž์‹ ์ด ์ •์˜๋œ ํ™˜๊ฒฝ, ์ฆ‰ ์ƒ์œ„ ์Šค์ฝ”ํ”„์˜ ์ฐธ์กฐ๋ฅผ ์ €์žฅํ•œ๋‹ค.

24.3 ํด๋กœ์ €์™€ ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ

์•„๋ž˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ์™ธ๋ถ€ ํ•จ์ˆ˜๋ณด๋‹ค ์ค‘์ฒฉ ํ•จ์ˆ˜๊ฐ€ ๋” ์˜ค๋ž˜ ์œ ์ง€๋˜๋Š” ๊ฒฝ์šฐ ์ค‘์ฒฉ ํ•จ์ˆ˜๋Š” ์ด๋ฏธ ์ƒ๋ช… ์ฃผ๊ธฐ๊ฐ€ ์ข…๋ฃŒํ•œ ์™ธ๋ถ€ ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ค‘์ฒฉ ํ•จ์ˆ˜๋ฅผ ํด๋กœ์ €๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

//24-05
const x = 1;

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

const innerFunc = outer();
innerFunc(); // 10
  1. outer ํ•จ์ˆ˜๊ฐ€ ํ‰๊ฐ€๋˜์–ด ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ์˜ ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ, ์ฆ‰ ์ „์—ญ ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ์„ outer ํ•จ์ˆ˜ ๊ฐ์ฒด์˜ [[Environment]] ๋‚ด๋ถ€ ์Šฌ๋กฏ์— ์ƒ์œ„ ์Šค์ฝ”ํ”„๋กœ์„œ ์ €์žฅํ•œ๋‹ค.
  2. ์ค‘์ฒฉ ํ•จ์ˆ˜ inner๊ฐ€ ํ‰๊ฐ€๋œ๋‹ค. ์ž์‹ ์˜ [[Environment]] ๋‚ด๋ถ€ ์Šฌ๋กฏ์— ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ์˜ ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ, ์ฆ‰ outer ํ•จ์ˆ˜์˜ ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ์„ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋กœ์„œ ์ €์žฅํ•œ๋‹ค.
  3. outer ํ•จ์ˆ˜์˜ ์‹คํ–‰์ด ์ข…๋ฃŒํ•˜๋ฉด inner ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด์„œ outer ํ•จ์ˆ˜์˜ ์ƒ๋ช…์ฃผ๊ธฐ๊ฐ€ ์ข…๋ฃŒ๋œ๋‹ค. ์ด๋•Œ outer ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๋Š” ์Šคํƒ์—์„œ ์ œ๊ฑฐ๋˜์ง€๋งŒ outer ํ•จ์ˆ˜์˜ ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ๊นŒ์ง€ ์†Œ๋ฉธํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.
  4. outer ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•œ inner ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด inner ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  ์‹คํ–‰ ์ปจํ…์ŠคํŠธ ์Šคํƒ์— ํ‘ธ์‹œ๋œ๋‹ค.

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

24.4 ํด๋กœ์ €์˜ ํ™œ์šฉ

ํด๋กœ์ €๋Š” ์ƒํƒœ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•˜๊ณ  ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค. ์ฆ‰ ์ƒํƒœ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์€๋‹‰ํ•˜๊ณ  ํŠน์ •ํ•จ์ˆ˜์—๊ฒŒ๋งŒ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ํ—ˆ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค.

// 24-11
const increase = (function (){
  let num = 0;
  return function () {
    return ++num;
  }
}());


console.log(increase()); // 1
console.log(increase()); // 2
console.log(increase()); // 3

์ฆ‰์‹œ ์‹คํ–‰ ํ•จ์ˆ˜๋Š” ํ˜ธ์ถœ๋œ ์ดํ›„ ์†Œ๋ฉธํ•˜์ง€๋งŒ ์ฆ‰์‹œ ์‹คํ–‰ ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ํด๋กœ์ €๋Š” increase ๋ณ€์ˆ˜์— ํ• ๋‹น๋˜์–ด ํ˜ธ์ถœํ•œ๋‹ค. ๋˜ํ•œ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๋ฏ€๋กœ increase๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค num ๋ณ€์ˆ˜๊ฐ€ ์žฌ์ฐจ ์ดˆ๊ธฐํ™”๋  ์ผ์€ ์—†์„ ๊ฒƒ์ด๋‹ค.

// 24-14
// ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›๊ณ  ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ณ ์ฐจํ•จ์ˆ˜
function makeCounter(aux) {
  let counter = 0;
  
  return function () {
    counter = aux(counter);
    return counter;
  }
}

function increase(n) {
  return ++n;
}

function decrease(n) {
  return --n;
}

const increaser = makeCounter(increase);
const decreaser = makeCounter(decrease);

console.log(increaser()); // 1 
console.log(decreaser()); // -1

์œ„ ์˜ˆ์ œ๋Š” increaser๊ณผ decreaser์€ ๋ณ„๊ฐœ์˜ ๋…๋ฆฝ๋œ ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ์„ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์— ์นด์šดํ„ฐ ์ƒํƒœ๊ฐ€ ์—ฐ๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋…๋ฆฝ๋œ ์นด์šดํ„ฐ๊ฐ€ ์•„๋‹ˆ๋ผ ์—ฐ๋™ํ•˜์—ฌ ์ฆ๊ฐ์ด ๊ฐ€๋Šฅํ•œ ์นด์šดํ„ฐ๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ์„ ๊ณต์œ ํ•˜๋Š” ํด๋กœ์ €๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

// 24-15
const counter = (function () {
  let counter = 0;
  
  // ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ ๋ฐ›๋Š” ํด๋กœ์ €๋ฅผ ๋ฐ˜ํ™˜
  return function (aux) {
    counter = aux(counter);
    return counter;
  }
}());

function increase(n) {
  return ++n;
}

function decrease(n) {
  return --n;
}

console.log(counter(increase)); // 1
console.log(counter(decrease)); // 0

24.5 ์บก์Šํ™”์™€ ์ •๋ณด ์€๋‹‰

์บก์Šํ™”๋Š” ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํผํ‹ฐ๋‚˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๋™์ž‘์ธ ๋ฉ”์„œ๋“œ๋ฅผ ํ•˜๋‚˜๋กœ ๋ฌถ๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค. ์ •๋ณด ์€๋‹‰์€ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๋Š” ํšจ๊ณผ๊ฐ€ ์žˆ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์ •๋ณด ์€๋‹‰์„ ์™„์ „ํ•˜๊ฒŒ ์ง€์›ํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค. ์ง€๊ธˆ์€ ํด๋ž˜์Šค์— private ํ•„๋“œ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ์ƒˆ๋กœ์šด ํ‘œ์ค€ ์‚ฌํ–ฅ์ด ์ •์˜ ๋˜์–ด ์žˆ๋‹ค.

24.6 ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” ์‹ค์ˆ˜

// 24-20
var funcs = [];

for(var i = 0; i < 3; i++){
  funcs[i] = function () {
    return i;
  }
}

for(var j = 0; j < funcs.length; j++){
  console.log(funcs[j]()); // 3, 3, 3
}

์œ„ ์˜ˆ์ œ๋ฅผ ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋งŒ๋“ค๋ฉด

// 24-21
var funcs = [];

for(var i = 0; i < 3; i++){
  funcs[i] = (function (id) { // ์ง€์—ญ ๋ณ€์ˆ˜ i์— ํ˜„์žฌ ํ• ๋‹น๋˜์–ด ์žˆ๋Š” ๊ฐ’์„ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›์•„ ๋งค๊ฐœ๋ณ€์ˆ˜ id์— ํ• ๋‹นํ•œ ํ›„ ์ค‘์ฒฉ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์ข…๋ฃŒํ•œ๋‹ค.
  	return function () {
   	  return id;
    }
  }(i));
}

for(var j = 0; j < func.length; j++) {
  console.log(funcs[j]());
}

Ref

  • ์ด์›…๋ชจ ์ €, โŒœ๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Deep DiveโŒŸ, ์œ„ํ‚ค๋ถ์Šค
profile
๋งค ์ˆœ๊ฐ„ ์„ฑ์žฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€