[πŸ“– λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ λ”₯λ‹€μ΄λΈŒ] 26μž₯. ES6 ν•¨μˆ˜μ˜ μΆ”κ°€ κΈ°λŠ₯

λ…Έμ˜μ™„Β·2024λ…„ 1μ›” 5일
0

JavaScript(Deep Dive)

λͺ©λ‘ 보기
21/23
post-thumbnail
post-custom-banner

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

1. ν•¨μˆ˜μ˜ ꡬ뢄

ES6 μ΄μ „μ˜ ν•¨μˆ˜λŠ” λ™μΌν•œ ν•¨μˆ˜λΌλ„ λ‹€μ–‘ν•œ ν˜•νƒœλ‘œ ν˜ΈμΆœν•  수 μžˆλ‹€.

var foo = function () {
  return 1;
};

// 일반적인 ν•¨μˆ˜λ‘œμ„œ 호좜
foo(); // -> 1

// μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ 호좜
new foo(); // foo {}

// λ©”μ„œλ“œλ‘œμ„œ 호좜
var obj = { foo: foo };
obj.foo(); // 1

ES6 μ΄μ „μ˜ ν•¨μˆ˜λŠ” μ‚¬μš© λͺ©μ μ— 따라 λͺ…ν™•νžˆ κ΅¬λΆ„λ˜μ§€ μ•ŠλŠ”λ‹€. 즉, ES6 μ΄μ „μ˜ λͺ¨λ“  ν•¨μˆ˜λŠ” 일반 ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  수 μžˆλŠ” 것은 λ¬Όλ‘  μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  수 μžˆλ‹€.

ES6 이전에 일반적으둜 λ©”μ„œλ“œλΌκ³  λΆ€λ₯΄λ˜ 객체에 λ°”μΈλ”©λœ ν•¨μˆ˜λ„ 일반 ν•¨μˆ˜λ‘œ ν˜ΈμΆœν•  수 μžˆλŠ” 것은 λ¬Όλ‘  μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  수 도 μžˆλ‹€.

// ν”„λ‘œνΌν‹° f에 λ°”μΈλ”©λœ ν•¨μˆ˜λŠ” callable이며 constructorλ‹€.
var obj = {
  x: 10,
  f: function () { return this.x; }
};

// ν”„λ‘œνΌν‹° f에 λ°”μΈλ”©λœ ν•¨μˆ˜λ₯Ό λ©”μ„œλ“œλ‘œμ„œ 호좜
cosole.log(obj.f()); // 10

// ν”„λ‘œνΌν‹° f에 λ°”μΈλ”©λœ ν•¨μˆ˜λ₯Ό 일반 ν•¨μˆ˜λ‘œμ„œ 호좜
var bar = obj.f;
console.log(bar()); // undefined

// ν”„λ‘œνΌν‹° f에 λ°”μΈλœ ν•¨μˆ˜λ₯Ό μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ 호좜
console.log(new obj.f()); // f {}

이처럼 ES6 μ΄μ „μ˜ λͺ¨λ“  ν•¨μˆ˜λŠ” μ‚¬μš© λͺ©μ μ— 따라 λͺ…ν™•ν•œ ꡬ뢄이 μ—†μœΌλ―€λ‘œ 호좜 방식에 νŠΉλ³„ν•œ μ œμ•½μ΄ μ—†κ³  μƒμ„±μž ν•¨μˆ˜λ‘œ ν˜ΈμΆœλ˜μ§€ μ•Šμ•„λ„ ν”„λ‘œν† νƒ€μž… 객체λ₯Ό μƒμ„±ν•œλ‹€. μ΄λŠ” ν˜Όλž€μŠ€λŸ¬μš°λ©° μ‹€μˆ˜λ₯Ό μœ λ°œν•  κ°€λŠ₯성이 있고 μ„±λŠ₯에도 쒋지 μ•Šλ‹€.

ES6 ν•¨μˆ˜μ˜ ꡬ뢄constructorprototypesuperarguments
일반 ν•¨μˆ˜(Normal)OOXO
λ©”μ„œλ“œ(Method)XXOO
ν™”μ‚΄ν‘œ ν•¨μˆ˜(Arrow)XXXX

2. λ©”μ„œλ“œ

ES6 μ‚¬μ–‘μ—μ„œ λ©”μ„œλ“œλŠ” λ©”μ„œλ“œ μΆ•μ•½ ν‘œν˜„μœΌλ‘œ μ •μ˜λœ ν•¨μˆ˜λ§Œμ„ μ˜λ―Έν•œλ‹€.

const obj = {
  x: 1,
  // fooλŠ” λ©”μ„œλ“œλ‹€.
  foo() { return thos.x;}
  // bar에 λ°”μΈλ”©λœ ν•¨μˆ˜λŠ” λ©”μ„œλ“œκ°€ μ•„λ‹Œ 일반 ν•¨μˆ˜λ‹€.
  bar: function() {return this.x;}
};

console.log(obj.foo()); // 1
console.log(obj.bar()); // 1

ES6 μ‚¬μ–‘μ—μ„œ μ •μ˜ν•œ λ©”μ„œλ“œ(μ΄ν•˜ ES6 λ©”μ„œλ“œ)λŠ” μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 μ—†λŠ” non-constructorλ‹€. λ”°λΌμ„œ ES6 λ©”μ„œλ“œλŠ” μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  수 μ—†λ‹€.

new obj.foo(); // -> TypeError: obj.foo is not a constructor
new obj.bar(); // -> bar {}

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

// obj.fooλŠ” constructorκ°€ μ•„λ‹Œ ES6 λ©”μ„œλ“œμ΄λ―€λ‘œ prototype ν”„λ‘œνΌν‹°κ°€ μ—†λ‹€.
obj.foo.hasOwnProperty('prototype'); // -> false

// obj.barλŠ” constructor인 일반 ν•¨μˆ˜μ΄λ―€λ‘œ prototype ν”„λ‘œνΌν‹°κ°€ μžˆλ‹€.
obj.bar.hasOwnProperty('prototype'); // -> true

참고둜 ν‘œμ€€ λΉŒλ“œμΈ 객체가 μ œκ³΅ν•˜λŠ” ν”„λ‘œν† νƒ€μž… λ©”μ„œλ“œμ™€ 정적 λ©”μ„œλ“œλŠ” λͺ¨λ‘ non-constructorλ‹€.

ES6 λ©”μ„œλ“œλŠ” μžμ‹ μ„ λ°”μΈλ”©ν•œ 객체λ₯Ό κ°€λ¦¬ν‚€λŠ” λ‚΄λΆ€ 슬둯 [[HomeObject]]λ₯Ό κ°–λŠ”λ‹€. super μ°Έμ‘°λŠ” λ‚΄λΆ€ 슬둯 [[HomeObject]]λ₯Ό μ‚¬μš©ν•˜μ—¬ 수퍼클래슀의 λ©”μ„œλ“œλ₯Ό μ°Έμ‘° λ‚΄λΆ€ 슬둯 [[HomeObject]]λ₯Ό κ°–λŠ” ES6 λ©”μ„œλ“œλŠ” super ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

const base = {
  name : 'Lee',
  sayHi() {
    return `Hi ${this.name}`'
  }
};

cosnt derived = {
  __proto__ : base,
  // sayHiλŠ” ES6 λ©”μ„œλ“œλ‹€. ES6 λ©”μ„œλ“œλŠ” [[HomeObject]]λ₯Ό κ°–λŠ”λ‹€.
  // sayHi의 [[HomeObject]]λŠ” sayHiκ°€ λ°”μΈλœ 객체인 derivedλ₯Ό 가리킀고
  // superλŠ” sayHidml [[HomeObject]]의 ν”„λ‘œν† νƒ€μž…μΈ baseλ₯Ό 가리킨닀.
  sayHi() {
    return `${super.sayHi()}. how are you doing?`;
  }
};

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

λ©”μ„œλ“œλ₯Ό μ •μ˜ν•  λ•Œ ν”„λ‘œνΌν‹° κ°’μœΌλ‘œ 읡λͺ… ν•¨μˆ˜ ν‘œν˜„μ‹μ„ ν• λ‹Ήν•˜λŠ” ES6 μ΄μ „μ˜ 방식은 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 것이 μ’‹λ‹€.

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

ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν‘œν˜„λ§Œ κ°„λž΅ν•œ 것이 μ•„λ‹ˆλΌ λ‚΄λΆ€ λ™μž‘λ„ 기쑴의 ν•¨μˆ˜λ³΄λ‹€ κ°„λž΅ν•˜λ‹€. 특히 ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” 콜백 ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ thisκ°€ μ „μ—­ 객체λ₯Ό κ°€λ¦¬ν‚€λŠ” 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•œ λŒ€μ•ˆμœΌλ‘œ μœ μš©ν•˜λ‹€.

3-1. ν™”μ‚΄ν‘œ ν•¨μˆ˜ μ •μ˜

1️⃣ ν•¨μˆ˜μ •μ˜

ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν•¨μˆ˜ μ„ μ–Έλ¬ΈμœΌλ‘œ μ •μ˜ν•  수 μ—†κ³  ν•¨μˆ˜ ν‘œν˜„μ‹μœΌλ‘œ μ •μ˜ν•΄μ•Ό ν•œλ‹€. 호좜 방식은 κΈ°μ‘΄ ν•¨μˆ˜μ™€ 동일

const multiply = (x, y) => x + y;
multiply(2, 3); // -> 6

2️⃣ λ§€κ°œλ³€μˆ˜ μ„ μ–Έ

λ§€κ°œλ³€μˆ˜ μ—¬λŸ¬ 개인 경우 μ†Œκ΄„ν˜Έ () μ•ˆμ— λ§€κ°œλ³€μˆ˜λ₯Ό μ„ μ–Έν•œλ‹€.

const arrow = (x, y) => { ... };

λ§€κ°œλ³€μˆ˜κ°€ ν•œ 개인 경우 μ†Œκ΄„ν˜Έ ()λ₯Ό μƒλž΅ν•  수 μžˆλ‹€.

const arrow = x => { ... };

λ§€κ°œλ³€μˆ˜κ°€ μ—†λŠ” 경우 μ†Œκ΄„ν˜Έ ()λ₯Ό μƒλž΅ν•  수 μ—†λ‹€.

const arrow = () => { ... };

3️⃣ ν•¨μˆ˜ λͺΈμ²΄ μ •μ˜

ν•¨μˆ˜ λͺΈμ²΄κ°€ ν•˜λ‚˜μ˜ 문으둜 κ΅¬μ„±λœλ‹€λ©΄ ν•¨μˆ˜ λͺΈμ²΄λ₯Ό κ°μ‹ΈλŠ” μ€‘κ΄„ν˜Έ {}λ₯Ό μƒλž΅ν•  수 μžˆλ‹€. μ΄λ•Œ ν•¨μˆ˜ λͺΈμ²΄ λ‚΄λΆ€μ˜ 문이 κ°’μœΌλ‘œ 평가될 수 μžˆλŠ” ν‘œν˜„μ‹μΈ 문이라면 μ•”λ¬΅μ μœΌλ‘œ λ°˜ν™˜λœλ‹€.

// conscise body
const power = x => x ** 2;
power(2); // -> 4

// μœ„ ν‘œν˜„μ€ λ‹€μŒκ³Ό λ™μΌν•˜λ‹€.
// block body
const power = x => { return x ** 2 };

ν•¨μˆ˜ λͺΈμ²΄λ₯Ό κ°μ‹ΈλŠ” μ€‘κ΄„ν˜Έ {}λ₯Ό μƒλž΅ν•œ 경우 ν•¨μˆ˜ λͺΈμ²΄ λ‚΄λΆ€μ˜ 문이 ν‘œν˜€μ‹μ΄ μ•„λ‹Œ 문이라면 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€. ν‘œν˜„μ‹μ΄ μ•„λ‹Œ 문은 λ°˜ν™˜ν•  수 μ—†κΈ° λ•Œλ¬Έμ΄λ‹€.

const arrow = () => const x = 1; // SyntaxError: Unexpercted token 'const'

// μœ„ ν‘œν˜„μ€ λ‹€μŒκ³Ό 같이 ν•΄μ„λœλ‹€.
const arrow = () => { return const x = 1; };

λ”°λΌμ„œ ν•¨μˆ˜ λͺΈμ²΄κ°€ ν•˜λ‚˜μ˜ 문으둜 κ΅¬μ„±λœλ‹€ 해도 ν•¨μˆ˜ λͺΈμ²΄μ˜ 문이 ν‘œν˜„μ‹μ΄ μ•„λ‹Œ 문이라면 μ€‘κ΄„ν˜Έλ₯Ό μƒλž΅ν•  수 μ—†λ‹€.

객체 λ¦¬ν„°λŸ΄μ„ λ°˜ν™˜ν•˜λŠ” 경우 객체 λ¦¬ν„°λŸ΄μ„ μ†Œκ΄„ν˜Έ ()둜 감싸 μ£Όμ–΄μ•Ό ν•œλ‹€.

const create = (id, content) => {{id, contend}};
create(1, 'JavaScript'); -> {id: 1, content: "JavaScript"}


// μœ„ ν‘œν˜„μ€ λ‹€μŒκ³Ό λ™μΌν•˜λ‹€
const create = (id, content) => { return {id, content}; };

객체 λ¦¬ν„°λŸ΄μ„ μ†Œκ΄„ν˜Έ ()둜 감싸지 μ•ŠμœΌλ©΄ 객체 λ¦¬ν„°λŸ΄μ˜ μ€‘κ΄„ν˜Έ {}λ₯Ό ν•¨μˆ˜ λͺΈμ²΄λ₯Ό κ°μ‹ΈλŠ” μ€‘κ΄„ν˜Έ {}둜 잘λͺ» ν•΄μ„ν•œλ‹€.

ν•¨μˆ˜ λͺΈμ²΄κ°€ μ—¬λŸ¬ 개의 문으둜 κ΅¬μ„±λœλ‹€λ©΄ ν•¨μˆ˜ λͺΈμ²΄λ₯Ό κ°μ‹ΈλŠ” μ€‘κ΄„ν˜Έ {}λ₯Ό μƒλž΅ν•  수 μ—†λ‹€. μ΄λ•Œ λ°˜ν™˜κ°’μ΄ μžˆλ‹€λ©΄ λͺ…μ‹œμ μœΌλ‘œ λ°˜ν™˜ν•΄μ•Ό ν•œλ‹€.

const sum = (a, b) => {
  const result = a + b;
  return result;
};

ν™”μ‚΄ν‘œ ν•¨μˆ˜λ„ μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜λ‘œ μ‚¬μš©ν•  수 μžˆλ‹€.

const person = (name => ({
  sayHi() { return `Hi? My name is ${name}.`;}
}))('Lee');

console.log(person.sayHi()); // Hi? My name is Lee

ν™”μ‚΄ν‘œ ν•¨μˆ˜λ„ 일급 κ°μ²΄μ΄λ―€λ‘œ Array.prototype.map Array.prototype.filter Array.prototype.reduce 같은 κ³ μ°¨ ν•¨μˆ˜μ— 인수둜 전달할 수 μ•˜λ‹€. 이 경우 일반적인 ν•¨μˆ˜ ν‘œν˜„μ‹λ³΄λ‹€ ν‘œν˜„μ΄ κ°„κ²°ν•˜κ³  가독성이 μ’‹λ‹€.

// ES5
[1, 2, 3].map(function (v) {
  return v * 2;
});

// ES6
[1,2,3].map(v => v * 2); // -> [2,4,6]

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

1️⃣ ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 μ—†λŠ” non-constructorλ‹€.

const Foo = () => {};
// ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  수 μ—†λ‹€.
new Foo(); // TypeError: Foo is not a constructor

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

const Foo = () => {};
// ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” prototype ν”„λ‘œνΌν‹°κ°€ μ—†λ‹€.
Foo.hasOwnProperty('prototype') // -> fasle

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

일반 ν•¨μˆ˜λŠ” μ€‘λ³΅λœ λ§€κ°œλ³€μˆ˜ 이름을 선언해도 μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

function normal(a, a) { return a + a; }
console.log(normal(1, 2)); // 4

ν™”μ‚΄ν‘œ ν•¨μˆ˜μ—μ„œ μ€‘λ³΅λœ λ§€κ°œλ³€μˆ˜ 이름을 μ„ μ–Έν•˜λ©΄ μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.

const arrow = (a, a) => a + a;
// SyntaxError: Duplicate parameter name not allowed in this context

3️⃣ ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν•¨μˆ˜ 자체의 this arguments super new.target 바인딩을 갖지 μ•ŠλŠ”λ‹€.

ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ this arguments super new.target을 μ°Έμ‘°ν•˜λ©΄ μŠ€μ½”ν”„ 체인을 톡해 μƒμœ„ μŠ€μ½”ν”„μ˜ this arguments super new.target을 μ°Έμ‘°ν•œλ‹€.

λ§Œμ•½ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ™€ ν™”μ‚΄ν‘œ ν•¨μˆ˜κ°€ μ€‘μ²©λ˜μ–΄ μžˆλ‹€λ©΄ κ°€μž₯ κ°€κΉŒμš΄ μƒμœ„ ν•¨μˆ˜μ€‘μ—μ„œ ν™”μ‚΄ν‘œν•¨μˆ˜ μ•„λ‹Œ ν•¨μˆ˜μ˜ this arguments super new.target을 μ°Έμ‘°ν•œλ‹€.

3-3. this

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

ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ thisλŠ” 일반 ν•¨μˆ˜μ˜ this와 λ‹€λ₯΄κ²Œ λ™μž‘ν•œλ‹€. μ΄λŠ” "콜백 ν•¨μˆ˜ λ‚΄λΆ€μ˜ this 문제" 즉, 콜백 ν•¨μˆ˜ λ‚΄λΆ€μ˜ thisκ°€ μ™ΈλΆ€ ν•¨μˆ˜μ˜ this와 λ‹€λ₯΄κΈ° λ•Œλ¬Έμ— λ°œμƒν•˜λŠ” 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μ˜λ„μ μœΌλ‘œ μ„€κ³„λœ 것.

class Prefixer {
  constructor(prefix) {
    this.prefix = prefix;
  }

  add(arr) {
    // add λ©”μ„œλ“œλŠ” 인수둜 μ „λ‹¬λœ λ°°μ—΄ arr을 μˆœνšŒν•˜λ©° λ°°μ—΄μ˜ λͺ¨λ“  μš”μ†Œμ— prefixλ₯Ό μΆ”κ°€ν•œλ‹€.
    // β‘ 
    return arr.map(function (item) {
      return this.prefix + item; // β‘‘
      // -> TypeError: Cannot read property 'prefix' of undefined
    });
  }
}

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

μœ„ 예제 μ‹€ν–‰ 결과값은 TypeError

Array.prototype.mapλ©”μ„œλ“œκ°€ 콜백 ν•¨μˆ˜λ₯Ό 일반 ν•¨μˆ˜λ‘œ ν˜ΈμΆœν•˜κΈ° λ•Œλ¬Έμ— β‘‘μ—μ„œ thisλŠ” undefinedλ₯Ό 가리킨닀.

일반 ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœλ˜λŠ” λͺ¨λ“  ν•¨μˆ˜ λ‚΄λΆ€μ˜ thisλŠ” μ „μ—­ 객체λ₯Ό 가리킀고, μ™ΈλΆ€ ν•¨μˆ˜μ— thisλŠ” ν˜ΈμΆœν•œ 객체λ₯Ό 가리킨닀.

β‘ , β‘‘κ°€ κ°€λΌν‚€λŠ” thisκ°€ λ‹€λ₯΄λ―€λ‘œ TypeError λ°œμƒ.

πŸ’‘ ES6 이전 this 문제 ν•΄κ²°

1️⃣ add λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ prefixer 객체λ₯Ό κ°€λ¦¬ν‚€λŠ” thisλ₯Ό 일단 νšŒν”Όμ‹œν‚¨ 후에 콜백 ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μ‚¬μš©ν•œλ‹€.

...
add(arr) {
  // thisλ₯Ό 일단 νšŒν”Όμ‹œν‚¨λ‹€.
  const that = this;
  return arr.map(function (item) {
    // this λŒ€μ‹  that을 μ°Έμ‘°ν•œλ‹€.
    return that.prefix + ' ' + item;
  });
}
...

2️⃣ Array.prototype.map 의 두 번째 인수둜 add λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ prefixer 객체λ₯Ό κ°€λ¦¬ν‚€λŠ” thisλ₯Ό μ „λ‹¬ν•œλ‹€.

ES5μ—μ„œ λ„μž…λœ Array.prototype.map은 "μ½œλ°°κ°€ ν•¨μˆ˜ λ‚΄λΆ€μ˜ this 문제"λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ 두 번째 인수둜 콜백 ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ this둜 μ‚¬μš©ν•  객체λ₯Ό 전달할 수 μžˆλ‹€.

...
add(arr) {
  return arr.map(function (item) {
    return this.prefix + ' ' + item;
  }, this); // this에 λ°”μΈλ”©λœ 값이 콜백 ν•¨μˆ˜ λ‚΄λΆ€μ˜ this에 λ°”μΈλ”©λœλ‹€.
}
...

3️⃣ Function.prototype.bind λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ add λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ prefixer 객체λ₯Ό κ°€λ¦¬ν‚€λŠ” thisλ₯Ό λ°”μΈλ”©ν•œλ‹€.

...
add(arr) {
  return arr.map(function (item) {
    return this.prefix + ' ' + item;
  }.bind(this)); // this에 λ°”μΈλœ 값이 콜백 ν•¨μˆ˜ λ‚΄λΆ€μ˜ this에 λ°”μΈλ”©λœλ‹€.
}
...

πŸ’‘ ES6 이후 this 문제 ν•΄κ²°

ν™”μ‚΄ν‘œ ν•¨μˆ˜ μ‚¬μš©ν•˜μ—¬ "콜백 ν•¨μˆ˜ λ‚΄λΆ€μ˜ this 문제λ₯Ό ν•΄κ²°

class Prefixer {
  constructor(prefix) {
    this.prefix = prefix;
  }
  
  add(arr) {
    return arr.map(item => this.prefix + item);
  }
}

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

ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν•¨μˆ˜ 자체의 this 바인딩을 갖지 μ•ŠλŠ”λ‹€. λ”°λΌμ„œ ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ this μ°Έμ‘°ν•˜λ©΄ μƒμœ„ μŠ€μ½”ν”„μ˜ thisλ₯Ό κ·ΈλŒ€λ‘œ μ°Έμ‘°ν•˜λ‚Ÿ. 이λ₯Ό lexcal this라 ν•œλ‹€. μ΄λŠ” 마치 λ ‰μ‹œμ»¬ μŠ€μ½”ν”„μ™€ 같이 ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ thisκ°€ ν•¨μˆ˜κ°€ μ •μ˜λœ μœ„μΉ˜μ— μ˜ν•΄ κ²°μ •λœλ‹€λŠ” 것을 μ˜λ―Έν•œλ‹€.

ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό Function.prototype.bindλ₯Ό μ‚¬μš©ν•˜μ—¬ ν‘œν˜„ν•˜λ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

// ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” μƒμœ„ μŠ€μ½”ν”„μ˜ thisλ₯Ό μ°Έμ‘°ν•œλ‹€.
() => this.x;

// 읡λͺ… ν•¨μˆ˜μ— μƒμœ„ μŠ€μ½”ν”„μ˜ thisλ₯Ό μ£Όμž…ν•œλ‹€. μœ„ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ™€ λ™μΌν•˜κ²Œ λ™μž‘ν•œλ‹€.
(function () { return this.x; }).bind(this);

ν™”μ‚΄ν‘œ ν•¨μˆ˜μ™€ ν™”μ‚΄ν‘œ ν•¨μˆ˜κ°€ μ€‘μ²©λ˜μ–΄ μžˆλ‹€λ©΄ μƒμœ„ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ—λ„ this 바인딩이 μ—†μœΌλ―€λ‘œ μŠ€μ½”ν”„ 체인 μƒμ—μ„œ κ°€μž₯ κ°€κΉŒμš΄ μƒμœ„ ν•¨μˆ˜ μ€‘μ—μ„œ ν™”μ‚΄ν‘œ ν•¨μˆ˜κ°€ μ•„λ‹Œ ν•¨μˆ˜μ˜ thisλ₯Ό μ°Έμ‘°ν•œλ‹€.

// 쀑첩 ν•¨μˆ˜ foo의 μƒμœ„ μŠ€μ½”ν”„λŠ” μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜λ‹€.
// λ”°λΌμ„œ ν™”μ‚΄ν‘œ ν•¨μˆ˜ foo의 thisλŠ” μƒμœ„ μŠ€μ½”ν”„μΈ μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜μ˜ thisλ₯Ό 가리킨닀.
(function () {
  const foo = () => console.log(this);
  foo();
}).call({ a:1 });

// bar ν•¨μˆ˜λŠ” ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•œλ‹€.
// bar ν•¨μˆ˜κ°€ λ°˜ν™˜ν•œ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ μƒμœ„ μŠ€μ½”ν”„λŠ” ν™”μ‚΄ν‘œ ν•¨μˆ˜ barλ‹€.
// ν•˜μ§€λ§Œ ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν•¨μˆ˜ 자체의 this 바인딩을 갖지 μ•ŠμœΌλ―€λ‘œ bar ν•¨μˆ˜κ°€ λ°˜ν™˜ν•œ
// ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μ°Έμ‘°ν•˜λŠ” thisλŠ” ν™”μ‚΄ν‘œ ν•¨μˆ˜κ°€ μ•„λ‹Œ μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜μ˜ thisλ₯Ό 가리킨닀.

(function () {
  const foo = () => () => console.log(this);
  bar()();
}).call({ a: 1}); // { a: 1 }

ν™”μ‚΄ν‘œ ν•¨μˆ˜κ°€ μ „μ—­ ν•¨μˆ˜λΌλ©΄ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ thisλŠ” μ „μ—­ 객체λ₯Ό 가리킨닀. μ „μ—­ ν•¨μˆ˜μ˜ μƒμœ„ μŠ€μ½”ν”„λŠ” 전역이고 μ „μ—­μ—μ„œ thisλŠ” μ „μ—­ 객체λ₯Ό 가리킀기 λ•Œλ¬Έμ΄λ‹€.

// μ „μ—­ ν•¨μˆ˜ foo의 μƒμœ„ μŠ€μ½”ν”„λŠ” μ „μ—­μ΄λ―€λ‘œ ν™”μ‚΄ν‘œ ν•¨μˆ˜ foo의 thisλŠ” μ „μ—­ 객체λ₯Ό 가리킨닀.
const foo = () => console.log(this);
foo(); // window

ν”„λ‘œνΌν‹°μ— ν• λ‹Ήν•œ ν™œμ‚΄ν‘œ ν•¨μˆ˜λ„ μŠ€μ½”ν”„ μ²΄μΈμƒμ—μ„œ κ°€μž₯ κ°€κΉŒμš΄ μƒμœ„ ν•¨μˆ˜ μ€‘μ—μ„œ ν™”μ‚΄ν‘œ ν•¨μˆ˜κ°€ μ•„λ‹Œ ν•¨μˆ˜μ˜ thisλ₯Ό μ°Έμ‘°ν•œλ‹€.

// increase ν”„λ‘œνΌν‹°μ— ν• λ‹Ήν•œ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ μƒμœ„ μŠ€μ½”ν”„λŠ” 전역이닀.
// λ”°λΌμ„œ increase ν”„λ‘œνΌν‹°μ— ν• λ‹Ήν•œ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ thisλŠ” μ „μ—­ 객체λ₯Ό 가리킨닀.
const counter = {
  num: 1,
  increase : () => ++this.num
};

console.log(counter.increase()); // NaN

ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν•¨μˆ˜ 자체의 this 바인딩을 갖지 μ•ŠκΈ° λ•Œλ¬Έμ— Function.prototype.call Function.prototype.apply Function.prototype.bind λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄λ„ ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ˜ thisλ₯Ό ꡐ체할 수 μ—†λ‹€.

ν™”μ‚΄ν‘œ ν•¨μˆ˜κ°€ Function.prototype.call Function.prototype.apply Function.prototype.bind λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  수 μ—†λ‹€λŠ” μ˜λ―ΈλŠ” μ•„λ‹ˆλ‹€. ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν•¨μˆ˜ 자체의 this 바인딩을 갖지 μ•ŠκΈ° λ•Œλ¬Έμ— thisλ₯Ό ꡐ체 ν•  수 μ—†κ³  μ–Έμ œλ‚˜ μƒμœ„ μŠ€μ½”ν”„μ˜ this 바인등을 μ°Έμ‘°ν•œλ‹€.

window.x = 1;

const normal = function () { return this.x; }
const arrow = () => this.x;

console.log(normal.call({ x: 10 })); // 10
console.log(arrow.call({ x: 10 })); // 1
const add = (a, b) => a + b;

console.log(add.call(null, 1, 2)); // 3
console.log(add.apply(null, [1, 2])); // 3
console.log(add.bind(null, 1, 2)()); // 3

λ©”μ„œλ“œλ₯Ό ν™”μ‚΄ν‘œ ν•¨μˆ˜λ‘œ μ •μ˜ν•˜λŠ” 것은 ν”Όν•΄μ•Ό ν•œλ‹€. μ—¬κΈ°μ„œ λ©”μ„œλ“œλŠ” ES6 λ©”μ„œλ“œκ°€ μ•„λ‹Œ 일반적인 의미의 λ©”μ„œλ“œλ₯Ό 의미.

// Bad
const person = {
  name : 'Lee',
  sayHi: () => console.log(`Hi ${this.name}`)
};

// sayHi ν”„λ‘œνΌν‹°μ— ν• λ‹Ήλœ ν™œμ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ˜ thisλŠ” μƒμœ„ μŠ€μ½”ν”„μΈ thisκ°€ κ°€λ¦¬ν‚€λŠ”
// μ „μ—­ 객체λ₯Ό κ°€λ¦¬ν‚€λ―€λ‘œ 이 예제λ₯Ό λΈŒλΌμš°μ €μ— μ‹€ν–‰ν•˜λ©΄ this.name은 빈 λ¬Έμžμ—΄μ„ κ°–λŠ” window.nameκ³Ό κ°™λ‹€.
// μ „μ—­ 객체 windowμ—λŠ” 빌트인 ν”„λ‘œνΌν‹° name이 μ‘΄μž¬ν•œλ‹€.
person.sayHi(); // Hi

λ©”μ„œλ“œλ₯Ό μ •μ˜ν•  λ•ŒλŠ” ES6 λ©”μ„œλ“œ μΆ•μ•½ ν‘œν˜„μœΌλ‘œ μ •μ˜ν•œ ES6 λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.

// Good
const person = {
  name: 'Lee',
  sayHi() {
    console.log(`Hi ${this.name}`);
  }
};

person.sayHi(); // Hi Lee

ν”„λ‘œν† νƒ€μž… κ°μ±„μ˜ ν”„λ‘œνΌν‹°μ— ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό ν• λ‹Ήν•˜λŠ” κ²½μš°λ„ λ™μΌν•œ λ¬Έμ œκ°€ λ°œμƒ.

// Bad
function Person(name) {
  this.name = name;
}

Person.prototype.sayHi = () => console.log(`Hi ${this.name}`);

const person = new Person('Lee');
// 이 예제λ₯Ό λΈŒλΌμš°μ €μ—μ„œ μ‹€ν–‰ν•˜λ©΄ this.name은 빈 λ¬Έμžμ—΄μ„ κ°–λŠ” window.nameκ³Ό κ°™λ‹€.
person.sayHi(); // Hi

ν”„λ‘œνΌν‹°λ₯Ό 동적 μΆ”κ°€ν•  λ•ŒλŠ” ES6 λ©”μ„œλ“œ μ •μ˜λ₯Ό μ‚¬μš©ν•  수 μ—†μœΌλ―€λ‘œ 일반 ν•¨μˆ˜λ₯Ό ν• λ‹Ήν•œλ‹€.

// Good
function Person(name) {
  this.name = name;
}

Person.prototype.sayHi = function () { console.log(`Hi ${this.name}`); };

const person = new Person('Lee');
person.sayHi(); // Hi Lee

일반 ν•¨μˆ˜κ°€ μ•„λ‹Œ ES6 λ©”μ„œλ“œλ₯Ό 동적 μΆ”κ°€ν•˜κ³  μ‹Άλ‹€λ©΄ λ‹€μŒκ³Ό 같이 객체 λ¦¬ν„°λŸ΄μ„ λ°”μΈλ”©ν•˜κ³  ν”„λ‘œν† νƒ€μž…μ˜ constructor ν”„λ‘œνΌν‹°μ™€ μƒμ„±μž ν•¨μˆ˜κ°„μ˜ 연결을 μž¬μ„€μ •ν•œλ‹€.

function Person(name) {
  this.name = name;
}

Person.prototype = {
  // constructor ν”„λ‘œνΌν‹°μ™€ μƒμ„±μž ν•¨μˆ˜ κ°„μ˜ 연결을 μž¬μ„€μ •
  constructor = Person,
  sayHi() { console.log(`Hi ${this.name}`); }
};

const person = new Person('Lee');
person.sayHi(); // Hi Lee

클래슀 ν•„λ“œ μ •μ˜ μ œμ•ˆμ„ μ‚¬μš©ν•˜μ—¬ 클래슀 ν•„λ“œμ— ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό ν• λ‹Ήν•  μˆ˜λ„ μžˆλ‹€.

// Bad
class Person {
  // 클래슀 ν•„λ“œ μ •μ˜ μ œμ•ˆ
  name = "Lee";
  sayHi = () => console.log(`Hi ${this.name}`);
}

const person = new Person();
person.sayHi(); // Hi Lee

μ΄λ•Œ sayHi 클래슀 ν•„λ“œμ— ν• λ‹Ήν•œ ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ thisλ₯Ό μ°Έμ‘°ν•˜λ©΄ μƒμœ„ μŠ€μ½”ν”„μ˜ this 바인딩을 μ°Έμ‘° κ·Έλ ‡λ‹€λ©΄ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ μƒμœ„ μŠ€μ½”ν”„λŠ” 무엇일가? sayHi 클래슀 ν•„λ“œλŠ” μΈμŠ€ν„΄μŠ€ ν”„λ‘œνΌν‹°μ΄λ―€λ‘œ λ‹€μŒκ³Ό 같은 μ˜λ―Έμ΄λ‹€.

class Person {
  constructor() {
    this.name = 'Lee';
    // ν΄λž˜μŠ€κ°€ μƒμ„±ν•œ μΈμŠ€ν„΄μŠ€(this)의 sayHi ν”„λ‘œνΌν‹°μ— ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό ν• λ‹Ήν•œλ‹€.
    // λ”°λΌμ„œ sayHi ν”„λ‘œνΌν‹°λŠ” μΈμŠ€ν„΄μŠ€ ν”„λ‘œνΌν‹°λ‹€.
    this.sayHi = () => console.log(`Hi ${this.name}`);
  }
}

sayHi 클래슀 ν•„λ“œμ— ν• λ‹Ήν•œ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ μƒμœ„ μŠ€μ½”ν”„λŠ” 사싀 클래슀 μ™ΈλΆ€μ§€λ§Œ thisκ°€ 클래슀λ₯Ό 생성할 μΈμŠ€ν„΄μŠ€λ₯Ό μ°Έμ‘°ν•œλ‹€. λ”°λΌμ„œ sayHi 클래슀 ν•„λ“œμ— ν• λ‹Ήν•œ ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μ°Έμ‘°ν•œ thisλŠ” constructor λ‚΄λΆ€μ˜ this 바인딩과 κ°™λ‹€.

ν•˜μ§€λ§Œ 클래슀 ν•„λ“œμ— ν• λ‹Ήν•œ ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν”„λ‘œν† νƒ€μž… λ©”μ„œλ“œκ°€ μ•„λ‹ˆλΌ μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œκ°€ λœλ‹€. λ”°λΌμ„œ λ©”μ„œλ“œλ₯Ό μ •μ˜ν•  λ•ŒλŠ” ES6 λ©”μ„œλ“œ μΆ•μ•½ ν‘œν˜„μœΌλ‘œ μ •μ˜ν•œ ES6 λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.

// Good
class Person {
  // 클래슀 ν•„λ“œ μ •μ˜ μ œμ•ˆ
  name = "Lee";
  sayHi() { console.log(`Hi ${this.name}`); }
}

const person = new Person();
person.sayHi(); // Hi Lee

3-4. super

ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν•¨μˆ˜ 자체의 super 바인딩을 갖지 μ•ŠλŠ”λ‹€. λ”°λΌμ„œ ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ superλ₯Ό μ°Έμ‘°ν•˜λ©΄ this와 λ§ˆμ°¬κ°€μ§€λ‘œ μƒμœ„ μŠ€μ½”ν”„μ˜ superλ₯Ό μ°Έμ‘°ν•œλ‹€.

class Base {
  constructor(name) {
    this.name = name;
  }
  
  sayHi() {
    return `Hi! ${this.name}`;
  }
}

class Derived extends Base {
  // ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ superλŠ” μƒμœ„ μŠ€μ½”ν”„μΈ constructor의 superλ₯Ό 가리킨닀.
  sayHi = () => `${super.sayHi()} how are you doing?`
}

const derived = new Derived('Lee');
console.log(derived.sayHi()); // Hi! LEe how are you doing?

sayHi 클래슀 ν•„λ“œμ— ν• λ‹Ήν•œ ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν•¨μˆ˜μžμ²΄μ˜ super 바인딩을 갖지 μ•ŠμœΌλ―€λ‘œ superλ₯Ό 참쑰해도 μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•Šκ³  Derived의 constructor의 super 바인딩을 μ°Έμ‘°

3-5. arguments

ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν•¨μˆ˜ 자체의 arguments 바인딩을 갖지 μ•ŠλŠ”λ‹€. λ”°λΌμ„œ ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ argumentsλ₯Ό μ°Έμ‘°ν•˜λ©΄ this와 λ§ˆμ°¬κ°€μ§€λ‘œ μƒμœ„ μŠ€μ½”ν”„μ˜ argumentsλ₯Ό μ°Έμ‘°ν•œλ‹€.

(function () {
  // ν™”μ‚΄ν‘œ ν•¨μˆ˜ foo의 argumentsλŠ” μƒμœ„ μŠ€μ½”ν”„μΈ μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜μ˜ argumentsλ₯Ό 가리킨닀.
  const foo = () => console.log(arguments); // [Arguments] { '0': 1, '1': 2}
  foo(3, 4);
},(1, 2));

// ν™”μ‚΄ν‘œ ν•¨μˆ˜ foo의 argumentsλŠ” μƒμœ„ μŠ€μ½”ν”„μΈ μ „μ—­μ˜ argumetnsλ₯Ό 가리킨닀.
// ν•˜μ§€λ§Œ μ „μ—­μ—λŠ” arguments 객체가 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€. arguments κ°μ²΄λŠ” ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œλ§Œ μœ νš¨ν•˜λ‹€.
const foo = () => console.log(arguments);
foo(1, 2); // ReferenceError: arguments is not defined

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

Rest νŒŒλΌλ―Έν„°(λ‚˜λ¨Έμ§€ λ§€κ°œλ³€μˆ˜)λŠ” λ§€κ°œλ³€μˆ˜ 이름 μ•žμ— μ„Έκ°œμ˜ 점 ...을 λΆ™μ—¬μ„œ μ •μ˜ν•œ λ§€κ°œλ³€μˆ˜λ₯Ό μ˜λ―Έν•œλ‹€.

Rest νŒŒλΌλ―Έν„°(λ‚˜λ¨Έμ§€ λ§€κ°œλ³€μˆ˜)λŠ” ν•¨μˆ˜μ— μ „λ‹¬λœ μΈμˆ˜λ“€μ˜ λͺ©λ‘μ„ λ°°μ—΄λ‘œ μ „λ‹¬λ°›λŠ”λ‹€.

function foo(...rest) {
  // λ§€κ°œλ³€μˆ˜ restλŠ” μΈμˆ˜λ“€μ˜ λͺ©λ‘μ„ λ°°μ—΄λ‘œ μ „λ‹¬λ°›λŠ” Rest νŒŒλ¦¬λ―Έν„°λ‹€.
  console.log(rest); // [1, 2, 3, 4, 5]
  
foo(1, 2, 3, 4, 5);

λ§€κ°œλ³€μˆ˜μ™€ Rest νŒŒλΌλ―Έν„°λŠ” ν•¨κ»˜ μ‚¬μš©ν•  수 μžˆλ‹€. μ΄λ•Œ ν•¨μˆ˜μ— μ „λ‹¬λœ μΈμˆ˜λ“€μ€ 순차적으둜 ν• λ‹Ήλœλ‹€.

function foo(param, ...rest) {
  console.log(param); // 1
  console.log(rest); // [2,3,4,5,]
}

foo(1, 2, 3, 4, 5);

Rest νŒŒλΌλ―Έν„°λŠ” λ°˜λ“œμ‹œ λ§ˆμ§€λ§‰ νŒŒλ¦¬λ―Έν„°μ΄μ–΄μ•Ό ν•˜λ©° 단, ν•˜λ‚˜λ§Œ μ„ μ–Έν•  수 μžˆλ‹€.

function foo(...rest , param1, param2) {}
foo(1, 2, 3, 4, 5); 
// SyntaxError: Rest parameter must ne last formal parameter
function foo(...rest1, ...rest2) { }
foo(1,2,3,4,5);
// SyntaxError: Rest parameter must ne last formal parameter

Rest νŒŒλΌλ―Έν„°λŠ” ν•¨μˆ˜ μ •μ˜ μ‹œ μ„ μ–Έν•œ λ§€κ°œλ³€μˆ˜ 개수λ₯Ό λ‚˜νƒ€λ‚΄λŠ” ν•¨μˆ˜ 객체의 length ν”„λ‘œνΌν‹°μ— 영ν–₯을 주지 μ•ŠλŠ”λ‹€.

function foo(..rest) {}
console.log(foo.length); // 0

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

function baz(x, y, ..rest) {}
console.log(baz.length); // 2

4-2. Rest νŒŒλΌλ―Έν„°μ™€ arguments 객체

ES5μ—μ„œλŠ” κ°€λ³€ 인자 ν•¨μˆ˜μ˜ 경우 λ§€κ°œλ³€μˆ˜λ₯Ό 톡해 인수λ₯Ό μ „λ‹¬λ°›λŠ” 것이 λΆˆκ°€λŠ₯ ν•˜λ―€λ‘œ argumetns 객체λ₯Ό ν™œμš©ν•˜μ—¬ 인수λ₯Ό μ „λ‹¬λ°›μ•˜λ‹€.

argumetns κ°μ²΄λŠ” ν•¨μˆ˜ 호좜 μ‹œ μ „λ‹¬λœ μΈμˆ˜λ“€μ˜ 정보λ₯Ό λ‹΄κ³  μžˆλŠ” 순회 κ°€λŠ₯ν•œ μœ μ‚¬ λ°°μ—΄ 객체이며, ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ 지역 λ³€μˆ˜μ²˜λŸΌ μ‚¬μš©ν•  수 μžˆλ‹€.

μœ μ‚¬ λ°°μ—΄ κ°μ²΄λŠ” λ°°μ—΄ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ €λ©΄ Function.prototype.call Function.prototype.apply λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄ arguments 객체λ₯Ό λ°°μ—΄λ‘œ λ³€ν™˜ν•΄μ•Ό ν•˜λŠ” λ²ˆκ±°λ‘œμ›€ μžˆλ‹€.

// λ§€κ°œλ³€μˆ˜μ˜ 개수λ₯Ό 사전에 μ•Œ 수 μ—†λŠ” κ°€λ³€ 인자 ν•¨μˆ˜
function sum() {
  // κ°€λ³€ 인자 ν•¨μˆ˜λŠ” arguments 객체λ₯Ό 톡해 인수λ₯Ό μ „λ‹¬λ°›λŠ”λ‹€.
  console.log(arguments);
}

sum(1, 2); // {length: 2, '0': 1, '1': 2}
function sum() {
  // μœ μ‚¬ λ°°μ—΄ 객체인 arguments 객체fmf λ°°μ—΄λ‘œ λ³€ν™˜ν•œλ‹€.
  var array = Array.prototype.slice.call(arguments);
  
  return array.reduce(function (pre, cur) {
    return pre + cur;
  }, 0);
}

console.log(sum(1,2,3,4,5)); // 15

ES6μ—μ„œλŠ” rest νŒŒλΌλ―Έν„°λ₯Ό μ‚¬μš©ν•˜μ—¬ κ°€λ³€ 인자 ν•¨μˆ˜μ˜ λͺ©λ‘μ„ λ°°μ—΄λ‘œ 직접 전달받을 수 μžˆλ‹€. 이λ₯Ό 톡해 μœ μ‚¬ λ°°μ—΄ 객체인 arguments 객체λ₯Ό λ°°μ—΄λ‘œ λ³€ν™˜ν•˜λŠ” λ²ˆκ±°λ‘œμ›€μ„ ν”Όν•  수 μžˆλ‹€.

function sum(...args) {
  // Rest νŒŒλ¦¬λ―Έν„° argμ—λŠ” λ°°μ—΄ [1, 2, 3, 4, 5]κ°€ ν• λ‹Ήλœλ‹€.
  return arg.reduce((pre, cur) => pre + cur, 0);
}
console.log(sum(1,2,3,4,5)); // 15

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

5. λ§€κ°œλ³€μˆ˜ κΈ°λ³Έκ°’

ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ λ§€κ°œλ³€μˆ˜μ˜ 개수만큼 인수λ₯Ό μ „λ‹¬ν•˜λŠ” 것이 λ°”λžŒμ§ ν•˜μ§€λ§Œ 그렇지 μ•Šμ€κ²½μš°μ—λ„ μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진이 λ§€κ°œλ³€μˆ˜μ˜ κ°œμˆ˜μ™€ 인수의 개수λ₯Ό μ²΄ν¬ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

μΈμˆ˜κ°€ μ „λ‹¬λ˜μ§€ μ•Šμ€ λ§€κ°œλ³€μˆ˜μ˜ 값은 undefinedλ‹€.

function sum(x, y) {
  return x + y;
}

console.log(sum(1)); // NaN

μΈμˆ˜κ°€ μ „λ‹¬λ˜μ§€ μ•Šμ€ κ²½μš°μ— λ§€κ°œλ³€μˆ˜μ— 기본값을 ν• λ‹Ήν•  ν•„μš”κ°€ μžˆλ‹€.

function sum(x, y) {
  // μΈμˆ˜κ°€ μ „λ‹¬λ˜μ§€ μ•Šμ•„ λ§€κ°œλ³€μˆ˜μ˜ 값이 undefined인 경우 기본값을 ν• λ‹Ήν•œλ‹€.
  x = x || 0;
  y = y || 0;
  
  return x + y;
}

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

ES6μ—μ„œ λ„μž…λœ λ§€κ°œλ³€μˆ˜ 기본값을 μ‚¬μš©ν•˜λ©΄ ν•¨μˆ˜ λ‚΄μ—μ„œ μˆ˜ν–‰ν•˜λ˜ 인수 체크 및 μ΄ˆκΈ°ν™”λ₯Ό κ°„μ†Œν™”ν•  수 μžˆλ‹€.

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

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

function logName(name = 'Lee') {
  console.log(name);
}

logName(); // Lee
logName(undefined); // Lee
logName(null); // null

Rest νŒŒλΌλ―Έν„°μ—λŠ” 기본값을 지정할 수 μ—†λ‹€.

function foo(...rest = []) {
  console.log(rest);
}

// SyntaxError: Rest paramter may not have a default initializer
post-custom-banner

0개의 λŒ“κΈ€