# ํ™”์‚ดํ‘œ ํ•จ์ˆ˜(Arrow Function)

ํ™”์‚ดํ‘œ ํ•จ์ˆ˜(Arrow Function)๋Š” ES6์˜ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜ ์ •์˜ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

# ๊ธฐ์กด์˜ ํ•จ์ˆ˜ ์ •์˜ ๋ฐฉ์‹

๊ธฐ์กด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํ•จ์ˆ˜ ์ •์˜ ๋ฐฉ์‹์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

var a = function() {
  // ...
};

# ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ ํ•จ์ˆ˜ ์ •์˜

ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ ํ•จ์ˆ˜ ์ •์˜ ๋ฐฉ์‹์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

var a = () => {
  // ...
};

# ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์˜ ๋‹ค์–‘ํ•œ ๋ฌธ๋ฒ•

ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐฉ์‹์€ ๊ฐ„๋‹จํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ‘œํ˜„์‹๋ถ€ํ„ฐ {} ๋ฅผ ์ด์šฉํ•œ ์„ ์–ธ ๋ฐฉ์‹๊นŒ์ง€ ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

# 1. ๋‹จ์ˆœํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ‘œํ˜„์‹

๋‹จ์ˆœํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ‘œํ˜„์‹์˜ ๊ฒฝ์šฐ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ„์†Œํ™” ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

() => 10 + 20; // {} ํ•„์š” ์—†์Œ

# 2. ํ•จ์ˆ˜ ์„ ์–ธ ๋ฐฉ์‹

๋ณต์žกํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์„ ์–ธ๋ฌธ์ด ๋“ค์–ด๊ฐˆ ๊ฒฝ์šฐ์—๋Š” {}๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

() => {
  print();
  log();
  return 10 + 20;
};

# 3. ์ „๋‹ฌ ์ธ์ž(parameter)๊ฐ€ ํ•˜๋‚˜์ธ ๊ฒฝ์šฐ

์ธ์ž๋ฅผ 1๊ฐœ๋งŒ ์„ ์–ธํ•˜๋Š” ๊ฒฝ์šฐ ์ธ์ž๋ฅผ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์†Œ๊ด„ํ˜ธ() ๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const a = num => {
  return num * 10;
};
const b = num => num * 10;
a(10); // 100
b(10); // 100

# this ๋ฐ”์ธ๋”ฉ์˜ ๋ณ€ํ™”

ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์—์„œ ์‚ฌ์šฉ๋˜๋Š” this ๋ฐ”์ธ๋”ฉ์€ ๊ธฐ์กด ํ•จ์ˆ˜์˜ this (opens new window)์™€ ๋‹ค๋ฅธ ๋ฐฉ์‹์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์˜ this๋Š” ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•  ๋•Œ์˜ ์ƒ์œ„ ์Šค์ฝ”ํ”„์˜ this๋กœ ๋ฐ”์ธ๋”ฉ ๋  ๊ฐ์ฒด๊ฐ€ ์ •ํ•ด์ง‘๋‹ˆ๋‹ค.

์•„๋ž˜๋Š” ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์˜ this๋ฅผ ๋‚˜ํƒ€๋‚ธ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. innerFunc์˜ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋Š” printThis์ด๊ธฐ ๋•Œ๋ฌธ์— printThis์˜ ๋‚ด๋ถ€ this์™€ innerFunc์˜ ๋‚ด๋ถ€ this๋Š” ๊ฐ™์€ ๊ฐ’์œผ๋กœ ๋ฐ”์ธ๋”ฉ ๋ฉ๋‹ˆ๋‹ค.

const foo = {
  name: "bar",
  age: 10000,
  printThis() {
    console.log(this); // {name: "bar", age: 10000, printThis: ฦ’}
    const innerFunc = () => {
      return this; // {name: "bar", age: 10000, printThis: ฦ’}
    };
    console.log(innerFunc());
  }
};

foo.printThis();

# setTimeout์—์„œ์˜ this

์ผ๋ฐ˜ ํ•จ์ˆ˜์—์„œ setTimeout์—์„œ์˜ this๋Š” window๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์—์„œ๋Š” ์ƒ์œ„ ์Šค์ฝ”ํ”„์˜ this๋กœ ๊ฐ’์ด ๋ฐ”์ธ๋”ฉ ๋ฉ๋‹ˆ๋‹ค.

const foo = {
  name: "bar",
  age: 10000,
  getThisArrowFunc: function() {
    console.log(this); // {name: "bar", age: 10000, getThisArrowFunc: ฦ’}
    setTimeout(() => {
      console.log(this); // {name: "bar", age: 10000, getThisArrowFunc: ฦ’}
    }, 1000);
  },

  getThisFunc: function() {
    console.log(this); // {name: "bar", age: 10000, getThisFunc: ฦ’}
    setTimeout(function() {
      console.log(this); // window
    }, 1000);
  }
};

foo.getThisArrowFunc();
foo.getThisFunc();

๊ทธ๋Ÿฌ๋‚˜ ์—„๊ฒฉ๋ชจ๋“œ('use strict') ์ผ๋•Œ๋Š” ๋ฐ”์ธ๋”ฉ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

"use strict";
(function() {
  setTimeout(() => {
    console.log(this); // undefined
  }, 1000);
})();

# addEventListener์—์„œ์˜ this

addEventListener ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ๋„ฃ์œผ๋ฉด this๋Š” ์ƒ์œ„ ์Šค์ฝ”ํ”„์˜ this๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค.

const button = document.getElementById("this-button");
button.innerText = "ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ฒ„ํŠผ";

button.addEventListener("click", () => {
  console.log(this === window); // true
  console.log(this.innerText); // undefined
});

๊ทธ๋ž˜์„œ addEventListener ํ•จ์ˆ˜์—์„œ this๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๊ฐ€ ์•„๋‹Œ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ์ •์˜๋œ addEventListener ํ•จ์ˆ˜์˜ this๋Š” currentTarget์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค.

const button = document.getElementById("this-button");
button.innerText = "ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ฒ„ํŠผ";

button.addEventListener("click", function() {
  console.log(this === button); // true
  console.log(this.innerText); // ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ฒ„ํŠผ
});

addEventListener ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ์•ˆ์—์„œ ์‚ฌ์šฉ๋˜๋Š” this๋Š” class๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. ์•„๋ž˜ ์˜ˆ์‹œ ์ฝ”๋“œ๋ฅผ ์ฐธ์กฐํ•ด์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

class Foo {
  constructor() {
    this.name = "bar";
  }
  register() {
    window.addEventListener("keydown", e => this.someMethod(e));
  }
  someMethod(event) {
    console.log(this.name); // bar
    console.log(event.keyCode); // Enter key๋ฅผ ๋ˆ„๋ฅด๋ฉด 63
  }
}

const baz = new Foo();
baz.register();

# call, bind, apply๋กœ ๋ฐ”์ธ๋”ฉ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€

ํ•œ๊ฐ€์ง€ ์ฃผ์˜ํ•˜์‹ค ์ ์€ ์ผ๋ฐ˜ ํ•จ์ˆ˜์˜ this์™€ ๋‹ค๋ฅด๊ฒŒ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์—์„œ์˜ this๋Š” call, bind, apply ๋ฉ”์†Œ๋“œ๋กœ this์— ๋ฐ”์ธ๋”ฉ ๋œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

this.foo = "bar";
const normalFunc = function() {
  return this.foo;
};
const arrowFunc = () => this.foo;

console.log(normalFunc.call({ foo: "baz" })); // baz
console.log(arrowFunc.call({ foo: "baz" })); // bar

# ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉ ๋ถˆ๊ฐ€

ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

const Foo = () => {};
const foo = new Foo(); // Uncaught TypeError: Foo is not a constructor