๐Ÿ“‹ ๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Deep Dive | 26์žฅ ES6 ํ•จ์ˆ˜์˜ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ

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

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

26.1 ํ•จ์ˆ˜์˜ ๊ตฌ๋ถ„

ES6 ์ด์ „์˜ ๋ชจ๋“  ํ•จ์ˆ˜๋Š” ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ๋ฌผ๋ก  ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹ค์‹œ ๋งํ•ด, ES6 ์ด์ „์˜ ๋ชจ๋“  ํ•จ์ˆ˜๋Š” callable์ด๋ฉด์„œ contructor์ด๋‹ค.

var foo = function () {}

foo() // undefined
new foo() // foo {}

๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ๋œ ํ•จ์ˆ˜๋„ callable์ด๋ฉด์„œ contructor์ด๋‹ค.

์‚ฌ์šฉ ๋ชฉ์ ์— ๋”ฐ๋ฅธ ํ•จ์ˆ˜ ๊ตฌ๋ถ„

ES6 ํ•จ์ˆ˜์˜ ๊ตฌ๋ถ„contructorprototypesuperarguments
์ผ๋ฐ˜ ํ•จ์ˆ˜(Normal)OOXO
๋ฉ”์„œ๋“œ(Method)XXOO
ํ™”์‚ดํ‘œ ํ•จ์ˆ˜(Arrow)XXXX

26.2 ๋ฉ”์„œ๋“œ

ES6 ์‚ฌ์–‘์—์„œ ๋ฉ”์„œ๋“œ๋Š” ๋ฉ”์„œ๋“œ ์ถ•์•ฝ ํ‘œํ˜„์œผ๋กœ ์ •์˜๋œ ํ•จ์ˆ˜๋งŒ์„ ์˜๋ฏธํ•œ๋‹ค.

const obj = {
  x: 1,
  // foo๋Š” ๋ฉ”์„œ๋“œ
  foo() { return this.x; }
  // bar์— ๋ฐ”์ธ๋”ฉ๋œ ํ•จ์ˆ˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹Œ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋‹ค.
  bar: function() {
    return this.x;
  }
}

new obj.foo() // obj.foo is not a constructor
new obj.bar() // bar {}

ES6์—์„œ ์ •์˜ํ•œ ๋ฉ”์„œ๋“œ๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๋Š” non-constructor๋‹ค.

๊ทธ๋ฆฌ๊ณ  ES6 ๋ฉ”์„œ๋“œ๋Š” ์ž์‹ ์„ ๋ฐ”์ธ๋”ฉํ•œ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋‚ด๋ถ€ ์Šฌ๋กฏ [[HomeObject]]๋ฅผ ๊ฐ–๋Š”๋‹ค. super ์ฐธ์กฐ๋Š” ๋‚ด๋ถ€ ์Šฌ๋กฏ [[HomeObject]]๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜ํผํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ฐธ์กฐํ•˜๋ฏ€๋กœ ๋‚ด๋ถ€ ์Šฌ๋กฏ [[HomeObject]]๋ฅผ ๊ฐ–๋Š” ES6 ๋ฉ”์„œ๋“œ๋Š” super ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

// 26-09
const base = {
  name: 'Lee',
  sayHi() {
    return `Hi ${this.name}`
  }
}

const derived = {
  __proto__: base,
  // sayHi๋Š” ES6 ๋ฉ”์„œ๋“œ์ด๊ธฐ ๋•Œ๋ฌธ์— [[HomeObject]]๋ฅผ ์ง„๋‹ค.
  // sayHi์˜ [[HomeObject]]๋Š” sayHi๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ ๊ฐ์ฒด์ธ derived๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ 
  // super๋Š” sayHi์˜ [[HomeObject]]์˜ ํ”„๋กœํ† ํƒ€์ž…์ธ base๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
  sayHi() {
    return `${super.sayHi()}. how are you doing?`
  }
}

console.log(derived.sayHi()) // Hi! Lee. how are you doing?

26.3 ํ™”์‚ดํ‘œ ํ•จ์ˆ˜

ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” function ํ‚ค์›Œ๋“œ ๋Œ€์‹  ํ™”์‚ดํ‘œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ์กด์˜ ํ•จ์ˆ˜ ์ •์˜ ๋ฐฉ์‹๋ณด๋‹ค ๊ฐ„๋žตํ•˜๊ฒŒ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

26.3.1 ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ์ •์˜

// ํ•จ์ˆ˜ ์ •์˜
const multiply = (x, y) => x * y
multiply(2,3) // 6

// ๋งค๊ฐœ๋ณ€์ˆ˜ ์„ ์–ธ
const arrow = (x, y) => { ... }
const arrow = x => { ... }
const arrow = () => { ... }

// ํ•จ์ˆ˜ ๋ชธ์ฒด ์ •์˜
const power = x => x ** 2
power(2) // 4
const arrow = () => {
  const x = 1
}

// ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ๋ฐ˜ํ™˜
const create = (id, content) => ({ id, content })

// ์ฆ‰์‹œ ์‹คํ–‰ ํ•จ์ˆ˜
const person = (name = > ({
  sayHi() {
    return `Hi~ ${name}` 
  }
}))('Lee')

// ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋„ ์ผ๊ธ‰ ๊ฐ์ฒด์ด๋ฏ€๋กœ map, filter, reduce์— ์ธ์ˆ˜๋กœ ์ „๋‹ฌ ๊ฐ€๋Šฅ
[1, 2, 3].map(v => v * 2)

26.3.2 ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์™€ ์ผ๋ฐ˜ ํ•จ์ˆ˜์˜ ์ฐจ์ด

  1. ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๋Š” non-contructor๋‹ค.
  2. ์ค‘๋ณต๋œ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„์„ ์„ ์–ธํ•  ์ˆ˜ ์—†๋‹ค.
  3. ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” ํ•จ์ˆ˜ ์ž์ฒด์˜ this, arguments, super, new.target ๋ฐ”์ธ๋”ฉ์„ ๊ฐ–์ง€ ์•Š๋Š”๋‹ค.

26.3.3 this

ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๊ฐ€ ์ผ๋ฐ˜ ํ•จ์ˆ˜์™€ ๊ตฌ๋ณ„๋˜๋Š” ๊ฐ€์žฅ ํฐ ํŠน์ง•์€ this์ด๋‹ค. ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” ๋‹ค๋ฅธ ํ•จ์ˆ˜์˜ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋˜์–ด ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

*ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ป๊ฒŒ ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€์— ๋”ฐ๋ผ this์— ๋ฐ”์ธ๋”ฉํ•  ๊ฐ์ฒด๊ฐ€ ๋™์ ์œผ๋กœ ๊ฒฐ์ •๋œ๋‹ค.

class Prefixer {
  constructor(prefix) {
    this.prefix = prefix
  }
  
  add(arr) {
    // ์ด ์žฅ์†Œ์—์„œ this๋Š” prefix๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
    return arr.map(function (item) {
      // ์—ฌ๊ธฐ์„œ this๋Š” undefined๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
      return this.prefix + item
      // TypeError: Cannot read property 'prefix' of undefined
    })
  }
}

const prefixer = new Prefixer('-webkit-')
console.log(prefixer.add(['transition','user-select']))

์œ„์˜ ๋ฌธ์ œ๋ฅผ ES6์—์„œ๋Š” ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ "์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this ๋ฌธ์ œ"๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

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

26.3.4 super

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

super

  • [[HomeObject]]๋ฅผ ๊ฐ–๋Š” ES6 ๋ฉ”์„œ๋“œ ๋‚ด์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ‚ค์›Œ๋“œ

26.3.5 arguments

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

(function() {
  const foo = () =>  console.log(arguments) // [Arguments] { '0': 1, '1': 2}
  ๋ž˜ใ…(3, 4)
}(1, 2)
 
const foo = () => console.log(arguments)
foo(1, 2) // ReferenceError: arguments is not defined

26.4 Rest ํŒŒ๋ผ๋ฏธํ„ฐ

26.4.2 Rest ํŒŒ๋ผ๋ฏธํ„ฐ์™€ arguments ๊ฐ์ฒด

arguments ๊ฐ์ฒด๋Š” ๋ฐฐ์—ด์ด ์•„๋‹Œ ์œ ์‚ฌ ๋ฐฐ์—ด ๊ฐ์ฒด์ด๋ฏ€๋กœ ๋ฐฐ์—ด ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Function.prototype.call์ด๋‚˜ Function.prototype.apply ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด arguments ๊ฐ์ฒด๋ฅผ ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ์žˆ์—ˆ๋‹ค.

function sum(...args) {
  // args๋ฅผ rest ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฐ์—ด๋กœ ์ง์ ‘ ๋ฐ›์•„์„œ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ€๋Šฅํ•˜๋‹ค.
  var array = Array.prototype.slice.call(arguments)
  
  return array.reduce((pre, cur) => pre + cur, 0)
}

26.5 ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ธฐ๋ณธ๊ฐ’

์ธ์ˆ˜๊ฐ€ ์ „๋‹ฌ๋˜์ง€ ์•Š์€ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ฐ’์€ undefined์ด๋‹ค.

ES6์—์„œ ๋„์ž…๋œ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜ ๋‚ด์—์„œ ์ˆ˜ํ–‰ํ•˜๋˜ ์ธ์ˆ˜ ์ฒดํฌ ๋ฐ ์ดˆ๊ธฐํ™”๋ฅผ ๊ฐ„์†Œํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

function sum(x = 0, y = 0) {
  return x + y
}

console.log(sum(1, 2)) // 3
console.log(sum(1)) //1

*rest ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ๊ธฐ๋ณธ๊ฐ’์„ ์ง€์ •ํ•  ์ˆ˜ ์—†๋‹ค.

Ref

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

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