2019-07-12 ES6(2) - rest파라미터, spread연산자

파라미터 기본값(Default Parameter Value)

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

console.log(plus()); // 0
console.log(plus(1,2)); // 3
  • parameter가 없을때 default parameter를 줄 수 있다.

Rest파라미터

  • rest파라미터는 정해지지 않은 인수를 배열로 나타낼 수 있게 해준다.
  • Rest파라미터는 Spread연산자를 사용하여 파라미터를 정의한것. Rest파라미터를 사용하면 인수의 리스트를 함수 내부에서 배열로 받는다.

구문

function f(a, b, ...theArgs) {
	// ...
}

  • 마지막 파라미터 앞에 …을 붙여 모든 나머지 인수를 배열로 대체한다. ``` function sum(…theArgs) { return theArgs.reduce((previous, current) => { return previous + current; }); }

function foo(param, …rest) { console.log(param); console.log(rest); }

foo(1,2,3,4,5,); console.log(“======”); function foo2(param1, param2, param3, …rest) { console.log(param1); console.log(param2); console.log(param3); console.log(rest); }

foo2(1,2,3,4,5,6,7,8); // result 1 [ 2, 3, 4, 5 ] ====== 1 2 3 [ 4, 5, 6, 7, 8 ]

- rest파라미터는 반드시 마지막이여야 한다.

## arguments와 rest파라미터

### 차이점
- arguments객체는 실제 배열이 아니고 rest 파라미터는 Array인스턴스로서 sort, map, forEach와 같은 배열메서드를 사용할 수 있다.
- arguments객체는 함수 호출 시 전달된 인수들의 정보를 가지고 있는 순회가능한(iterable) 유사 배열 객체(array-like object)이며 함수 내부에서 지역변수 처럼 사용한다.

// es5 arguments var foo3 = function() { var array = Array.prototype.slice.call(arguments); return array.reduce(function(pre, cur) { return pre + cur; }); };

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

============= // rest argument function sum(…args) { console.log(arguments); console.log(Array.isArray(args)); return args.reduce((pre, cur) => pre + cur); }

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

// using arrow function let sum2 = (…rest) => { console.log(rest); return rest.reduce((pre, cur) => pre + cur); };

console.log(sum2(1,2,3,4,5,6));

- arrow function에서는 arguments 프로퍼티가 없다. 따라서 화살표 함수로 가변인자를 구현할 때는 반드시 rest 파라미터가 필요하다.

## Spread연산자
### 구문

// 함수호출 myFunction(…iterableObj);

// 배열 리터럴과 문자열 […iterableObj, ‘4’, ‘five’, 6];

// 객체 리터럴 let obj = { …obj}


// …[1,2,3]은 [1,2,3]을 개별 요소로 분리한다. console.log(…[1,2,3]);

// 문자열은 이터러블이다.

console.log(… ‘Hello’);

// Map과 Set은 이터러블이다. console.log(…new Map([[‘a’,1], [‘b’, 2]])); console.log(…new Set([1,2,3])); // result 1 2 3 H e l l o [ ‘a’, 1 ] [ ‘b’, 2 ] 1 2 3

// 이터러블이 아닌 일반 객체는 Spread 연산자의 피연산자가 될 수 없다. console.log(…{ a: 1, b: 2 }); // TypeError: Found non-callable @@iterator

- 이터러블이 아닌 일반 객체는 Spread 연산자의 피연산자가 될 수 없다.

### 함수의 인수로 사용하는 경우

// es5 function foo(x, y, z) { console.log(x); console.log(y); console.log(z); }

const arr = [1, 2, 3];

foo.apply(null, arr);

- ES5에서 배열의 요소들을 파라미터로 전달을 할때 Function.prototype.apply를 사용하는 것이 일반적이였다.
- ES6의 Spread(...)를 사용한 배열을 인수로 함수에 전달하면 순차적으로 전달.

function foo(x, y, z) { console.log(x); console.log(y); console.log(z); }

const arr = [1, 2, 3]; foo(…arr);


- Spread연산자를 사용한 매개변수 정의(rest 파라미터) ...rest는 분리된 요소들을 함수 내부에 배열로 전달한다.
- Spread 연산자를 사용한 인수. 배열 인수는 분리되어 순차적으로 할다. foo(...[1,2,3]);


### 배열에서 사용하는 경우

- 기존 배열의 요소를 새로운 배열의 일부로 만들때, concat을 사용했었다.

//ES5 let arr = [1, 2, 3, 4, 5]; console.log(arr.concat(6,7,8,9));

//ES6 console.log([…arr, 6,7,8,9,10,11]);

//result [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]

- spread연산자를 사용하면 배열 리터럴 만으로 기존 배열의 요소를 새로운 배열 요소의 일부로 만들 수 있다.


#### 배열의 푸쉬

let arr2 = [6,7,8,9,10]; Array.prototype.push.apply(arr1, arr2); console.log(“es5 arr1 : “,arr1);

arr1.push(…arr2); console.log(“es6 arr1: “, arr1);


### apply()대체

//Before function myFunction(x, y, z) { }; var args = [1,2,3]; myFunction.apply(null, args);

// After function myFunction(x, y, z) { } var args = [0, 1, 2]; myFunction(…args);


### new연산자에서도 사용가능

function applyAndNew(contructor, args) { function partial() { return constructor.apply(this, args); } if (typeof constructor.prototype === ‘object’) { partial.prototype = Object.create(constructor.create); } return partial; }

function myConstructor () { console.log(“arguments.length: “ + arguments.length); console.log(arguments); this.prop1=”val1”; this.prop2=”val2”; };

var myArguments = [“hi”, “how”, “are”, “you”, “mr”, null]; var myConstructorWithArguments = applyAndNew(myConstructor, myArguments);

console.log(new myConstructorWithArguments); // (internal log of myConstructor): arguments.length: 6 // (internal log of myConstructor): [“hi”, “how”, “are”, “you”, “mr”, null] // (log of “new myConstructorWithArguments”): {prop1: “val1”, prop2: “val2”}

//After var dateFields = [1993,0,1]; var d = new Date(…dateFields);


### 배열에서의 사용

var parts = [‘shoulders’, ‘knees’]; var lyrics = [‘head’, …parts, ‘and’, ‘toes’]; // [“head”, “shoulders”, “knees”, “and”, “toes”]

- push, slice를 안써도 된다.

//배열의 복사 var arr = [1, 2, 3]; var arr2 = […arr]; // arr.slice() 와 유사 arr2.push(4);

// arr2 은 [1, 2, 3, 4] 이 됨 // arr 은 영향을 받지 않고 남아 있음

// 배열을 연결 var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; // arr2 의 모든 항목을 arr1 에 붙임 arr1 = arr1.concat(arr2);

to

var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1 = […arr1, …arr2]; // arr1 은 이제 [0, 1, 2, 3, 4, 5]



### 객체리터럴의 전개

var obj1 = { foo: ‘bar’, x: 42 }; var obj2 = { foo: ‘baz’, y: 13 };

var clonedObj = { …obj1 }; // Object { foo: “bar”, x: 42 }

var mergedObj = { …obj1, …obj2 }; // Object { foo: “baz”, x: 42, y: 13 }


var obj1 = { foo: ‘bar’, x: 42 }; var obj2 = { foo: ‘baz’, y: 13 }; const merge = ( …objects ) => ( { …objects } );

var mergedObj = merge ( obj1, obj2); // Object { 0: { foo: ‘bar’, x: 42 }, 1: { foo: ‘baz’, y: 13 } }

var mergedObj = merge ( {}, obj1, obj2); // Object { 0: {}, 1: { foo: ‘bar’, x: 42 }, 2: { foo: ‘baz’, y: 13 } } ```

느낀점

spread, rest파라미터로 인해 객체를 파싱하고 값을 전달하는데 편할거 같다. 특히 JSON값을 응답받았을때 그걸 그반으로 객체화를 시킬때 용이하겠다. java에서는 json응답에 대한 Dto객체를 만들때 하나하나 다 만들고 객체화를 시켰었는데, 그때 안쓰는 프로퍼티까지 다 객체화를 한 후에야 dto로 변경이 가능했었는데, js의 객체리터럴 전개를 활용하면 이 부분을 간략하게 할 수 있을거같다 :) 기대가 된다.

Written on July 12, 2019