ํด๋กœ์ €์˜ ์˜๋ฏธ ๋ฐ ์›๋ฆฌ ์ดํ•ด

์•ž์—์„œ ์‹คํ–‰์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•ด ๋ฐฐ์šด ์ง€์‹์„ ๋ฐ”ํƒ•์œผ๋กœ ํด๋กœ์ €๋ฅผ ์ •์˜ํ•ด๋ณธ๋‹ค๋ฉด, ํด๋กœ์ €๋ž€ ์™ธ๋ถ€ ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋‚ด๋ถ€ ํ•จ์ˆ˜๋ฅผ ์™ธ๋ถ€๋กœ ์ „๋‹ฌํ•  ๋•Œ ์™ธ๋ถ€ ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋œ ํ›„์—๋„ ์™ธ๋ถ€ ํ•จ์ˆ˜๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ํ˜„์ƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ œ๊ฐ€ ์™œ ํด๋กœ์ €๋ฅผ ์ •์˜ํ–ˆ๋Š”์ง€ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์šฐ์„  ์™ธ๋ถ€ ํ•จ์ˆ˜์—์„œ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ณ  ๋‚ด๋ถ€ ํ•จ์ˆ˜์—์„œ ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋Š” ํ˜•ํƒœ์˜ ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

var outer = function () {
  var a = 1;
  var inner = function () {
    console.log(++a);
  };
  inner();
};
outer();

outer ํ•จ์ˆ˜์—์„œ ๋ณ€์ˆ˜ a๋ฅผ ์„ ์–ธํ–ˆ๊ณ , outer์˜ ๋‚ด๋ถ€ ํ•จ์ˆ˜์ธ inner ํ•จ์ˆ˜์—์„œ a์˜ ๊ฐ’์„ 1๋งŒํผ ์ฆ๊ฐ€์‹œํ‚จ ๋‹ค์Œ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. inner ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋Š” a๋ฅผ ์„ ์–ธํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— environmentRecord์—์„œ ๊ฐ’์„ ์ฐพ์ง€ ๋ชปํ•˜๋ฏ€๋กœ outerEnvironmentReference์— ์ง€์ •๋œ ์ƒ์œ„ ์ปจํ…์ŠคํŠธ์ธ outer์˜ LexicalEnvironment์— ์ ‘๊ทผํ•ด์„œ ๋‹ค์‹œ a๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค. 4๋ฒˆ์งธ ์ค„์—์„œ๋Š” 2๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค. outer ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด LexicalEnvironment์— ์ €์žฅ๋œ ์‹๋ณ„์ž(a, inner)์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ์ง€์›๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๊ฐ ์ฃผ์†Œ์— ์ €์žฅ๋ผ ์žˆ๋˜ ๊ฐ’๋“ค์€ ์ž์‹ ์„ ์ฐธ์กฐํ•˜๋Š” ๋ณ€์ˆ˜๊ฐ€ ํ•˜๋‚˜๋„ ์—†๊ฒŒ ๋˜๋ฏ€๋กœ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์˜ ์ˆ˜์ง‘ ๋Œ€์ƒ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์˜ˆ์ œ๋„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

var outer = function () {
  var a = 1;
  var inner = function () {
    return ++a;
  };
  return inner();
};
var outer2 = outer();
console.log(outer2);

์ด๋ฒˆ์—๋„ inner ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์™ธ๋ถ€ ๋ณ€์ˆ˜์ธ a๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ 6๋ฒˆ์งธ ์ค„์—์„œ๋Š” Inner ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํ„ดํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ๊ฒฐ๊ณผ์ ์œผ๋กœ outer ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋œ ์‹œ์ ์—๋Š” a ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋Œ€์ƒ์ด ์—†์–ด์ง‘๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์ œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ a, inner ๋ณ€์ˆ˜์˜ ๊ฐ’๋“ค์€ ์–ธ์  ๊ฐ€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์— ์˜ํ•ด ์†Œ๋ฉธํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ญ์‹œ ์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜ ๋ฐ ๋‚ด๋ถ€ ํ•จ์ˆ˜์—์„œ์˜ ๋™์ž‘๊ณผ ์ฐจ์ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์œ„ ๋‘ outer ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋˜๊ธฐ ์ด์ „์— inner ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋ผ ์žˆ์œผ๋ฉฐ, ์ดํ›„ ๋ณ„๋„๋กœ inner ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ณตํ†ต์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด outer์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋œ ํ›„์—๋„ inner ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค๋ฉด ์–ด๋–จ๊นŒ์š”?

var outer = function () {
  var a = 1;
  var inner = function () {
    return ++a;
  };
  return inner;
};
var outer2 = outer();
console.log(outer2());
console.log(outer2());

์ด๋ฒˆ์—๋Š” 6๋ฒˆ์งธ ์ค„์—์„œ inner ํ•จ์ˆ˜์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๊ฐ€ ์•„๋‹Œ inner ํ•จ์ˆ˜ ์ž์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด outer ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ outer2 ๋ณ€์ˆ˜๋Š” outer์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ์ธ inner ํ•จ์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ดํ›„ 9๋ฒˆ์งธ์—์„œ outer2๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์•ž์„œ ๋ฐ˜ํ™˜๋œ ํ•จ์ˆ˜์ธ inner๊ฐ€ ์‹คํ–‰๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

inner ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ์˜ environmentRecord์—๋Š” ์ˆ˜์ง‘ํ•  ์ •๋ณด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. outer-EnvironmentReference์—๋Š” inner ํ•จ์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ์œ„์น˜์˜ LexicalEnvironment๊ฐ€ ์ฐธ์กฐ ๋ณต์‚ฌ๋ฉ๋‹ˆ๋‹ค. inner ํ•จ์ˆ˜๋Š” outer ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์„ ์–ธ๋์œผ๋ฏ€๋กœ, outer ํ•จ์ˆ˜์˜ LexicalEnvironment๊ฐ€ ๋‹ด๊ธธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์ œ ์Šค์ฝ”ํ”„ ์ฒด์ด๋‹์— ๋”ฐ๋ผ outer์—์„œ ์„ ์–ธํ•œ ๋ณ€์ˆ˜ a์— ์ ‘๊ทผํ•ด์„œ 1๋งŒํผ ์ฆ๊ฐ€์‹œํ‚จ ํ›„ ๊ทธ ๊ฐ’์ธ 2๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , inner ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค. 10๋ฒˆ์งธ ์ค„์—์„œ ๋‹ค์‹œ outer2๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ a์˜ ๊ฐ’์„ 2์—์„œ 3์œผ๋กœ 1 ์ฆ๊ฐ€์‹œํ‚จ ํ›„ 3์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ด์ƒํ•œ ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. Inner ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์‹œ์ ์—๋Š” outer ํ•จ์ˆ˜๋Š” ์ด๋ฏธ ์‹คํ–‰์ด ์ข…๋ฃŒ๋œ ์ƒํƒœ์ธ๋ฐ outer ํ•จ์ˆ˜์˜ LexicalEnvironment์— ์–ด๋–ป๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ผ๊นŒ์š”? ์ด๋Š” ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์˜ ๋™์ž‘ ๋ฐฉ์‹ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๋Š” ์–ด๋–ค ๊ฐ’์„ ์ฐธ์กฐํ•˜๋Š” ๋ณ€์ˆ˜๊ฐ€ ํ•˜๋‚˜๋ผ๋„ ์žˆ๋‹ค๋ฉด ๊ทธ ๊ฐ’์€ ์ˆ˜์ง‘ ๋Œ€์ƒ์— ํฌํ•จ์‹œํ‚ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์‹œ์—์„œ outer ํ•จ์ˆ˜๋Š” ์‹คํ–‰ ์ข…๋ฃŒ ์‹œ์ ์— inner ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€ ํ•จ์ˆ˜์ธ outer์˜ ์‹คํ–‰์ด ์ข…๋ฃŒ๋˜๋”๋ผ๋„ ๋‚ด๋ถ€ ํ•จ์ˆ˜์ธ inner ํ•จ์ˆ˜๋Š” ์–ธ์  ๊ฐ€ outer2๋ฅผ ์‹คํ–‰ํ•จ์œผ๋กœ์จ ํ˜ธ์ถœ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์—ด๋ฆฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์–ธ์  ๊ฐ€ inner ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ํ™œ์„ฑํ™”๋˜๋ฉด outerEnvironmentReference๊ฐ€ outer ํ•จ์ˆ˜์˜ LexicalEnvironment๋ฅผ ํ•„์š”๋กœ ํ•  ๊ฒƒ์ด๋ฏ€๋กœ ์ˆ˜์ง‘ ๋Œ€์ƒ์—์„œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค. ๊ทธ ๋•์— inner ํ•จ์ˆ˜๊ฐ€ ์ด ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ๋‹ค์‹œ ์ •๋ฆฌํ•ด๋ณด๋ฉด, ํด๋กœ์ €๋ž€ ์™ธ๋ถ€ ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋‚ด๋ถ€ ํ•จ์ˆ˜๋ฅผ ์™ธ๋ถ€๋กœ ์ „๋‹ฌํ•  ๋•Œ ์™ธ๋ถ€ ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋œ ํ›„์—๋„ ์™ธ๋ถ€ ํ•จ์ˆ˜๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ํ˜„์ƒ์ด๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด, ํด๋กœ์ €๋ฅผ ํ™œ์šฉํ•  ๋•Œ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋Š” ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”? ์ด์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํด๋กœ์ €์™€ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ

ํด๋กœ์ €๋Š” ๋‚ด๋ถ€ ํ•จ์ˆ˜๊ฐ€ ์™ธ๋ถ€ ํ•จ์ˆ˜์˜ ๊ฐ’์„ ์ฐธ์กฐํ•ด์•ผ ํ•  ๋•Œ, ์˜๋„์ ์œผ๋กœ ํ•จ์ˆ˜์˜ ์ง€์—ญ๋ณ€์ˆ˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์†Œ๋ชจํ•˜๋„๋ก ํ•จ์œผ๋กœ์จ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ํšจ์œจ์ ์ธ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”? ํ•ด๊ฒฐ์ฑ…์€ ์ง€์—ญ๋ณ€์ˆ˜์˜ ํ•„์š”์„ฑ์ด ์‚ฌ๋ผ์ง„ ์‹œ์ ์— ๋”๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์†Œ๋ชจํ•˜์ง€ ์•Š๊ฒŒ ํ•ด ์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ฐธ์กฐ ์นด์šดํŠธ๋ฅผ 0์œผ๋กœ ๋งŒ๋“ค๋ฉด ์–ธ์  ๊ฐ€ GC๊ฐ€ ์ˆ˜๊ฑฐํ•ด๊ฐˆ ๊ฒƒ์ด๊ณ , ์ด๋•Œ ์†Œ๋ชจ๋๋˜ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํšŒ์ˆ˜๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฐธ์กฐ ์นด์šดํŠธ๋ฅผ 0์œผ๋กœ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์€? ์‹๋ณ„์ž์— ์ฐธ์กฐํ˜•์ด ์•„๋‹Œ ๊ธฐ๋ณธํ˜• ๋ฐ์ดํ„ฐ(๋ณดํ†ต null์ด๋‚˜ undefined)๋ฅผ ํ• ๋‹นํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ์ฝ”๋“œ์— ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

// (1) return์— ์˜ํ•œ ํด๋กœ์ €์˜ ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ
var outer = (function () {
    var a = 1;
    var inner = function() {
        return ++a;
    };
    return inner;
})();
console.log(outer());
console.log(outer());
outer = null; // outer ์‹๋ณ„์ž์˜ inner ํ•จ์ˆ˜ ์ฐธ์กฐ๋ฅผ ๋Š์Œ

ํด๋กœ์ € ํ™œ์šฉ ์‚ฌ๋ก€

์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์™ธ๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•  ๋•Œ

๋Œ€ํ‘œ์ ์ธ ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ์ค‘ ํ•˜๋‚˜์ธ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ์— ๊ด€ํ•˜์—ฌ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

var fruits = ['apple', 'banana', 'peach'];
var $ul = document.createElement('ul');

fruits.forEach(function(fruit) {
    var $li = document.createElement('li');
    $li.innerText = fruit;
    $li.addEventListener('click', function(){
        alert('your choice is ' + fruit);
    });
    $ul.appendChild($li);
});
document.body.appendChild($ul);

fruits ๋ณ€์ˆ˜๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ li๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ฐ li๋ฅผ ํด๋ฆญํ•˜๋ฉด ํ•ด๋‹น ๋ฆฌ์Šค๋„ˆ์— ๊ธฐ์–ต๋œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค. 4๋ฒˆ์งธ ์ค„์˜ forEach ๋ฉ”์„œ๋“œ์— ๋„˜๊ฒจ์ค€ ์ต๋ช…์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜(A)๋Š” ๊ทธ ๋‚ด๋ถ€์—์„œ ์™ธ๋ถ€ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์žˆ์œผ๋ฏ€๋กœ ํด๋กœ์ €๊ฐ€ ์—†์ง€๋งŒ, 7๋ฒˆ์งธ ์ค„์˜ addEventListener์— ๋„˜๊ฒจ์ค€ ์ฝœ๋ฐฑ ํ•จ์ˆ˜(B)์—๋Š” fruit์ด๋ผ๋Š” ์™ธ๋ถ€ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ํด๋กœ์ €๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. (A)๋Š” fruits์˜ ๊ฐœ์ˆ˜๋งŒํผ ์‹คํ–‰๋˜๋ฉฐ, ๊ทธ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ํ™œ์„ฑํ™”๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. A์˜ ์‹คํ–‰ ์ข…๋ฃŒ ์—ฌ๋ถ€์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ํด๋ฆญ ์ด๋ฒคํŠธ์— ์˜ํ•ด ๊ฐ ์ปจํ…์ŠคํŠธ์˜ (B)๊ฐ€ ์‹คํ–‰๋  ๋•Œ๋Š” (B)์˜ outerEnvironmentReference๊ฐ€ (A)์˜ LexicalEnvironment๋ฅผ ์ฐธ์กฐํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ตœ์†Œํ•œ (B) ํ•จ์ˆ˜๊ฐ€ ์ฐธ์กฐํ•  ์˜ˆ์ •์ธ ๋ณ€์ˆ˜ fruit์— ๋Œ€ํ•ด์„œ๋Š” (A)๊ฐ€ ์ข…๋ฃŒ๋œ ํ›„์—๋„ GC ๋Œ€์ƒ์—์„œ ์ œ์™ธ๋˜์–ด ๊ณ„์† ์ฐธ์กฐ ๊ฐ€๋Šฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ (B) ํ•จ์ˆ˜๊ฐ€ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฟ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ๊ณณ์—์„œ๋„ ์“ฐ์ธ๋‹ค๋ฉด, ๋ฐ˜๋ณต์„ ์ค„์ด๊ธฐ ์œ„ํ•ด (B)๋ฅผ ์™ธ๋ถ€๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ํŽธ์ด ๋‚˜์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Bํ•จ์ˆ˜๋ฅผ ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

var alertFruit = function(fruit){
    alert('your choice is ' + fruit);
};

fruits.forEach(function(fruit) {
    var $li = document.createElement('li');
    $li.innerText = fruit;
    $li.addEventListener('click', alertFruit);
    $ul.appendChild($li);
});
document.body.appendChild($ul);
alertFruit(fruits[1]);

์œ„์˜ ์˜ˆ์‹œ์—์„œ๋Š” ๊ณตํ†ต ํ•จ์ˆ˜๋กœ ์“ฐ๊ณ ์ž ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์™ธ๋ถ€๋กœ ๊บผ๋‚ด์–ด alertFruit๋ผ๋Š” ๋ณ€์ˆ˜์— ๋‹ด์•˜์Šต๋‹ˆ๋‹ค. ์ด์ œ alertFruit์„ ์ง์ ‘ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ 14๋ฒˆ์งธ ์ค„์—์„œ๋Š” ์ •์ƒ์ ์œผ๋กœ 'banana'์— ๋Œ€ํ•œ ์–ผ๋Ÿฟ์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ๊ฐ li๋ฅผ ํด๋ฆญํ•˜๋ฉด ํด๋ฆญํ•œ ๋Œ€์ƒ์˜ ๊ณผ์ผ๋ช…์ด ์•„๋‹Œ [object MouseEvent]๋ผ๋Š” ๊ฐ’์ด ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค. ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ธ์ž์— ๋Œ€ํ•œ ์ œ์–ด๊ถŒ์„ addEventListener๊ฐ€ ๊ฐ€์ง„ ์ƒํƒœ์ด๋ฉฐ, addEventListener๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ฒซ ๋ฒˆ์งธ ์ธ์ž์— '์ด๋ฒคํŠธ ๊ฐ์ฒด'๋ฅผ ์ฃผ์ž…ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” bind ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์†์‰ฝ๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

var alertFruit = function(fruit){
    alert('your choice is ' + fruit);
};

fruits.forEach(function(fruit) {
    var $li = document.createElement('li');
    $li.innerText = fruit;
    $li.addEventListener('click', alertFruit.bind(null, fruit));
    $ul.appendChild($li);
});
document.body.appendChild($ul);
alertFruit(fruits[1]);

๋‹ค๋งŒ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ์ธ์ž๋กœ ๋„˜์–ด์˜ค๋Š” ์ˆœ์„œ๊ฐ€ ๋ฐ”๋€Œ๋Š” ์  ๋ฐ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ์˜ this๊ฐ€ ์›๋ž˜์˜ ๊ทธ๊ฒƒ๊ณผ ๋‹ฌ๋ผ์ง€๋Š” ์ ์€ ๊ฐ์•ˆํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ฒŒ๋” ํ•˜๋ฉด์„œ ์ด์Šˆ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” bind ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ํ’€์–ด๋‚ด์•ผ๋งŒ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋‹ค๋ฅธ ๋ฐฉ์‹์ด๋ž€ ๊ณ ์ฐจ ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ, ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์ž์ฃผ ์“ฐ์ด๋Š” ๋ฐฉ์‹์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

var alertFruitBuilder = function (fruit){
    return function() {
        alert('your choice is ' + fruit);
    }
}

fruits.forEach(function (fruit) {
    var $li = document.createElement('li');
    $li.innerText = fruit;
    $li.addEventListener('click', alertFruitBuilder(fruit));
    $ul.appendChild($li);
});

4๋ฒˆ์งธ ์ค„์—์„œ alertFruit ํ•จ์ˆ˜ ๋Œ€์‹  alertFruitBuilder๋ผ๋Š” ์ด๋ฆ„์˜ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋Š” ๋‹ค์‹œ ์ต๋ช… ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”๋ฐ, ์ด ์ต๋ช… ํ•จ์ˆ˜๊ฐ€ ๋ฐ”๋กœ ๊ธฐ์กด์˜ alertFruit ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. 12๋ฒˆ์งธ ์ค„์—์„œ๋Š” alertFruitBuilder ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋ฉด์„œ fruit ๊ฐ’์„ ์ธ์ž๋กœ ์ „๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ด ํ•จ์ˆ˜์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค์‹œ ํ•จ์ˆ˜๊ฐ€ ๋˜๋ฉฐ, ์ด๋ ‡๊ฒŒ ๋ฐ˜ํ™˜๋œ ํ•จ์ˆ˜๋ฅผ ๋ฆฌ์Šค๋„ˆ์— ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ์จ ์ „๋‹ฌํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ดํ›„ ์–ธ์  ๊ฐ€ ํด๋ฆญ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋น„๋กœ์†Œ ์ด ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์—ด๋ฆฌ๋ฉด์„œ alertFruitBuilder์˜ ์ธ์ž๋กœ ๋„˜์–ด์˜จ fruit๋ฅผ outerEnvironmentReference์— ์˜ํ•ด ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, alertFruitBuilder์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๋กœ ๋ฐ˜ํ™˜๋œ ํ•จ์ˆ˜์—๋Š” ํด๋กœ์ €๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€ ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์™ธ๋ถ€ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ• ์„ธ ๊ฐ€์ง€๋ฅผ ์‚ดํŽด๋ดค์Šต๋‹ˆ๋‹ค.

  1. ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋‚ด๋ถ€ ํ•จ์ˆ˜๋กœ ์„ ์–ธํ•ด์„œ ์™ธ๋ถ€ ๋ณ€์ˆ˜๋ฅผ ์ง์ ‘ ์ฐธ์กฐํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ, ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•œ ๋ฐฉ๋ฒ•.
  2. bind ๋ฉ”์„œ๋“œ๋กœ ๊ฐ’์„ ์ง์ ‘ ๋„˜๊ฒจ์ค€ ๋•๋ถ„์— ํด๋กœ์ €๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ฒŒ ๋œ ๋ฐ˜๋ฉด ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ œ์•ฝ์‚ฌํ•ญ์ด ๋”ฐ๋ฅด๊ฒŒ ๋์Šต๋‹ˆ๋‹ค.
  3. ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๊ณ ์ฐจ ํ•จ์ˆ˜๋กœ ๋ฐ”๊ฟ”์„œ ํด๋กœ์ €๋ฅผ ์ ๊ทน์ ์œผ๋กœ ํ™œ์šฉํ•œ ๋ฐฉ๋ฒ•

์ด ์„ธ ๋ฐฉ๋ฒ•์˜ ์žฅ๋‹จ์ ์„ ๊ฐ๊ธฐ ํŒŒ์•…ํ•˜๊ณ  ๊ตฌ์ฒด์ ์ธ ์ƒํ™ฉ์— ๋”ฐ๋ผ ์–ด๋–ค ๋ฐฉ๋ฒ•์„ ๋„์ž…ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ํšจ๊ณผ์ ์ผ์ง€ ๊ณ ๋ฏผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ ‘๊ทผ ๊ถŒํ•œ ์ œ์–ด (์ •๋ณด ์€๋‹‰)

๋‘ ๋ฒˆ์งธ ์ •๋ณด ์€๋‹‰์€ ์–ด๋–ค ๋ชจ๋“ˆ์˜ ๋‚ด๋ถ€ ๋กœ์ง์— ๋Œ€ํ•ด ์™ธ๋ถ€๋กœ์˜ ๋…ธ์ถœ์„ ์ตœ์†Œํ™”ํ•ด์„œ ๋ชจ๋“ˆ ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๊ณ  ์œ ์—ฐ์„ฑ์„ ๋†’์ด๊ณ ์ž ํ•˜๋Š” ํ˜„๋Œ€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ ์ค‘์š”ํ•œ ๊ฐœ๋… ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ํ”ํžˆ ์ ‘๊ทผ ๊ถŒํ•œ์—๋Š” public, private, protected์˜ ์„ธ ์ข…๋ฅ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๋‹จ์–ด์˜ ์˜๋ฏธ ๊ทธ๋Œ€๋กœ, public์€ ์™ธ๋ถ€์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๊ฒƒ์ด๊ณ , private์€ ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋ฉฐ ์™ธ๋ถ€์— ๋…ธ์ถœ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ณ€์ˆ˜ ์ž์ฒด์— ์ด๋Ÿฌํ•œ ์ ‘๊ทผ ๊ถŒํ•œ์„ ์ง์ ‘ ๋ถ€์—ฌํ•˜๋„๋ก ์„ค๊ณ„๋ผ ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๊ณ  ์ ‘๊ทผ ๊ถŒํ•œ ์ œ์–ด๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ํด๋กœ์ €๋ฅผ ์ด์šฉํ•˜๋ฉด ํ•จ์ˆ˜ ์ฐจ์›์—์„œ public ํ•œ ๊ฐ’๊ณผ private ํ•œ ๊ฐ’์„ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

var outer = function () {
    var a = 1;
    var inner = function() {
        return ++a;
    }
    return inner;
};

var outer2 = outer();
console.log(outer2());
console.log(outer2());

outer ํ•จ์ˆ˜๋ฅผ ์ข…๋ฃŒํ•  ๋•Œ inner ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•จ์œผ๋กœ์จ outer ํ•จ์ˆ˜์˜ ์ง€์—ญ๋ณ€์ˆ˜์ธ a์˜ ๊ฐ’์„ ์™ธ๋ถ€์—์„œ๋„ ์ฝ์„ ์ˆ˜ ์žˆ๊ฒŒ ๋์Šต๋‹ˆ๋‹ค. ์ด์ฒ˜๋Ÿผ ํด๋กœ์ €๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์™ธ๋ถ€ ์Šค์ฝ”ํ”„์—์„œ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ๋ณ€์ˆ˜๋“ค ์ค‘ ์„ ํƒ์ ์œผ๋กœ ์ผ๋ถ€์˜ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์ ‘๊ทผ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ return์„ ํ™œ์šฉํ•ด์„œ ๋ง์ž…๋‹ˆ๋‹ค.

closure๋ผ๋Š” ์˜์–ด ๋‹จ์–ด๋Š” ์‚ฌ์ „์ ์œผ๋กœ '๋‹ซํ˜€์žˆ์Œ', ํ์‡„์„ฑ, ์™„๊ฒฐ์„ฑ' ์ •๋„์˜ ์˜๋ฏธ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ์ด ํ์‡„์„ฑ์— ์ฃผ๋ชฉํ•ด๋ณด๋ฉด ์œ„ ์˜ˆ์ œ๋ฅผ ์กฐ๊ธˆ ๋‹ค๋ฅด๊ฒŒ ๋ฐ›์•„๋“ค์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. outer ํ•จ์ˆ˜๋Š” ์™ธ๋ถ€(์ „์—ญ ์Šค์ฝ”ํ”„)๋กœ๋ถ€ํ„ฐ ์ฒ ์ €ํ•˜๊ฒŒ ๊ฒฉ๋ฆฌ๋œ ๋‹ซํžŒ ๊ณต๊ฐ„์ž…๋‹ˆ๋‹ค. ์™ธ๋ถ€์—์„œ๋Š” ์™ธ๋ถ€ ๊ณต๊ฐ„์— ๋…ธ์ถœ๋ผ ์žˆ๋Š” outer๋ผ๋Š” ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด outer ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, outer ํ•จ์ˆ˜ ๋‚ด๋ถ€์—๋Š” ์–ด๋– ํ•œ ๊ฐœ์ž…๋„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์™ธ๋ถ€์—์„œ๋Š” ์˜ค์ง outer ํ•จ์ˆ˜๊ฐ€ return ํ•œ ์ •๋ณด์—๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. return ๊ฐ’์ด ์™ธ๋ถ€์— ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ์œ ์ผํ•œ ์ˆ˜๋‹จ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ์™ธ๋ถ€์— ์ œ๊ณตํ•˜๊ณ ์ž ํ•˜๋Š” ์ •๋ณด๋“ค์„ ๋ชจ์•„์„œ return ํ•˜๊ณ , ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ •๋ณด๋“ค์€ return ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ์ ‘๊ทผ ๊ถŒํ•œ ์ œ์–ด๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. return ํ•œ ๋ณ€์ˆ˜๋“ค์€ ๊ณต๊ฐœ ๋ฉค๋ฒ„๊ฐ€ ๋˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์€ ๋ณ€์ˆ˜๋“ค์€ ๋น„๊ณต๊ฐœ ๋ฉค๋ฒ„๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€ ํด๋กœ์ €์˜ ๊ฐœ๋…์„ ํ™œ์šฉํ•ด์„œ ์™ธ๋ถ€ ์Šค์ฝ”ํ”„์—์„œ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ๋ณ€์ˆ˜ ์ค‘ ์ผ๋ถ€์— ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ตํ˜€๋ดค๋Š”๋ฐ, ์ด๋ฒˆ์—๋Š” ํด๋กœ์ €๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ, getter์™€ setter ๊ฐœ๋…์„ ํ†ตํ•ด ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ

์ ‘๊ทผ์ž๋ž€ ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๊ฐ์ฒด๊ฐ€ ๊ฐ€์ง„ ํ”„๋กœํผํ‹ฐ ๊ฐ’์„ ๊ฐ์ฒด ๋ฐ”๊นฅ์—์„œ ์ฝ๊ฑฐ๋‚˜ ์“ธ ์ˆ˜ ์žˆ๋„๋ก ์ œ๊ณตํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋ž€ ๊ฐ’์„ ํš๋“(get)ํ•˜๊ณ  ์„ค์ •(set)ํ•˜๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€ ์ฝ”๋“œ์—์„œ๋Š” ํ•จ์ˆ˜๊ฐ€ ์•„๋‹Œ ์ผ๋ฐ˜์ ์ธ ํ”„๋กœํผํ‹ฐ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

getter์™€ setter

์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋Š” 'getter(ํš๋“์ž)'์™€ 'setter(์„ค์ •์ž)' ๋ฉ”์„œ๋“œ๋กœ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค. ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ์•ˆ์—์„œ getter์™€ setter ๋ฉ”์„œ๋“œ๋Š” get๊ณผ set์œผ๋กœ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

let obj = {
 get propName() {
   // getter, obj.propName์„ ์‹คํ–‰ํ•  ๋•Œ ์‹คํ–‰๋˜๋Š” ์ฝ”๋“œ
 },

 set propName(value) {
   // setter, obj.propNAme = value๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ์‹คํ–‰๋˜๋Š” ์ฝ”๋“œ
 }
};

getter ๋ฉ”์„œ๋“œ๋Š” obj.propName์„ ์‚ฌ์šฉํ•ด ํ”„๋กœํผํ‹ฐ๋ฅผ ์ฝ์œผ๋ ค๊ณ  ํ•  ๋•Œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. setter ๋ฉ”์„œ๋“œ๋Š” obj.propName = value์œผ๋กœ ํ”„๋กœํผํ‹ฐ์— ๊ฐ’์„ ํ• ๋‹นํ•˜๋ ค ํ•  ๋•Œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ํ†ตํ•ด getter์™€ setter์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

let user = {
  name: "John",
  surname: "Smith",

  get fullName() {
    return `${this.name} ${this.surname}`;
  }
};

alert(user.fullName); // John Smith

๋ฐ”๊นฅ ์ฝ”๋“œ์—์„  ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋ฅผ ์ผ๋ฐ˜ ํ”„๋กœํผํ‹ฐ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋Š” ์ด๋Ÿฐ ์•„์ด๋””์–ด์—์„œ ์ถœ๋ฐœํ–ˆ์Šต๋‹ˆ๋‹ค. ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜์ฒ˜๋Ÿผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ , ์ผ๋ฐ˜ ํ”„๋กœํผํ‹ฐ์—์„œ ๊ฐ’์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ํ‰๋ฒ”ํ•˜๊ฒŒ user.fullName์„ ์‚ฌ์šฉํ•ด ํ”„๋กœํผํ‹ฐ ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋จธ์ง€ ์ž‘์—…์€ getter ๋ฉ”์„œ๋“œ๊ฐ€ ๋’ท๋‹จ์—์„œ ์ฒ˜๋ฆฌํ•ด์ค๋‹ˆ๋‹ค. ํ•œํŽธ ์œ„ ์˜ˆ์‹œ์˜ fullName์€ getter ๋ฉ”์„œ๋“œ๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— user.fullName = ์„ ์‚ฌ์šฉํ•ด ๊ฐ’์„ ์‚ฌ์šฉํ•ด ๊ฐ’์„ ํ• ๋‹นํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

let user = {
  name: "John",
  surname: "Smith",

  get fullName() {
    return `${this.name} ${this.surname}`;
  }
};

user.fullName = "Test"; // Error (ํ”„๋กœํผํ‹ฐ์— getter ๋ฉ”์„œ๋“œ๋งŒ ์žˆ์–ด์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.)

ํ•˜์ง€๋งŒ setter๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด, ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

let user = {
  name: "John",
  surname: "Smith",

  get fullName() {
    return `${this.name} ${this.surname}`;
  },

  set fullName(value) {
    [this.name, this.surname] = value.split(" ");
  }
};

// ์ฃผ์–ด์ง„ ๊ฐ’์„ ์‚ฌ์šฉํ•ด set fullName์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
user.fullName = "Alice Special"

alert(user.fullName); // Alice Special
alert(user.name); // Alice
alert(user.surname); // Special

์ด๋ ‡๊ฒŒ getter์™€ setter ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ๊ฐ์ฒด์—” fullName์ด๋ผ๋Š” '๊ฐ€์ƒ'์˜ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ƒ๊น๋‹ˆ๋‹ค. ๊ฐ€์ƒ์˜ ํ”„๋กœํผํ‹ฐ๋Š” ์ฝ๊ณ  ์“ธ ์ˆœ ์žˆ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ getter์™€ setter์˜ ์‚ฌ์šฉ์— ๋Œ€ํ•ด ์กฐ๊ธˆ ๋” ์ž์„ธํ•˜๊ฒŒ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

getter์™€ setter ๋˜‘๋˜‘ํ•˜๊ฒŒ ํ™œ์šฉํ•˜๊ธฐ

์ผ๋ฐ˜์ ์œผ๋กœ ์ด๋ฆ„์„ ์ฝ๊ณ  ์ˆ˜์ •ํ•˜๋Š” ๊ฐ์ฒด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ด๋ฆ„์„ ์ˆ˜์ •ํ•˜๋Š” ๋ฉ”์„œ๋“œ setName()์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

let user = {
  name: '',
  setName(value) {
    if (value.length < 4) {
      alert("์ž…๋ ฅํ•˜์‹  ๊ฐ’์ด ๋„ˆ๋ฌด ์งง์Šต๋‹ˆ๋‹ค. ๋„ค ๊ธ€์ž ์ด์ƒ์œผ๋กœ ๊ตฌ์„ฑ๋œ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”.");
      return;
    }
    this.name = value;
  }
};

user.setName("Pete");
alert(user.name); // Pete

user.setName(""); // ๋„ˆ๋ฌด ์งง์€ ์ด๋ฆ„์„ ํ• ๋‹นํ•˜๋ ค ํ•จ

๊ทธ๋Ÿฌ๋‚˜ getter์™€ setter๋ฅผ '์‹ค์ œ' ํ”„๋กœํผํ‹ฐ ๊ฐ’์„ ๊ฐ์‹ธ๋Š” ๋ž˜ํผ(wrapper)์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๋ฉด, ๋ฉ”์„œ๋“œ๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“œ๋Š” ์ผ ์—†์ด ํ”„๋กœํผํ‹ฐ ๊ฐ’์„ ์›ํ•˜๋Š” ๋Œ€๋กœ ํ†ต์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

let user = {
  get name() {
    return this._name;
  },

  set name(value) {
    if (value.length < 4) {
      alert("์ž…๋ ฅํ•˜์‹  ๊ฐ’์ด ๋„ˆ๋ฌด ์งง์Šต๋‹ˆ๋‹ค. ๋„ค ๊ธ€์ž ์ด์ƒ์œผ๋กœ ๊ตฌ์„ฑ๋œ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”.");
      return;
    }
    this._name = value;
  }
};

user.name = "Pete";
alert(user.name); // Pete

user.name = ""; // ๋„ˆ๋ฌด ์งง์€ ์ด๋ฆ„์„ ํ• ๋‹นํ•˜๋ ค ํ•จ

user์˜ ์ด๋ฆ„์€ _name์— ์ €์žฅ๋˜๊ณ , ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์€ getter(user.name)์™€ setter(user.name = value)๋ฅผ ํ†ตํ•ด ์ด๋ค„์ง‘๋‹ˆ๋‹ค. ๊ธฐ์ˆ ์ ์œผ๋ก  ์™ธ๋ถ€ ์ฝ”๋“œ์—์„œ user._name์„ ์‚ฌ์šฉํ•ด ์ด๋ฆ„์— ๋ฐ”๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ฐ‘์ค„(user._name)๋กœ ์‹œ์ž‘ํ•˜๋Š” ํ”„๋กœํผํ‹ฐ๋Š” ๊ฐ์ฒด ๋‚ด๋ถ€์—์„œ๋งŒ ํ™œ์šฉํ•˜๊ณ , ์™ธ๋ถ€์—์„œ๋Š” ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ด€์Šต์ž…๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์ œ์—์„œ user.name์„ ํ†ตํ•ด ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•˜๊ณ  ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ user._name์„ ์ง์ ‘์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€๋Š” ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

Reference

 

๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค!