일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Java8
- 자바
- 그래프
- 알고리즘
- LEVEL2
- Brute-force
- baekjoon
- backtracking
- 네트워크
- 모던자바
- 백트래킹
- DFS
- DP
- java
- programmers
- 스프링
- 프로젝트
- back-end
- BFS
- TDD
- 코틀린
- lambda
- algorithm
- 백준
- OS
- 자료구조
- 운영체제
- kotlin
- 프로그래머스
- Spring
- Today
- Total
요깨비's LAB
[Javascript, ES6] 4. 매개변수 기본값, Rest 파라미터, Spread 문법, Rest/Spread 프로퍼티 본문
[Javascript, ES6] 4. 매개변수 기본값, Rest 파라미터, Spread 문법, Rest/Spread 프로퍼티
요깨비 2019. 12. 11. 12:22
1. 매개 변수 기본값 (Default Parameter Value)
함수를 호출할 때 매개변수의 개수만큼 인수를 전달하는 것이 일반적이지만 그렇지 않은 경우에도 에러가 발생하지는
않습니다. 함수는 매개변수의 인수의 개수를 체크하지 않습니다. 인수가 부족한 경우, 매개변수의 값은 undefined입니다.
function sum(x,y) {
return x + y;
}
console.log(sun(1)); // NaN
따라서 매개변수에 적절한 인수가 전달되었는지 함수 내부에서 확인할 필요가 있습니다.
function sum(x, y) {
// 매개변수의 값이 falsy value인 경우, 기본값을 할당한다.
x = x || 0;
y = y || 0;
return x + y;
}
console.log(sum(1)); // 1
console.log(sum(1,2)); // 3
ES6에서는 매개변수 기본값을 사용하여 함수 내에서 수행하던 인수 체크 및 초기화를 간소화할 수 있습니다. 매개변수
기본값은 매개변수에 인수를 전달하지 않았을 경우에만 유효합니다.
function sum(x=0, y=0) {
return x + y;
}
console.log(sum(1)); // 1
console.log(sum(1,2)); // 3
매개변수 기본값은 함수 정의 시 선언한 매개변수 개수를 나타내는 함수 객체의 length 프로퍼티와 arguments 객체에
영향을 주지 않습니다.
function foo(x,y = 0) {
console.log(arguments);
}
console.log(foo.length); // 1
sum(1); // Arguments { '0' : 1 }
sum(1,2); // Arguments { '0' : 1, '1' : 2 }
2. Rest 파라미터
2.1 기본 문법
Rest 파라미터(Rest Parameter, 나머지 매개변수)는 매개변수 이름 앞에 세개의 점 ... 을 붙여서 정의한 매개변수입니다.
Rest 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달받습니다.
function foo ( ... rest ) {
console.log(Array.isArray(rest)); // true
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);
function bar(param1, param2, ...rest) {
console.log(param1); // 1
console.log(param2); // 2
console.log(rest); // [3,4,5]
}
bar(1, 2, 3, 4, 5);
Rest 파라미터는 이름 그대로 먼저 선언된 파라미터에 할당된 인수를 제외한 나머지 인수들이 모두 배열에 담겨 할당됩니다.
따라서 Rest 파라미터는 반드시 마지막 파라미터여야 합니다.
function foo( ...rest, param1, param2) { }
foo(1,2,3,4,5); // SyntaxError: Rest parameter must be 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.2 arguments와 rest 파라미터
ES5에서는 인자의 개수를 사전에 알 수 없는 가변 인자 함수의 경우, arguments 객체를 통해 인수를 확인합니다. arguments 객체는 함수 호출 시 전달된 인수(argument)들의 정보를 담고 있는 순회가능한(iterable) 유사 배열 객체이며
함수 내부에서 지역 변수처럼 사용할 수 있습니다.
arguments 프로퍼티는 현재 일부 브라우저에서 지원하고 있지만 ES3부터 deprecated 되었습니다.
Function.arguments와 같은 사용 방법은 권장되지 않으며 함수 내부에서 지역변수처럼 사용할 수 있는 arguments 객체를
참조합시다.
// ES5
var foo = function() {
console.log(arguments);
};
foo(1, 2); // { '0' : 1, '1' : 2 }
가변 인자 함수는 파라미터를 통해 인수를 전달받는 것이 불가능하므로 arguments 객체를 활용하여 인수를 전달받습니다.
하지만 arguments 객체는 유사 배열 객체이므로 Function.prototype.call을 사용해야 하는 번거로움이 있습니다.
// ES5
function sum() {
/*
가변 인자 함수는 arguments 객체를 통해 인수를 전달받는다.
유사 배열 객체인 arguments 객체를 배열로 변환한다.
*/
var array = Array.prototype.slice.call(arguments);
return array.reduce(function (pre, cur) {
return pre + cur;
});
}
console.log(sum(1,2,3,4,5)); // 15
ES6에서는 rest 파라미터를 사용하여 가변 인자의 목록을 배열로 전달받을 수 있습니다. 이를 통해 유사 배열인 arguments 객체를 배열로 변환하는 번거로움을 피할 수 있습니다.
// ES6
function sum( ...args ) {
console.log(arguments); // Arguments(5) [1, 2, 3, 4, 5, callee: ( ...), Symbol.iterator): f]
console.log(Array.isArray(args)); // true
return args.reduce((pre, cur) => pre + cur);
}
console.log(sum(1,2,3,4,5)); // 15
하지만 ES6의 화살표 함수에는 함수 객체의 arguments 프로퍼티가 없습니다. 따라서 화살표 함수로 가변 인자 함수를
구현해야 할 때는 반드시 rest 파라미터를 사용해야 합니다.
var normalFunc = function() {};
console.log(normalFunc.hasOwnProperty('arguments')); // true
const arrowFunc = () => {};
console.log(arrowFunc.hasOwnProperty('arguments)); // false
3. Spread 문법
Spread 문법(Spread Syntax, ... )은 대상을 개별 요소로 분리합니다. Spread 문법의 대상은 이터러블이어야 합니다.
// ... [1, 2, 3]은 [1, 2, 3]을 개별 요소로 분리한다 -> 1, 2, 3
console.log(...[1, 2, 3]); // 1, 2, 3
// 문자열은 이터러블이다.
console.log(... 'Hello'); // H e l l o
// Map과 Set은 이터러블이다.
console.log(... new Map([['a', '1'],['b', '2']])); // [ 'a', '1' ] [ 'b', '2' ]
console.log(... new Set([1, 2, 3])); // 1 2 3
// 이터러블이 아닌 일반 객체는 Spread 문법의 대상이 될 수 없다.
console.log(... { a: 1, b: 2 });
// TypeError: Found non-callable @@iterator
3.1 함수의 인수로 사용하는 경우
배열을 분해하여 배열의 각 요소를 파라미터에 전달하고 싶은 경우, Functionprototype.apply를 사용하는게 일반적입니다.
// ES5
function foo(x, y, z) {
console.log(x); // 1
console.log(y); // 2
console.log(z); // 3
}
// 배열을 분해하여 배열의 각 요소를 파라미터에 전달하려고 한다.
const arr = [1, 2, 3];
// apply 함수의 2번째 인수(배열)는 분해되어 함수 foo의 파라미터에 전달된다.
foo.apply(null, arr);
// foo.call(null, 1, 2, 3);
ES6의 Spread 문법( ... )을 사용한 배열을 인수로 함수에 전달하면 배열의 요소를 분해하여 순차적으로 파라미터에
할당합니다.
// ES6
function foo(x, y, z) {
console.log(x); // 1
console.log(y); // 2
console.log(z); // 3
}
// 배열을 foo 함수의 인자로 전달하려고 한다.
const arr = [1, 2, 3];
/*
... [1, 2, 3]는 [1, 2, 3]을 개별 요소로 분리한다 -> 1, 2, 3
spread 문법에 의해 분리된 배열의 요소는 개별적인 인자로서 각각의 매개변수에 전달된다.
*/
foo(... arr);
앞에서 살펴본 Rest 파라미터는 Spread 문법을 사용하여 파라미터를 정의한 것을 의미합니다!
형태가 동일하여 혼동할 수 있으므로 주의해야 합니다.
/*
Spread 문법을 사용한 매개변수 정의 ( = Rest 파라미터)
... rest는 분리된 요소들을 함수 내부에 배열로 전달한다.
*/
function foo(param, ...rest) {
console.log(param); // 1
console.log(rest); // [2, 3]
}
foo(1,2,3);
/*
Spread 문법을 사용한 인수
배열 인수는 분리되어 순차적으로 매개변수에 할당
*/
function bar(x, y, z) {
console.log(x); // 1
console.log(y); // 2
console.log(z); // 3
}
// ...[1, 2, 3]은 [1, 2, 3]을 개별 요소로 분리한다 -> 1, 2, 3
// spread 문법에 의해 분리된 배열의 요소는 개별적인 인자로서 각각의 매개변수에 전달된다
bar(... [1, 2, 3]);
Rest 파라미터는 반드시 마지막 파라미터여야 하지만 Spread 문법을 사용한 인수는 자유롭게 사용할 수 있습니다.
// ES6
function foo(v, w, x, y, z) {
console.log(v); // 1
console.log(w); // 2
console.log(x); // 3
console.log(y); // 4
console.log(z); // 5
}
// ... [2, 3]은 [2, 3]을 개별 요소로 분리한다 -> 2, 3
// spread 문법에 의해 분리된 배열의 요소는 개별적인 인자로서 각각의 매개변수에 전달된다.
foo(1, ... [2, 3], 4, ... [5]);
3.2 배열에서 사용하는 경우
Spread 문법을 배열에서 사용하면 보다 간결하고 가독성 좋게 표현할 수 있습니다.
3.2.1 concat
ES5에서 기존 배열의 요소를 새로운 배열 요소의 일부로 만들고 싶은 경우, 배열 리터럴 만으로 해결할 수 없고
concat 메소드를 사용해야 합니다.
// ES5
var arr = [1, 2, 3];
console.log(arr.concat([4, 5, 6])); // [1, 2, 3, 4, 5, 6]
Spread 문법을 사용하면 배열 리터럴 만으로 기존 배열의 요소를 새로운 배열 요소의 일부로 만들 수 있습니다.
// ES6
const arr = [1, 2, 3];
// ... arr은 [1, 2, 3]을 개별 요소로 분리한다.
console.log(... arr, 4, 5, 6); // [1, 2, 3, 4, 5, 6]
3.2.2 push
ES5에서 기존 배열에 다른 배열의 개별 요소를 각각 push하려면 아래와 같은 방법을 사용합니다.
// ES5
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
// apply 메소드의 2번째 인자는 배열. 이것은 개별 인자로 push 메소드에 전달된다.
Array.prototype.push.apply(arr1, arr2);
console.log(arr1); // [1, 2, 3, 4, 5, 6]
Spread 문법을 사용하면 보다 간편하게 표현할 수 있습니다.
// ES6
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
// ... arr2는 [4, 5, 6]을 개별 요소로 분리한다.
arr1.push(... arr2); // == arr1.push(4,5,6);
console.log(arr1); // [1, 2, 3 ,4 ,5 ,6]
3.2.3 splice
ES5에서 기존 배열에 다른 배열의 개별 요소를 삽입하려면 아래와 같은 방법을 사용합니다.
// ES5
var arr1 = [1, 2, 3, 6];
var arr2 = [4, 5];
/*
apply 메소드의 2번째 인자는 배열. 이것은 개별 인자로 splicae 메소드에 전달된다.
[3,0].concat(arr2) -> [3, 0, 4, 5]
arr1.splice(3, 0, 4, 5) -> arr1[3]부터 0개의 요소를 제거하고 그자리에 새로운 요소(4, 5)를 추가한다.
*/
Array.prototype.splice.apply(arr1, [3,0].concat(arr2));
console.log(arr1); // [1, 2, 3, 4, 5, 6]
Spread 문법을 사용하면 보다 간편하게 표현할 수 있습니다.
// ES6
const arr1 = [1, 2, 3, 6];
const arr2 = [4, 5];
// ...arr2는 [4, 5]를 개별 요소로 분리한다.
arr1.splice(3, 0, ...arr2); // == arr1.splice(3, 0, 4, 5);
console.log(arr1); // [1, 2, 3, 4, 5, 6]
3.2.4 copy
ES5에서 기존 배열을 복사하기 위해서는 slice 메소드를 사용합니다.
// ES5
var arr = [1, 2, 3];
var copy = arr.slice();
console.log(copy); // [1, 2, 3]
// copy를 변경한다.
copy.push(4);
console.log(copy); // [1, 2, 3, 4]
// arr은 변경되지 않는다
console.log(arr);
Spread 문법을 사용하면 보다 간편하게 배열을 복사할 수 있습니다.
// ES6
const arr = [1, 2, 3];
// ...ar은 [1, 2, 3]을 개별 요소로 분리한다.
const copy = [...arr];
console.log(copy); // [1,2,3]
// copy를 변경한다.
copy.push(4);
console.log(copy); // [1, 2, 3, 4]
// arr은 변경되지 않는다.
console.log(arr); // [1, 2, 3];
* Spread 문법과 Object.assign은 원본을 shallow copy합니다. Deep Copy를 위해서는 lodash의 deepClone을 사용!
Spread 문법을 사용하면 유사 배열 객체(Array-like Object)를 배열로 손쉽게 변환할 수 있습니다.
const htmlCollection = document.getElementByTagName('li');
// 유사 배열인 HTMLCollection을 배열로 변환한다.
const newArray = [...htmlCollection]; // Spread 문법
// ES6의 Array.from 메소드를 사용할 수도 있다.
// const newArray = Array.from(htmlCollection);
4. Rest/Spread Property => 추후에 정리
https://poiemaweb.com/es6-extended-parameter-handling
'자바스크립트 > ES6' 카테고리의 다른 글
[Javascript, ES6] 3. 화살표 함수(Arrow Function) (0) | 2019.12.04 |
---|---|
[Javascript, ES6] 2. 템플릿 리터럴(Template Literal) (0) | 2019.12.04 |
[Javascript, ES6] 1. let, const와 블록 레벨 스코프 (0) | 2019.12.03 |