1. Params
default params
default params는 사용자가 함수에 인자를 전달하지 않았을 때, 기본으로 적용할 값을 설정하기 위해 만들어진 문법이다. 이전에는 아래와 같이 함수 내부에서 조건문을 이용했다.
function rollDice(numsSide) {
return Math.floor(Math.random() * numsSide) + 1;
}
rollDice(); // numsSide===undefined => it prints out NaN
// use condition checking
function rollDice(numsSide) {
if(!numsSide) {
numsSide = 6;
};
return Math.floor(Math.random() * numsSide) + 1;
}
rollDice(); // 1~6 중 하나의 값 출력
하지만 함수에서 사용하는 parameter 값이 늘어나면 조건문을 이용해서 기본 값을 설정하는 것이 번거로워진다. 뿐만 아니라 순수 함수 관점에서도, 함수 내부에서 조건문을 사용하는 코드는 나쁜 코드이다. 그래서 등장한 것이 default parameter syntax이다.
// default parameter
function rollDice(numsSide = 6) {
return Math.floor(Math.random() * numsSide) + 1;
}
function greet(name, msg="hello there") {
return `${msg}, ${name}`;
}
greet("taylor"); // hello there, taylor
function greet2(msg="hello, there", name) {
return `${msg}, ${name}`;
}
greet("taylor"); // undefined, taylor
이 때 예제 코드의 greet 함수와 같이, 여러 개의 params를 인자로 받는 함수에서는 기본값을 갖는 변수를 첫번째 순서에 작성하지 않는 것이 좋다.
rest params(...)
rest parameter를 살펴보기 이전에 arguments object에 대해서 먼저 알아보아야 한다. auguments object는 모든 함수가 선언될 때 자동으로 만들어지는 객체로, 다음과 같은 성질을 가지고 있다.
- 모든 함수에 존재한다. 단, 화살표 함수에는 존재하지 않는다.
- array와 유사하기 때문에, array-like object라고 부른다.
- index(0, 1, 2, 3...)를 통해서 값에 접근할 수 있다.
- push, pop...과 같은 array method를 사용할 수 없다.
- 함수에 전달된 인자를 item으로 갖는다.
아래 코드에서와 같이 arguments는 배열이 아니기 때문에, 배열에 내장되어있는 유용한 method를 사용할 수 없다.
function sum() {
console.log(arguments);
return arguments.reduce((accumulator, num) => { // error! argumets is not array
return accumulator + num;
});
}
sum(1, 2, 3, 4, 5); // [Arguments] { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
이 때 parameter로 전달받은 여러 argument를 하나의 배열로 만들어 주는 것이 rest parameter이다.
function sum(...nums) {
console.log(arguments);
console.log(nums)
return nums.reduce((accumulator, num) => { // no error! nums is array
return accumulator + num;
});
}
sum(1, 2, 3, 4, 5); // 15
// [Arguments] { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
// nums => [ 1, 2, 3, 4, 5 ]
일부 인자들만 하나의 배열에 담는 것도 가능하다.
function raceResult(gold, silver, bronze, ...everyoneElse) {
console.log(`GOLD: ${gold}`);
console.log(`SILVER: ${silver}`);
console.log(`BRONZE: ${bronze}`);
console.log(`THANKS TO: ${everyoneElse}`);
}
raceResult('taylor', 'harry', 'sigrid', 'louis', 'tammy');
/*
GOLD: taylor
SILVER: harry
BRONZE: sigrid
THANKS TO: [ louis,tammy ]
*/
2. Spread(...)
- rest parameter와 똑같이 생겼지만 완전히 다르다.
- rest는 params로 전달받은 인자들을 하나의 배열에 넣어주고, spread는 iterable이나 객체의 각 아이템을 꺼낸다.
- 함수의 인자로 배열이나 객체의 아이템을 각각 전달하고 싶을 때 사용하면 유용하다.
Function
함수의 인자로 spread 문법을 사용한 배열(뿐만 아니라 iterable)을 전달하면, 배열의 각 item이 개별적인 인자로서 함수에 전달된다.
const prices = [12.99, 13.50, 51.99, 8.99, 3.50];
Math.max(prices); // NaN
Math.max(...prices); // 51.99
console.log(..."hello") // h e l l o
Array
배열의 item으로 spread 문법을 사용한 배열(뿐만 아니라 iterable)을 전달하면, 문법을 사용한 배열의 각 item들이 새로운 배열의 item으로 복사된다.
const char = [...'hello'];
char; // [ 'h', 'e', 'l', 'l', 'o' ];
const dogs = ['🐶', '🐕🦺', '🐩', '🐕'];
const cats = ['🐈⬛', '🐈'];
const pets = [...dogs, ...cats];
const copiedDogs = [...dogs]; // dogs !== copiedDogs(stored in different memory cell)
pets; // ['🐶', '🐕🦺', '🐩', '🐕', '🐈⬛', '🐈']
Object
객체의 item으로 spread 문법을 사용한 객체(뿐만 아니라 iterable)를 전달하면, 문법을 사용한 객체의 각 property를 새로운 객체의 property로 복사할 수 있다.
const harry = {
age: 28,
country: 'UK',
};
const recentHarry = { ...harry, albumsNums: 3 };
recentHarry;
// { age: 28, country: 'UK', albumsNums: 3 }
여러 객체를 하나의 새로운 객체에 함께 담을 때 같은 key를 가지고 있다면 conflict이 발생하고, 이 때에는 나중에 전달된 객체의 key와 value가 최종적으로 복사된다.
const taylor = {
age: 31,
country: 'USA',
};
const singer = { ...recentHarry, ...taylor };
singer;
// { age: 31, country: 'USA', albumsNums: 3 }
3. De-structuring
Array
배열을 분해(de-structuring)하면, 배열안의 아이템을 각각 순서대로 꺼내서 개별적인 변수에 그 값을 할당할 수 있다. 이 때 원본 배열을 수정하지 않기 때문에 유용하다.
const scores = [100, 95, 80, 75, 70, 55, 40, 35];
const [gold, silver, bronze, ...everyoneElse] = scores;
gold; // scores[0], 100
silver; // scores[1], 95
bronze; // score[2], 80
everyoneElse; // [75, 70, 55, 40, 35]
Object
객체를 분해하면 배열 분해에서와 마찬가지로 개별적인 변수에 각 property를 꺼내서 할당할 수 있다. 이 때 객체에 아이템이 저장된 순서와 관계없이 값을 할당할 수 있기 때문에 배열 분해보다 더 유용하게 자주 사용된다.
const harry = {
age: 28,
country: 'UK',
albumsNums: 3,
email: 'harrystyles@gamil.com'
};
const {email, albumNums, age} = harry;
email; // 'harrystyles@gamil.com'
객체에 저장되어있는 key 값이 아니라, 다른 값으로 변수의 이름을 바꿀 수도 있다.
// renaming variable
const {country: bornCountry} = harry;
bornCountry; // 'UK'
countrt; // error! no ref
객체에 없는 key 값을 변수에 할당하면 undefined이 할당되는데, 이 때 defalut value를 지정함으로써 변수에 값을 추가할 수도 있다.
const { filmography: filmoNums = 0 } = harry;
filmoNums; // 0
Function
함수의 인자에 전달되는 값이 객체일 때 자주 사용된다. 특히 객체의 모든 property가 아니라 특정 property 값에만 접근해서 참조하고 싶을 때 유용하다.
const firstGuest = {
firstName: 'harry',
lastName: 'styles',
age: 28,
country: 'UK',
albumsNums: 3
}
function fullName( { firstName, lastName } ) { //de-structuring
return `${firstName} ${lastName}`;
}
function fullName2(person) {
return `${person.firstName} ${person.lastName}`;
}
fullName(firstGuest); // 'harry styles'
fullName2(firstGuest); // 'harry styles'
배열의 각 아이템이 객체일 때에도 다음과 같이 사용할 수 있다.
const singers = [
{
firstName: 'harry',
lastName: 'styles',
age: 28,
country: 'UK',
albumsNums: 3,
},
{
firstName: 'taylor',
lastName: 'swift',
age: 31,
country: 'USA',
albumsNums: 9,
},
];
singers.filter( singer => (singer.albumNums >=5) ); // [{firstName: taylor, ... , albumsNums: 9}]
singers.filter( ({ albumNums }) => albumNums >= 5 ); // same result
'Study > JavaScript' 카테고리의 다른 글
Testing, TDD (0) | 2022.09.05 |
---|---|
shallow vs. deep copy (0) | 2022.08.08 |
Hoisting (0) | 2022.05.25 |
Var (0) | 2022.05.25 |
Request & Response | API, JSON, fetch... (0) | 2022.04.17 |