본문 바로가기

항해99_10기/105일의 TIL & WIL

[TIL] [5주차] [20221209] object literal에서 spread operator

Spread Operator

 

Spread syntax (...) - JavaScript | MDN

The spread (...) syntax allows an iterable, such as an array or string, to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected. In an object literal, the spread syntax enumerates the propert

developer.mozilla.org

In an object literal, the spread syntax enumerates the properties of an object and adds the key-value pairs to the object being created.

 

mdn에 spread operator를 검색했는데, 바로 코드블럭 위에 저렇게 obejct literal로 사용하면 properties를 늘어 놓고, 생성되는 객체에 key-value 쌍을 추가할 수 있다고 되어 있다…! (진작 볼걸ㅠㅠ)

아래와 같이, iterable object가 아닌 obejct를 spread하려고 하면 syntexError를 일으킨다.

const obj = { key1: 'value1' };
const array = [...obj]; // TypeError: obj is not iterable

 

반대로, 아래와 같이 iterable object를 object literal 안에서 spread 하면, iterable object의 own properties를 enumerate 한다.

const array = [1, 2, 3];
const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 }

 

강의에서는 soket.io를 사용해 같은 페이지에 있는 유저 수를 카운트하기 위해서 위의 저 코드를 사용했는데, 객체에 spread operator를 reduce 메서드에 저렇게 적용하니까 이해가 안 가서 한참을 봤다.(ㅠㅠ)

Object.values(socketIdMap).reduce((value, url) => {
    return {
      ...value,    // {...value}를 하는 것임, value는 accumulator임
      [url]: value[url] ? value[url] + 1 : 1,
    };
  }, {});

// obejct literal 안에서는 일반 object도 spread 연산자를 사용해서 enumerate 할 수 있음
const obj = {key1: 1, key2: 2}
const cloneObj = {...obj} // shallow cloning

 

하지만, object literal 안에서 spread를 하면, shallow-clone (prototype을 제외하고 복제)된다. 만약, prototype까지 모두 복제하고 싶다면, Object.assign()을 이용할 수 있다.

Object.assign()의 경우, target obejct에 대해 setter를 trigger한다. (spread 연산자는 못함)

const objectAssign = Object.assign({ set foo(val) { console.log(val); } }, { foo: 1 });
// Logs "1"; objectAssign.foo is still the original setter

const spread = { set foo(val) { console.log(val); }, ...{ foo: 1 } };
// Nothing is logged; spread.foo is 1

 

Obejct.assign() 함수를 spread 연산자를 사용해서 재구현하는 방법도 있다. 함수의 인자로 일반 객체를 spread하면, 객체가 object 안에 들어간다. 이를 다시 reduce 메서드를 사용해서 object literal 안에서 spread 해주면, Object.assign()을 재구현 한 것이다.

const obj1 = { foo: 'bar', x: 42 };
const obj2 = { foo: 'baz', y: 13 };
const merge = (...objects) => objects.reduce((acc, cur) => ({ ...acc, ...cur }));

const mergedObj1 = merge(obj1, obj2);
// { foo: 'baz', x: 42, y: 13 }