Объект распространения и объекта.назначить



допустим, у меня есть options переменная и я хочу установить некоторое значение по умолчанию.



в чем преимущество / недостаток этих двух вариантов?



использование объекта spread



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


или с помощью объекта.назначить



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


Это commit что заставило меня задуматься.

607   7  

7 ответов:

это не обязательно является исчерпывающим.

распространение синтаксис

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

плюсы:

  • если вы создаете код для выполнения в средах без собственной поддержки, вы можете просто скомпилировать этот синтаксис (в отличие от использования polyfill). (С Вавилоном, например.)

  • менее многословен.

недостатки:

  • A предложение, не стандартизировано. (Подумайте, что бы вы сделали, если бы написали его сейчас, и он не стандартизирован.)

  • буквальный, а не динамический.


Object.assign()

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

плюсы:

  • стандартизированы.

  • динамические. Пример:

    var sources = [{a: "A"}, {b: "B"}, {c: "C"}];
    options = Object.assign.apply(Object, [{}].concat(sources));
    
  • более подробную информацию.

недостатки:

  • если авторский код для выполнения в средах без собственной поддержки вам нужно заполнить polyfill.

это фиксация, которая заставила меня задуматься.

это не имеет прямого отношения к тому, что вы спрашиваете. Этот код не использовал Object.assign(), он использовал пользовательский код (object-assign), что делает то же самое. Они, похоже, компилируют этот код с Babel (и связывают его с Webpack), о чем я и говорил: синтаксис, который вы можете просто скомпилировать. По-видимому, они предпочли это тому, чтобы включить object-assign как зависимость, которая войдет в их сборку.

для эталонного объекта rest / spread завершается в ECMAScript 2018 как этап 4. Предложение можно найти здесь.

по большей части сброс объекта и распространение работают одинаково, ключевое различие заключается в том, что распространение определяет свойства, в то время как объект.назначение() устанавливает их. Это означает объект.назначьте () триггеры-сеттеры.

стоит помнить, что кроме этого, объект rest/spread 1:1 сопоставляется с объектом.назначить() и действует по-разному массив (итерационный) спред. Например, при распространении массива распространяются нулевые значения. Однако с помощью объекта spread нулевые значения молча распространяются на ничто.

Array (Iterable) Spread Example

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

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

Пример Распространения Объекта

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

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

Это согласуется с тем, как объект.assign () будет работать, оба молча исключают нулевое значение без ошибок.

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

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

оператор распространения объекта (...) не работает в браузерах, потому что он еще не является частью какой-либо спецификации ES, просто предложение. Единственный вариант-скомпилировать его с Babel (или что-то подобное).

как вы можете видеть, это просто синтаксический сахар над объектом.назначать.)}{(

насколько я могу видеть, это важные различия.

    как уже упоминали другие, в этот момент написания,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);
    

    эти оба производят тот же результат.

    вот выход из Вавилона, в 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" spread object merge", в браузерах и в экосистеме с помощью инструментов.

    Spec

    браузеры: в Chrome, в SF, Firefox скоро (ver 60, IIUC)

    • поддержка браузера для "свойства распространения" поставляется в Chrome 60, в том числе и этот сценарий.
    • поддержка этого сценария не работает в текущем Firefox (59), но работает в моем 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) и Node (8.7+).

    Зачем Отвечать?

    Я пишу это 2.5 лет после первоначального вопроса. Но у меня был тот же вопрос, и вот куда меня послал Google. Я раб миссии SO, чтобы улучшить длинный хвост.

    Так как это расширение синтаксиса "array spread", мне было очень трудно google, и трудно найти в таблицах совместимости. Самое близкое, что я мог найти это Kangax "собственность", но этот тест не имеет двух спредов в одном выражении (не слияние). Кроме того, имя в предложениях/черновиках/страницах состояния браузера все используют "распространение свойств", но мне кажется, что это был "первый принцип", к которому сообщество пришло после предложений использовать синтаксис распространения для "слияния объектов". (Что может объяснить, почему так трудно google.) Поэтому я документирую свое открытие здесь, чтобы другие могли просматривать, обновлять и компилировать ссылки на эту конкретную функцию. Я надеюсь, что он поймает. Пожалуйста, помогите распространить новости о его посадке в спецификации и в браузерах.

    наконец, я бы добавил эту информацию в качестве комментария, но я не мог редактировать их, не нарушая оригинал авторов намерение. В частности, я не могу редактировать комментарий @ChillyPenguin без потери его намерения исправить @RichardSchulte. Но годы спустя Ричард оказался прав (на мой взгляд). Поэтому я пишу этот ответ вместо этого, надеясь, что он в конечном итоге получит тягу к старым ответам (может занять годы, но это то, что длинный хвост эффект-это все о, в конце концов).

    Примечание: распространение-это не просто синтаксический сахар вокруг объекта.назначить. Они действуют очень по-разному за кулисами.

    Это теперь часть ES6, таким образом унифицировано, и также документировано на MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator

    Это очень удобно в использовании и имеет большой смысл наряду с деструктуризацией объекта.

    единственное оставшееся преимущество, перечисленное выше, - это динамические возможности объекта.assign (), однако это так же просто, как распространение массива внутри литерального объекта. В скомпилированном виде babel output использует именно то, что демонстрируется с объектом.назначить()

    поэтому правильным ответом было бы использовать распространение объекта, поскольку он теперь стандартизирован, широко используется (см. react, redux и т. д.), прост в использовании и имеет все функции объекта.назначить()

    Comments

      Ничего не найдено.