๐Ÿชด ์„ฑ์žฅ์ผ์ง€

์ฑ… ํ–‰๋ณตํ•œ ์ด๊ธฐ์ฃผ์˜์ž(์›จ์ธ ๋‹ค์ด์–ด)์˜ ๋‚ด์šฉ์— ์ž๊ทน๋ฐ›์•„ ์‹œ์ž‘ํ•˜๋Š” ์†Œ๋ฐ•ํ•œ ์„ฑ์žฅ๊ธฐ๋ก

์‚ด์•„์žˆ๋Š” ๊ฝƒ๊ณผ ์ฃฝ์€ ๊ฝƒ์€ ์–ด๋–ป๊ฒŒ ๊ตฌ๋ณ„ํ•˜๋Š”๊ฐ€?
์„ฑ์žฅํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด ์‚ด์•„ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.
์ƒ๋ช…์˜ ์œ ์ผํ•œ ์ฆ๊ฑฐ๋Š” ์„ฑ์žฅ์ด๋‹ค!

๐ŸŒณ ํ‚ค์›Œ๋“œ ์ตœ๋Œ€ํ•œ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ •๋ฆฌ, ์ถ”ํ›„์— ๋ณด๋ฉด์„œ ์Šค์Šค๋กœ ์„ค๋ช…

JavaScript ์ฝœ๋ฐฑ ํ•จ์ˆ˜

๋‹ค๋ฅธ ์ฝ”๋“œ์˜ ์ธ์ž๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ํ•จ์ˆ˜
์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋„˜๊ฒจ๋ฐ›์€ ์ฝ”๋“œ๋Š” ํ•„์š”์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ์‹œ์ ์— ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰(์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ œ์–ด๊ถŒ์„ ๋„˜๊ธฐ๋Š” ๊ฒƒ)

์ฝœ๋ฐฑ ํ•จ์ˆ˜ ์˜ˆ์‹œ

var count = 0;
var timer = setInterval(function () {
  console.log(count);
  if (++count > 4) clearInterval(timer);
}, 3000);

์ผ๋ฐ˜์ ์ธ ์ฝ”๋“œ๋Š” ์‚ฌ์šฉ์ž(์œ ์ €)๊ฐ€ ํ˜ธ์ถœ ์ฃผ์ฒด์ด๋ฉด์„œ ์ œ์–ด๊ถŒ์„ ๊ฐ€์ง€๋Š” ๋ฐ˜๋ฉด, ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ํŠน์ • ์ฝ”๋“œ์—๊ฒŒ ์ œ์–ด๊ถŒ์„ ๋„˜๊ฒจ์คŒ

์ฝœ๋ฐฑ ํ•จ์ˆ˜ ์˜ˆ์‹œ2

var newArr = [10, 20, 30].map(function (value, index) {
  console.log(value, index);
  return value + 5;
});

์œ„์™€ ๊ฐ™์ด ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ๋„˜๊ฒจ์ค˜์•ผํ•˜๋Š” ์ธ์ž๊ฐ€ ์ œ๊ฐ๊ฐ
์ œ์–ด๊ถŒ์„ ๊ฐ–๋Š” ํ•จ์ˆ˜ ํ˜น์€ ๋ฉ”์„œ๋“œ๊ฐ€ ์–ด๋–ค ์ธ์ž๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฐ›์•„์„œ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•˜๋Š”์ง€ ๊ผญ ํ™•์ธํ•ด์•ผํ•จ
๋˜ํ•œ, ์ผ๋ฐ˜์ ์œผ๋กœ thisArg๋ฅผ ์ƒ๋žตํ•  ๊ฒฝ์šฐ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ์ „์—ญ ๊ฐ์ฒด(window)๋ฅผ ๋ฐ”์ธ๋”ฉ

์˜ˆ์‹œ1์˜ setInterval, setTimeout์€ ์• ์ดˆ์— thisArg๋ฅผ ์ธ์ž๋กœ ๋„˜๊ฒจ์ค„ ์ˆ˜๋„ ์—†์Œ

์ฝœ๋ฐฑ ํ•จ์ˆ˜ ์˜ˆ์‹œ3

document.body.innerHTML += '<div id="jay">์•ˆ๋…•</div>';
document.body.querySelector('#jay').addEventListener('click', function (event) {
  console.log(this, event);
});

addEventListener์˜ ๊ฒฝ์šฐ, ์ž์ฒด์ ์œผ๋กœ this๋ฅผ ๊ทธ ์•ž์˜ ํ˜ธ์ถœ ์ฃผ์ฒด์ธ document.body.querySelector('#jay')์œผ๋กœ ๋ฐ”์ธ๋”ฉ

์ฝœ๋ฐฑ ํ•จ์ˆ˜๋„ ๊ฒฐ๊ตญ ํ•จ์ˆ˜

์–ด๋–ค ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋กœ์„œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋”๋ผ๋„ ๊ทธ ๋ฉ”์„œ๋“œ์˜ this binding๊ณผ๋Š” ๋ณ„๊ฐœ๋กœ ๊ทธ์ € ํ•จ์ˆ˜๋กœ์„œ ์ž‘๋™

var obj = {
  arr: [1, 2, 3],
  method: function (value, index) {
    console.log(this, value, index); // ๋ฉ”์„œ๋“œ๋กœ์„œ ํ˜ธ์ถœ ์‹œ this๋Š” obj ๊ฐ์ฒด๋ฅผ ๋ฐ”์ธ๋”ฉ
  },
}[(4, 5, 6)].forEach(obj.method); // this๋Š” ์ „์—ญ๊ฐ์ฒด๋ฅผ ๋ฐ”์ธ๋”ฉ(์ฝœ๋ฐฑ ํ•จ์ˆ˜์—์„œ ๋”ฐ๋กœ ์ง€์ •ํ•˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ)

// ์ฝœ๋ฐฑ ํ•จ์ˆ˜์— ์›ํ•˜๋Š” this ๋ฐ”์ธ๋”ฉํ•˜๊ธฐ

var arr2 = [4, 5, 6];
arr2.forEach(obj.method.bind(arr2)); // this์— arr2๊ฐ€ ๋ฐ”์ธ๋”ฉ๋จ

์ฝœ๋ฐฑ ์ง€์˜ฅ๊ณผ ๋น„๋™๊ธฐ ์ œ์–ด์˜ ๋ณ€์ฒœ์‚ฌ

  • ์ฝœ๋ฐฑ ์ง€์˜ฅ: ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ต๋ช… ํ•จ์ˆ˜๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ณผ์ •์ด ๋ฐ˜๋ณต๋˜๋ฉฐ ์ฝ”๋“œ์˜ ๋“ค์—ฌ์“ฐ๊ธฐ๊ฐ€ ๊ฐ๋‹นํ•˜๊ธฐ ํž˜๋“ค ์ •๋„๋กœ ๊นŠ์–ด์ง€๋Š” ํ˜„์ƒ
  • ๋น„๋™๊ธฐ ์ œ์–ด์˜ ๋ณ€์ฒœ์‚ฌ: setTimeout/setInterval -> Promise, Generator -> async/await

๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ JavaScript ํด๋กœ์ €

ํด๋กœ์ €๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฟ ์•„๋‹ˆ๋ผ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์—์„œ ๋“ฑ์žฅํ•˜๋Š” ๋ณดํŽธ์ ์ธ ํŠน์„ฑ
์–ด๋–ค ํ•จ์ˆ˜ A(์™ธ๋ถ€ํ•จ์ˆ˜)์—์„œ ์„ ์–ธํ•œ ๋ณ€์ˆ˜ a๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋‚ด๋ถ€ํ•จ์ˆ˜ B๋ฅผ ์™ธ๋ถ€๋กœ ์ „๋‹ฌํ•  ๊ฒฝ์šฐ, A์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋œ ์ดํ›„์—๋„ ๋ณ€์ˆ˜ a๊ฐ€ ์‚ฌ๋ผ์ง€์ง€ ์•Š๋Š” ํ˜„์ƒ

ํด๋กœ์ €์˜ ์ •์˜์—์„œ โ€˜๋‚ด๋ถ€ํ•จ์ˆ˜๋ฅผ ์™ธ๋ถ€๋กœ ์ „๋‹ฌํ•  ๊ฒฝ์šฐโ€™๊ฐ€ return๋งŒ ์žˆ๋Š” ๊ฒŒ ์•„๋‹˜ setInterval, addEventListener๊ณผ ๊ฐ™์€ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์‹œ์—๋„, ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ์™ธ๋ถ€๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒฝ์šฐ ํด๋กœ์ € ๋ฐœ์ƒ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ์™„์ „ํžˆ ์ข…๋ฃŒ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ, ๊ทธ ํ•จ์ˆ˜๋ฅผ ์ œ์–ดํ•˜๋Š” ํ•จ์ˆ˜์˜ ํŠน์ • ๋™์ž‘(์ผ์ • ์‹œ๊ฐ„๋งˆ๋‹ค, ํด๋ฆญ ์‹œ, ์Šคํฌ๋กค ์‹œ ๋“ฑ๋“ฑ)์— ๋”ฐ๋ผ ๊ณ„์† ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ์™ธ๋ถ€ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒฝ์šฐ ํด๋กœ์ €๊ฐ€ ๋ฐœ์ƒ

// ์˜ˆ์‹œ 1๋ฒˆ
var outer = function () {
  var a = 1;
  var inner = function () {
    console.log(++a);
  };
  return inner();
};

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

// ์˜ˆ์‹œ 2๋ฒˆ
var outer = function () {
  var a = 1;
  var inner = function () {
    console.log(++a);
  };
  return inner; // ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  ๊ทธ ํ•จ์ˆ˜ ์ž์ฒด๋ฅผ ๋ฆฌํ„ด
};

var outer2 = outer();
console.log(outer2()); // 2
console.log(outer2()); // 3

์˜ˆ์‹œ 1๋ฒˆ: inner๊ฐ€ ์‹คํ–‰๋˜๊ณ  ๋ฆฌํ„ด๋จ์œผ๋กœ์จ inner์˜ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด์„œ outer์˜ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋Œ€์ƒ์ด ์—†์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๋น„์ง€ ์ฝœ๋ ‰ํ„ฐ์— ์˜ํ•ด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ฒ˜๋ฆฌ๋จ

์˜ˆ์‹œ 2๋ฒˆ: inner๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š๊ณ  ๋ฆฌํ„ด๋จ์œผ๋กœ์จ, inner์˜ ์ปจํ…์ŠคํŠธ(outerEnvironmentReferece)๋Š” outer์˜ ์ปจํ…์ŠคํŠธ(LexicalEnvironment)๋ฅผ ์ฐธ์กฐํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ outer์˜ ๋ณ€์ˆ˜๊ฐ€ ๊ฐ€๋น„์ง€ ์ฝœ๋ ‰ํ„ฐ์— ์˜ํ•œ ์ œ๊ฑฐ ๋Œ€์ƒ์— ์žˆ์ง€ ์•Š์Œ

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

ํด๋กœ์ € ํ˜„์ƒ์œผ๋กœ ๋ฐœ์ƒํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์†Œ๋ชจ๋Š” ๊ทธ์ € ํด๋กœ์ €์˜ ๋ณธ์งˆ์ ์ธ ํŠน์„ฑ
๊ฐœ๋ฐœ์ž์˜ ์˜๋„์™€ ๋‹ฌ๋ฆฌ ์–ด๋–ค ๊ฐ’์˜ ์ฐธ์กฐ ์นด์šดํŠธ๊ฐ€ 0์ด ๋˜์ง€ ์•Š์•„์„œ ๊ฐ€๋น„์ง€ ์ฝœ๋ ‰ํ„ฐ์˜ ์ˆ˜๊ฑฐ ๋Œ€์ƒ์ด ๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ํด๋กœ์ €๋Š” ์˜๋„์ ์œผ๋กœ ์ฐธ์กฐ ์นด์šดํŠธ๋ฅผ 0์ด ๋˜๊ฒŒ ํ•˜์ง€ ์•Š์Œ์œผ๋กœ์จ ์™ธ๋ถ€ ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด๊ธฐ์— ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์—†์Œ

๊ทธ๋Ÿฌ๋ฏ€๋กœ ํด๋กœ์ €์˜ ํ•„์š”์„ฑ์ด ๋๋‚ฌ๋‹ค๋ฉด, ๊ทธ์ € ๊ทธ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋น„์›Œ์ฃผ๋Š” ์ž‘์—…์„ ํ•ด์ฃผ๋ฉด ํ•ด๊ฒฐ

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

console.log(outer());
console.log(outer());
console.log(outer());
// ์ด์ œ ํด๋กœ์ €๋ฅผ ์ด์šฉํ•  ์ผ์ด ์—†๋‹ค๋ฉด

outer = null;
// outer ์‹๋ณ„์ž์˜ inner ํ•จ์ˆ˜ ์ฐธ์กฐ๋ฅผ ๋Š์–ด๋ฒ„๋ฆฌ๋ฉด ๋”์ด์ƒ inner๊ฐ€ ํ˜ธ์ถœ๋  ์ผ์ด ์—†๊ณ 
// ๊ทธ์— ๋”ฐ๋ผ ์™ธ๋ถ€ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜ a๋ฅผ ์ฐธ์กฐํ•  ์ผ์ด ์—†๊ฒŒ ๋˜๋ฏ€๋กœ ๊ฐ€๋น„์ง€ ์ฝœ๋ ‰ํ„ฐ์— ์˜ํ•ด ์ œ๊ฑฐ๋จ