아래의 코드를 보자.
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를 사용하는 것을 추천한다.
'Javascript' 카테고리의 다른 글
Ajax with XHR (0) | 2018.07.03 |
---|---|
[Javascript] Global 변수, Global 함수가 좋지 않은 이유 (0) | 2018.06.26 |
[Javascript] 프로토타입 상속(Prototypal Inheritance) (0) | 2018.06.02 |
[Javascript] Closure, 그리고 IIFE의 활용 (2) | 2018.05.03 |
Javascript의 스코프(Scope)에 대한 이해 (0) | 2018.04.29 |
댓글