λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
javascript/πŸ“– study

[5μ£Όμ°¨ μŠ€ν„°λ””]26μž₯-ES6 ν•¨μˆ˜ μΆ”κ°€ κΈ°λŠ₯

by HomieKim 2022. 3. 27.

ES6 ν•¨μˆ˜μ˜ μΆ”κ°€ κΈ°λŠ₯

ν•¨μˆ˜μ˜ ꡬ뢄

  • es6 μ΄μ „μ˜ ν•¨μˆ˜λŠ” μ‚¬μš© λͺ©μ μ— 따라 λͺ…ν™• ν•˜κ²Œ ꡬ뢄 λ˜μ§€ μ•ŠμŒ

    • 일반 ν•¨μˆ˜λ‘œμ„œ 호좜 κ°€λŠ₯
    • newμ—°μ‚°μžμ™€ ν•¨κ»˜ ν˜ΈμΆœν•˜μ—¬ μƒμ„±μž ν•¨μˆ˜λ‘œ 호좜 κ°€λŠ₯
    • 객체에 바인딩 λ˜μ–΄ λ©”μ„œλ“œλ‘œμ„œ 호좜 κ°€λŠ₯
  • 즉, es6μ΄μ „μ˜ λͺ¨λ“  ν•¨μˆ˜λŠ” 일반 ν•¨μˆ˜, μƒμ„±μž ν•¨μˆ˜ λ‘˜λ‹€ 호좜 κ°€λŠ₯

    es6μ΄μ „μ˜ λͺ¨λ“  ν•¨μˆ˜λŠ” callable μ΄λ©΄μ„œ constructor 이닀

  • μ‹€μˆ˜λ₯Ό μœ λ°œν•  수 있으며 μ„±λŠ₯ λ©΄μ—μ„œλ„ 손해

  • μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ es6μ—μ„œλŠ” ν•¨μˆ˜λ₯Ό μ‚¬μš© λͺ©μ μ— 따라 μ„Έ 가지 μ’…λ₯˜λ‘œ λͺ…ν™•νžˆ ꡬ뢄

ES6 ν•¨μˆ˜μ˜ ꡬ뢄 constructor prototype super arguments
일반 ν•¨μˆ˜(Normal, ES6 이전 ν•¨μˆ˜) O O X O
λ©”μ„œλ“œ(Method) X X O O
ν™”μ‚΄ν‘œ(Arrow) X X X X
  • 일반 ν•¨μˆ˜λŠ” ν•¨μˆ˜ μ„ μ–Έλ¬Έμ΄λ‚˜ ν‘œν˜„μ‹μœΌλ‘œ μ •μ˜ν•œ ν•¨μˆ˜ (μ΄μ „μ˜ ν•¨μˆ˜μ™€ 동일)
  • λ©”μ„œλ“œμ™€ ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” μ΄μ „μ˜ ν•¨μˆ˜μ™€ λͺ…ν™•ν•œ 차이 쑴재

    일반 ν•¨μˆ˜λŠ” constructorμ΄μ§€λ§Œ es6의 λ©”μ„œλ“œμ™€ ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” non-constructor 이닀.

λ©”μ„œλ“œ

  • es6 μ‚¬μ–‘μ—μ„œ λ©”μ„œλ“œλŠ” λ©”μ„œλ“œ μΆ•μ•½ ν‘œν˜„μœΌλ‘œ μ •μ˜λœ ν•¨μˆ˜λ§Œμ„ 의미
// ES5 
var obj = {
     name: 'Lee', 
     sayHi: function() { 
         console.log('Hi! ' + this.name); 
        } 
};
/*------------------------------------------------------ */
// ES6 
const obj = { 
    name: 'Lee', 
    // λ©”μ†Œλ“œ μΆ•μ•½ ν‘œν˜„ 
    sayHi() {
     console.log('Hi! ' + this.name); 
    } 
}; 
  • es6의 λ©”μ„œλ“œλŠ” μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 μ—†λŠ” non-constructor
  • ES6 λ©”μ„œλ“œλŠ” μžμ‹ μ„ λ°”μΈλ”©ν•œ 객체λ₯Ό κ°€λ¦¬ν‚€λŠ” λ‚΄λΆ€ 슬둯 [[HomeObject]]λ₯Ό 가짐.
  • super μ°Έμ‘°λŠ” λ‚΄λΆ€ 슬둯 [[HomeObject]]λ₯Ό μ‚¬μš©ν•˜μ—¬ 수퍼 클래슀의 λ©”μ„œλ“œλ₯Ό μ°Έμ‘°ν•˜λ―€λ‘œ, [[HomeObject]]λ₯Ό κ°–λŠ” ES6 λ©”μ„œλ“œλŠ” super ν‚€μ›Œλ“œλ₯Ό μ‚¬μš© κ°€λŠ₯.

ν™”μ‚΄ν‘œ ν•¨μˆ˜

  • 콜백 ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ thisκ°€ μ „μ—­ 객체λ₯Ό κ°€λ¦¬ν‚€λŠ” 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•œ λŒ€μ•ˆμœΌλ‘œ μœ μš©ν•˜λ‹€.
  • ν•¨μˆ˜ ν‘œν˜„μ‹μœΌλ‘œ μ •μ˜ν•΄μ•Ό ν•œλ‹€.
  • ν•¨μˆ˜ λͺΈμ²΄κ°€ ν•˜λ‚˜μ˜ 문으둜 κ΅¬μ„±λœλ‹€λ©΄ ν•¨μˆ˜ λͺΈμ²΄λ₯Ό κ°μ‹ΈλŠ” μ€‘κ΄„ν˜Έ {}λ₯Ό μƒλž΅ν•  수 μžˆλ‹€.
const power = x => x ** 2;
power(2); // 4

이 λ•Œ ν•¨μˆ˜ λͺΈμ²΄ λ‚΄λΆ€μ˜ 문이 평가 될 수 μžˆλ‹€λ©΄ μ•”λ¬΅μ μœΌλ‘œ λ°˜ν™˜, ν‘œν˜„μ‹μ΄ μ•„λ‹Œ 문이라면 λ°˜ν™˜ ν•  수 μ—†κΈ° λ•Œλ¬Έμ— μ—λŸ¬

  • ν•¨μˆ˜ λͺΈμ²΄μ˜ 문이 ν‘œν˜„μ‹μ΄ μ•„λ‹Œ 문이라면 μ€‘κ΄„ν˜Έ μƒλž΅ λͺ»ν•¨
  • 객체 λ¦¬ν„°λŸ΄ λ°˜ν™˜ν•˜λŠ” 경우 μ†Œκ΄„ν˜Έλ‘œ ()감싸 μ£Όμ–΄μ•Ό ν•œλ‹€.
  • ν™”μ‚΄ν‘œ ν•¨μˆ˜λ„ 일급 객체 μ΄λ―€λ‘œ κ³ μ°¨ ν•¨μˆ˜(Higher-Order Function, HOF)에 인수둜 전달할 수 μžˆλ‹€.
[1,2,3].map(v => v * 2); // [ 2, 4, 6]
  • ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” μ½œλ°±ν•¨μˆ˜λ‘œ μ •μ˜ν•  λ•Œ 유용
  • 일반 ν•¨μˆ˜μ˜ κΈ°λŠ₯을 κ°„λž΅ν™” ν–ˆμœΌλ©°, this도 νŽΈλ¦¬ν•˜κ²Œ μ„€κ³„λ˜μ—ˆλ‹€.

ν™”μ‚΄ν‘œ ν•¨μˆ˜μ™€ 일반 ν•¨μˆ˜μ˜ 차이

  1. ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 μ—†λŠ” non-constructor이닀.
const Foo = () => {};
// ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” μƒμ„±μž ν•¨μˆ˜λ‘œ 호좜 ν•  수 μ—†λ‹€.
new Foo(); // TypeError : Foo is not constructor

μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 μ—†μœΌλ―€λ‘œ prototype ν”„λ‘œνΌν‹°κ°€ μ—†κ³  ν”„λ‘œν† νƒ€μž…λ„ μƒμ„±ν•˜μ§€ μ•ŠλŠ”λ‹€.

  1. μ€‘λ³΅λœ λ§€κ°œλ³€μˆ˜ 이름을 μ„ μ–Έ ν•  수 μ—†λ‹€.

    • 일반 ν•¨μˆ˜λŠ” μ€‘λ³΅λœ λ§€κ°œλ³€μˆ˜ 이름을 선언해도 μ—λŸ¬ x (strict mode μ—μ„œλŠ” μ—λŸ¬)
  2. ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν•¨μˆ˜ 자체의 this, arguments, super, new.target 바인딩을 갖지 μ•ŠλŠ”λ‹€.

    • ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ this, arguments, super, new.target을 μ°Έμ‘°ν•˜λ©΄ μƒμœ„ μŠ€μ½”ν”„μ˜ this, arguments, super, new.targetλ₯Ό μ°Έμ‘°
    • ν™”μ‚΄ν‘œ ν•¨μˆ˜κ°€ 쀑첩 λ˜μ–΄μžˆλ‹€λ©΄ μƒμœ„ ν•¨μˆ˜ μ€‘μ—μ„œ ν™”μ‚΄ν‘œ ν•¨μˆ˜κ°€ μ•„λ‹Œ ν•¨μˆ˜μ˜ this, arguments, super, new.targetλ₯Ό μ°Έμ‘°

this

ν™”μ‚΄ν‘œ ν•¨μˆ˜κ°€ 일반 ν•¨μˆ˜μ™€ κ΅¬λ³„λ˜λŠ” κ°€μž₯ 큰 νŠΉμ§•μ€ this
ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” λ‹€λ₯Έ ν•¨μˆ˜μ˜ 인수둜 μ „λ‹¬λ˜μ–΄ 콜백 ν•¨μˆ˜λ‘œ μ‚¬μš©λ˜λŠ” κ²½μš°κ°€ λ§Žλ‹€.

  • 일반 ν•¨μˆ˜μ˜ this와 λ‹€λ₯΄κ²Œ λ™μž‘ν•˜λŠ” 이유 : "콜백 ν•¨μˆ˜ λ‚΄λΆ€μ˜ this 문제"λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄

    콜백 ν•¨μˆ˜ λ‚΄λΆ€μ˜ thisκ°€ μ™ΈλΆ€ ν•¨μˆ˜μ˜ this와 λ‹€λ₯΄κΈ° λ•Œλ¬Έμ— 문제 λ°œμƒ
    thisλŠ” ν•¨μˆ˜κ°€ μ–΄λ–»κ²Œ 호좜 λ˜λŠ” 지에 따라 바인딩 될 객체가 λ™μ μœΌλ‘œ κ²°μ • 됨

class Prefixer {
  constructor(prefix) {
    this.prefix = prefix; // thisλŠ” 생성할 μΈμŠ€ν„΄μŠ€μ— 바인딩
  }

  add(arr) {
    return arr.map(function (item) {
      // 콜백 ν•¨μˆ˜ λ‚΄λΆ€μ˜ thisλŠ” undefined
      // 클래슀 λ‚΄λΆ€λŠ” strict mode, strict modeμ—μ„œ 일반 ν•¨μˆ˜ 호좜 μ‹œ μ „μ—­ 객체 μ•„λ‹ˆλΌ undefined에 this 바인딩됨
      return this.prefix + item; 
    });
  }
}

const prefixer = new Prefixer('-webkit-');
prefixer.add([])// μ—¬κΈ°μ„œ this 바인딩됨
// μƒμ„±μž λ‚΄λΆ€ thisλŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•œ 객체(prefixer)에 바인딩됨
  • es6 μ΄μ „μ˜ ν•΄κ²° 방법
  1. thisλ₯Ό νšŒν”Ό μ‹œν‚¨ 후에 μ½œλ°±ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μ‚¬μš©
add(arr) {
  // thisλ₯Ό 일단 νšŒν”Όμ‹œν‚¨λ‹€, μ—¬κΈ°μ„œλŠ” thisκ°€ ν˜ΈμΆœν•œ 객체 가리킴
  const that = this;
  return arr.map(function (item) {
    // this λŒ€μ‹  that을 μ°Έμ‘°ν•œλ‹€.
    return that.prefix + ' ' + item;
  });
}
  1. map의 λ‘λ²ˆμ§Έ 인수둜 this전달
add(arr) {
  return arr.map(function (item) {
    return this.prefix + ' ' + item;
  }, this); // this에 λ°”μΈλ”©λœ 값이 콜백 ν•¨μˆ˜ λ‚΄λΆ€μ˜ this에 λ°”μΈλ”©λœλ‹€.
}
  1. bind λ©”μ„œλ“œ μ‚¬μš©
add(arr) {
  return arr.map(function (item) {
    return this.prefix + ' ' + item;
  }.bind(this)); // this에 λ°”μΈλ”©λœ 값이 콜백 ν•¨μˆ˜ λ‚΄λΆ€μ˜ this에 λ°”μΈλ”©λœλ‹€.
}
  • es6μ—μ„œλŠ” ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 문제 ν•΄κ²°
arr(arr) {
    return arr.map(item => this.prefix + item);
}
  • ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν•¨μˆ˜ 자체의 this 바인딩을 갖지 μ•ŠλŠ”λ‹€.
  • ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ this μ°Έμ‘°ν•˜λ©΄ μƒμœ„ μŠ€μ½”ν”„μ˜ thisλ₯Ό κ·ΈλŒ€λ‘œ μ°Έμ‘° 이λ₯Ό lexical this 라고 ν•œλ‹€.

    마치 lexical scope 처럼 ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ˜ thisλŠ” ν•¨μˆ˜κ°€ μ •μ˜λœ μœ„μΉ˜μ— μ˜ν•΄ κ²°μ • 됨

  • λ§Œμ•½ ν™”μ‚΄ν‘œ ν•¨μˆ˜κ°€ μ „μ—­ ν•¨μˆ˜λΌλ©΄ thisλŠ” μ „μ—­ 객체 가리킨닀. (μƒμœ„ μŠ€μ½”ν”„ 따라)
  • ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” 자체의 this 바인딩을 갖지 μ•ŠκΈ° λ•Œλ¬Έμ— Function.prototype.call, bind, apply λ©”μ„œλ“œ μ‚¬μš©ν•΄λ„ λ‚΄λΆ€μ˜ this ꡐ체 λΆˆκ°€λŠ₯
  • 클래슀 ν•„λ“œμ— ν• λ‹Ήν•œ ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν”„λ‘œν† νƒ€μž… λ©”μ„œλ“œκ°€ μ•„λ‹ˆλΌ μΈμŠ€ν„΄μŠ€μ˜ λ©”μ„œλ“œκ°€ 됨 => λ©”μ„œλ“œ μ •μ˜μ‹œμ—λŠ” λ©”μ„œλ“œ μΆ•μ•½ ν‘œν˜„ ꢌμž₯

Rest νŒŒλΌλ―Έν„°

  • Rest νŒŒλ¦¬λ―Έν„°(λ‚˜λ¨Έμ§€ λ§€κ°œλ³€μˆ˜)λŠ” λ§€κ°œλ³€μˆ˜ μ΄λ¦„μ•žμ— μ„Έκ²Œμ˜ 점 ...을 λΆ™μ—¬ μ •μ˜ν•œ λ§€κ°œλ³€μˆ˜λ₯Ό 의미
  • Rest νŒŒλΌλ―Έν„°λŠ” ν•¨μˆ˜μ— μ „λ‹¬λœ μΈμˆ˜λ“€μ˜ λͺ©λ‘μ„ λ°°μ—΄λ‘œ λ°›λŠ”λ‹€.
function foo(...rest) {
  // λ§€κ°œλ³€μˆ˜ restλŠ” μΈμˆ˜λ“€μ˜ λͺ©λ‘μ„ λ°°μ—΄λ‘œ μ „λ‹¬λ°›λŠ” Rest νŒŒλΌλ―Έν„°λ‹€.
  console.log(rest); // [ 1, 2, 3, 4, 5 ]
}

foo(1, 2, 3, 4, 5);
  • Rest νŒŒλΌλ―Έν„°λŠ” 일반 맀개 λ³€μˆ˜μ™€ ν•¨κ»˜ μ‚¬μš©ν•  수 μžˆμœΌλ‚˜ λ°˜λ“œμ‹œ λ§ˆμ§€λ§‰μ— μ™€μ•Όν•œλ‹€.
  • Rest νŒŒλΌλ―Έν„°λŠ” 단 ν•˜λ‚˜λ§Œ μ„ μ–Έκ°€λŠ₯
function foo(param, ...rest) {
  console.log(param); // 1
  console.log(rest);  // [ 2, 3, 4, 5 ]
}

foo(1, 2, 3, 4, 5);
  • ν•¨μˆ˜ 객체의 length ν”„λ‘œνΌν‹°μ— 영ν–₯ x
function foo(...rest) {}
console.log(foo.length); // 0

function bar(x, ...rest) {}
console.log(bar.length); // 1

Rest νŒŒλΌλ―Έν„°μ™€ argument 객체

  • es6μ—μ„œλŠ” Rest νŒŒλΌλ―Έν„°λ₯Ό μ‚¬μš©ν•˜μ—¬ κ°€λ³€ 인자 ν•¨μˆ˜μ˜ 인수 λͺ©λ‘μ„ λ°°μ—΄λ‘œ 직접 받을 수 μžˆλ‹€.
  • ν•¨μˆ˜μ™€ es6 λ©”μ„œλ“œλŠ” Rest νŒŒλΌλ―Έν„°μ™€ argument 객체λ₯Ό λͺ¨λ‘ μ‚¬μš©κ°€λŠ₯
  • ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” 자체의 argument 객체 갖지 μ•ŠλŠ”λ‹€. λ”°λΌμ„œ ν™”μ‚΄ν‘œ ν•¨μˆ˜λ‘œ κ°€λ³€ 인자 ν•¨μˆ˜ κ΅¬ν˜„ μ‹œ λ°˜λ“œμ‹œ Rest νŒŒλΌλ―Έν„° μ‚¬μš©

λŒ“κΈ€