[javascript] 개체 확산 대 개체 할당

options변수가 있고 기본값을 설정하고 싶다고 가정 해 봅시다 .

이 두 대안의 장점 / 단점은 무엇입니까?

객체 확산 사용

options = {...optionsDefault, ...options};

또는 Object.assign 사용

options = Object.assign({}, optionsDefault, options);

이것이 나를 놀라게 한 커밋 입니다.



답변

이것은 반드시 완전한 것은 아닙니다.

확산 구문

options = {...optionsDefault, ...options};

장점 :

  • 기본 지원이없는 환경에서 실행할 코드를 작성하는 경우, polyfill을 사용하는 대신이 구문을 컴파일 할 수 있습니다. (예를 들어, 바벨과 함께)

  • 덜 장황하다.

단점 :

  • 이 답변이 처음 쓰여졌을 때 표준화되지 않은 제안 . 제안서를 사용할 때 지금 코드를 작성하고 표준화를 진행함에 따라 표준화되지 않거나 변경되지 않는 경우 수행 할 작업을 고려하십시오. 이후 ES2018에서 표준화되었습니다.

  • 동적이 아닌 리터럴.


Object.assign()

options = Object.assign({}, optionsDefault, options);

장점 :

  • 표준화.

  • 동적. 예:

    var sources = [{a: "A"}, {b: "B"}, {c: "C"}];
    options = Object.assign.apply(Object, [{}].concat(sources));
    // or
    options = Object.assign({}, ...sources);

단점 :

  • 더 장황하다.
  • 기본 지원이없는 환경에서 실행할 코드를 작성하려면 polyfill해야합니다.

이것이 나를 놀라게 한 커밋입니다.

그것은 당신이 요구하는 것과 직접 관련이 없습니다. 해당 코드는을 사용하지 않았 으며 동일한 작업을 수행하는 Object.assign()사용자 코드 ( object-assign)를 사용하고있었습니다 . 그들은 Babel을 사용하여 코드를 컴파일하고 Webpack과 번들로 묶는 것처럼 보입니다. 그들은 분명히 object-assign빌드에 들어갈 종속성 으로 포함하는 것을 선호했습니다 .


답변

ECMAScript 2018에서는 참조 오브젝트 레스트 / 스프레드가 4 단계로 마무리됩니다. 제안은 여기 에서 찾을 수 있습니다 .

대부분의 객체 재설정 및 확산 작업은 동일한 방식으로, 주요 차이점은 spread는 속성을 정의하고 Object.assign ()이 속성을 설정 한다는 입니다. 이것은 Object.assign ()이 setter를 트리거한다는 것을 의미합니다.

이것 이외의 오브젝트 레스트 / 스프레드 1 : 1은 Object.assign ()에 매핑되고 배열 (반복 가능) 스프레드에 다르게 작동한다는 것을 기억할 가치가 있습니다. 예를 들어, 배열을 펼칠 때 null 값이 펼칩니다. 그러나 객체 스프레드를 사용하면 null 값이 자동으로 아무 것도 퍼지지 않습니다.

배열 (반복 가능) 스프레드 예

const x = [1, 2, null , 3];
const y = [...x, 4, 5];
const z = null;

console.log(y); // [1, 2, null, 3, 4, 5];
console.log([...z]); // TypeError

개체 확산 예

const x = null;
const y = {a: 1, b: 2};
const z = {...x, ...y};

console.log(z); //{a: 1, b: 2}

이는 Object.assign ()의 작동 방식과 일치하며 오류없이 null 값을 자동으로 제외합니다.

const x = null;
const y = {a: 1, b: 2};
const z = Object.assign({}, x, y);

console.log(z); //{a: 1, b: 2}


답변

스프레드 연산자와 Object.assign현재 답변에서 언급되지 않은 것의 큰 차이점 은 스프레드 연산자가 소스 객체의 프로토 타입을 대상 객체에 복사하지 않는다는 것입니다. 객체에 속성을 추가하고 객체의 인스턴스를 변경하지 않으려면을 사용해야 Object.assign합니다. 아래 예제는 이것을 보여 주어야합니다.

const error = new Error();
error instanceof Error // true

const errorExtendedUsingSpread = {
  ...error,
  ...{
    someValue: true
  }
};
errorExtendedUsingSpread instanceof Error; // false

const errorExtendedUsingAssign = Object.assign(error, {
  someValue: true
});
errorExtendedUsingAssign instanceof Error; // true


답변

다른 사람들이 언급했듯이,이 글을 쓰는 순간에 Object.assign()폴리 필이 ...필요 하고 객체 스프레드 에는 작동하기 위해 약간의 트랜스 필링 (그리고 아마도 폴리 필도 필요)이 필요합니다.

이 코드를 고려하십시오.

// Babel wont touch this really, it will simply fail if Object.assign() is not supported in browser.
const objAss = { message: 'Hello you!' };
const newObjAss = Object.assign(objAss, { dev: true });
console.log(newObjAss);

// Babel will transpile with use to a helper function that first attempts to use Object.assign() and then falls back.
const objSpread = { message: 'Hello you!' };
const newObjSpread = {...objSpread, dev: true };
console.log(newObjSpread);

둘 다 동일한 출력을 생성합니다.

다음은 Babel에서 ES5 로의 출력입니다.

var objAss = { message: 'Hello you!' };
var newObjAss = Object.assign(objAss, { dev: true });
console.log(newObjAss);

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var objSpread = { message: 'Hello you!' };
var newObjSpread = _extends({}, objSpread, { dev: true });
console.log(newObjSpread);

이것은 지금까지 나의 이해입니다. Object.assign()객체 확산 ...이 아직없는 곳에서 실제로 표준화되었습니다 . 유일한 문제는 전자에 대한 브라우저 지원과 미래에 대한 브라우저 지원입니다.

여기 코드를 가지고 놀아

도움이 되었기를 바랍니다.


답변

객체 스프레드 연산자 (…)는 브라우저에서 작동하지 않습니다. 아직 ES 사양의 일부가 아니며 제안 일뿐입니다. 유일한 옵션은 Babel (또는 이와 유사한 것)로 컴파일하는 것입니다.

보다시피 Object.assign ({})에 대한 구문 설탕 일뿐입니다.

내가 볼 수있는 한, 이것들은 중요한 차이점입니다.

  • Object.assign은 대부분의 브라우저에서 작동합니다 (컴파일없이).
  • ... 개체가 표준화되지 않았습니다
  • ... 실수로 오브젝트를 변경하지 않도록 보호
  • ... 브라우저없이 Object.assign을 polyfill합니다.
  • ... 같은 생각을 표현하기 위해 더 적은 코드가 필요하다

답변

“스프레드 오브젝트 병합”ES 기능, 브라우저 및 생태계에서 도구를 통해 상태를 요약하고 싶습니다.

투기

브라우저 : Chrome, SF, Firefox 곧 (버전 60, IIUC)

  • Chrome 60에서 제공되는 ‘스프레드 속성’에 대한 브라우저 지원이 시나리오를 포함하여 .
  • 이 시나리오에 대한 지원은 현재 Firefox (59)에서 작동하지 않지만 DOES는 Firefox Developer Edition에서 작동합니다. 그래서 나는 그것이 Firefox 60에 제공 될 것이라고 믿습니다.
  • Safari : 테스트되지 않았지만 Kangax는 Desktop Safari 11.1에서는 작동하지만 SF 11에서는 작동하지 않는다고 말합니다.
  • iOS Safari : teseted는 아니지만 Kangax는 iOS 11.3에서는 작동하지만 iOS 11에서는 작동하지 않는다고 말합니다.
  • 아직 가장자리에 없습니다

도구 : 노드 8.7, TS 2.1

연결

코드 샘플 (호환성 테스트의 두 배)

var x = { a: 1, b: 2 };
var y = { c: 3, d: 4, a: 5 };
var z = {...x, ...y};
console.log(z); // { a: 5, b: 2, c: 3, d: 4 }

다시 :이 샘플을 작성할 때이 샘플은 Chrome (60+), Firefox Developer Edition (Firefox 60의 미리보기) 및 노드 (8.7+)에서 변환없이 작동합니다.

왜 대답해야합니까?

나는 원래 질문 후 2.5 을 쓰고 있습니다. 그러나 나는 똑같은 질문을했고 이것이 Google이 보낸 곳입니다. 나는 긴 꼬리를 향상시키는 SO의 사명의 노예입니다.

이것이 “배열 확산”구문의 확장이기 때문에 Google에 매우 어려워 호환성 테이블에서 찾기가 어렵다는 것을 알았습니다. 내가 찾을 수있는 가장 가까운 것은 Kangax “속성 확산”입니다 이지만,이 테스트에는 같은 식으로 두 개의 스프레드가 없습니다 (병합 아님). 또한 제안서 / 초안 / 브라우저 상태 페이지의 이름은 모두 “속성 스프레드”를 사용하지만 커뮤니티가 제안서 다음에 “개체 병합”에 대한 스프레드 구문을 사용하기 위해 도착한 “첫 번째 주체”인 것 같습니다. (Google이 왜 그렇게 어려운지 설명 할 수 있습니다.) 따라서 다른 사람들이이 특정 기능에 대한 링크를보고 업데이트하고 컴파일 할 수 있도록 여기에 찾은 결과를 문서화합니다. 나는 그것이 붙잡기를 바란다. 사양 및 브라우저에 상륙한다는 소식을 알리십시오.

마지막으로이 정보를 주석으로 추가했지만 저자의 원래 의도를 깨뜨리지 않고는 정보를 편집 할 수 없었습니다. 특히 @RichardSchulte를 수정하려는 의도를 잃지 않으면 @ChillyPenguin의 의견을 편집 할 수 없습니다. 그러나 몇 년 후 Richard는 (내 의견으로는) 옳았습니다. 그래서 나는이 답변을 씁니다. 오래된 답변에 결국 견인력을 갖기를 기대합니다 (몇 년이 걸릴 수 있지만 결국 긴 꼬리 효과가 있습니다).


답변

참고 : 확산은 Object.assign 주위의 구문 설탕이 아닙니다. 그들은 배후에서 크게 다르게 작동합니다.

Object.assign은 setter를 새 객체에 적용하지만 Spread는 적용하지 않습니다. 또한 객체는 반복 가능해야합니다.

복사이
시점에서 개체의 값이 필요하고 해당 값이 개체의 다른 소유자가 변경 한 내용을 반영하지 않게하려면이 옵션을 사용하십시오.

변경 불가능한 버전은 변경 불가능한 속성으로 전달 될 수 있으므로 복사는 항상 변경 불가능한 오브젝트를 처리 할 수 ​​있도록하기 위해 항상 변경 불가능한 특성을 복사하도록 오브젝트의 단순 사본을 작성하는 데 사용하십시오.

할당
할당은 복사와 반대입니다. Assign은 값을 복사하거나 유지하지 않고 인스턴스 변수에 직접 값을 지정하는 setter를 생성합니다. assign 속성의 getter를 호출하면 실제 데이터에 대한 참조가 반환됩니다.