본문 바로가기
Javascript

[Javascript] 기본 매개변수(Default Function Parameters)

by kmmguumnn 2018. 6. 12.

아래의 코드를 보자.

function greet(name, greeting) {
  name = (typeof name !== 'undefined') ?  name : 'Student';
  greeting = (typeof greeting !== 'undefined') ?  greeting : 'Welcome';

  return `${greeting} ${name}!`;
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!


greet()은 2개의 인자를 받아 각각 출력하는 간단한 함수이다. 다만 인자가 들어오지 않았거나 'undefined'인 경우에 대비해 각각 'Student'와 'Welcome'이라는 일종의 기본값을 설정해 놓은 것을 알 수 있다. 그리 어렵지 않은 코드이지만, 매개변수의 기본값을 지정하기 위해 매번 이런 식으로 코드를 작성해야 한다면 매우 귀찮을 것이다.

ES6에서는 이러한 경우를 위해 'Default Function Parameters'라는 기능을 제공한다.


이렇게 하면 된다.

function greet(name = 'Student', greeting = 'Welcome') {
  return `${greeting} ${name}!`;
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

매개변수 뒤에 '='를 붙인 뒤 기본값을 지정해주면 끝이다. 2개의 매개변수 중 비어있는 것이 있을 경우, 지정한 기본값이 인자로 전달된다.




이 기능을 배열(array)과 객체(object)에도 활용해 보자.

function createGrid([width = 5, height = 5]) {
  return `Generates a ${width} x ${height} grid`;
}

createGrid([]); // Generates a 5 x 5 grid
createGrid([2]); // Generates a 2 x 5 grid
createGrid([2, 3]); // Generates a 2 x 3 grid
createGrid([undefined, 3]); // Generates a 5 x 3 grid

직관적으로 이해할 수 있을 것이다. 2개의 element(width, height)를 포함한 배열 [width, height]가 createGrid()의 인자로 들어가는데, 배열의 element의 기본값을 위와 같은 방법으로 지정해 놓으면 비어있는 배열을 인자로 전달해도 정상적으로 출력된다.


다만 이 코드에서 createGrid()를 호출한 4가지 경우는 모두 [] 형태로 배열을 인자로 전달했다. 만약 createGrid()와 같이 아무 것도 넣지 않으면 어떻게 될까? 다음과 같은 에러가 발생한다.


Uncaught TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined




어떤 경우에도 배열의 형태로 인자가 전달되도록 기본값을 지정하고 싶다면? 원리는 동일하다. 오른쪽에 = [] 를 추가하면 된다.

function createGrid([width = 5, height = 5] = []) {
  return `Generates a ${width} x ${height} grid`;
}

이렇게 하면 배열 없이 createGrid()로 호출해도 'Generates a 5 x 5 grid'와 같이 기본값이 적용된다.





객체(object)에 적용할 때도 원리는 동일하다.

function createSundae({scoops = 1, toppings = ['Hot Fudge']}) {
  const scoopText = scoops === 1 ? 'scoop' : 'scoops';
  return `Your sundae has ${scoops} ${scoopText} with ${toppings.join(' and ')} toppings.`;
}

createSundae({}); // Your sundae has 1 scoop with Hot Fudge toppings.
createSundae({scoops: 2}); // Your sundae has 2 scoops with Hot Fudge toppings.
createSundae({scoops: 2, toppings: ['Sprinkles']}); // Your sundae has 2 scoops with Sprinkles toppings.
createSundae({toppings: ['Cookie Dough']}); // Your sundae has 1 scoop with Cookie Dough toppings.


createSundae() 함수는 인자로 객체를 받도록 되어 있는데, 위에서 배열을 받는 함수와 마찬가지로, 객체를 포함하지 않고 함수를 호출하면 에러가 발생한다. 해결방법은 위와 동일하게 = {} 를 붙여주면 된다.

function createSundae({scoops = 1, toppings = ['Hot Fudge']} = {}) {
  const scoopText = scoops === 1 ? 'scoop' : 'scoops';
  return `Your sundae has ${scoops} ${scoopText} with ${toppings.join(' and ')} toppings.`;
}




Array defaults vs. object defaults

객체 기본매개변수(object defaults)가 배열 기본매개변수(array defaults)보다 좋은 점이 한가지 있는데, 특정 매개변수를 스킵하고 싶을 때 더 편하다는 것이다.

function createSundae({scoops = 1, toppings = ['Hot Fudge']} = {}) { … }

위와 같이 object defaults로 작성된 함수를 호출할 때, 만약 첫번째 값인 scoops는 스킵하고 두번째 값인 toppings만 바꾸고 싶으면 호출할 때 toppings만 건드리면 된다.

createSundae({toppings: ['Hot Fudge', 'Sprinkles', 'Caramel']});



하지만,

function createSundae([scoops = 1, toppings = ['Hot Fudge']] = []) { … }

위와 같이 array defaults로 작성된 함수를 첫번째 인자를 스킵해서 호출하려면, 인자를 비우면 안되고 아래와 같이 'undefined'를 무조건 포함시켜서 호출해야만 한다.

createSundae([undefined, ['Hot Fudge', 'Sprinkles', 'Caramel']]);



꼭 array defaults를 써야만 하는 상황이 아니라면, object defaults를 사용하는 것을 추천한다.

댓글