Объект распространения и объекта.назначить
допустим, у меня есть options переменная и я хочу установить некоторое значение по умолчанию.
в чем преимущество / недостаток этих двух вариантов?
использование объекта spread
options = {...optionsDefault, ...options};
или с помощью объекта.назначить
options = Object.assign({}, optionsDefault, options);
Это commit что заставило меня задуматься.
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
- https://github.com/tc39/proposal-object-rest-spread
- эта функция языка это предложение стадии 4, что означает, что он был объединен в спецификацию языка ES, но еще не широко реализован.
браузеры: в 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
- NodeJS поддержал, поскольку 8.7 (через Kangax). Подтвердил на 9.8, когда я тестировал локально.
- TypeScript поддерживает его с тех пор 2.1, ток 2.8
ссылки
пример кода (используется как тест на совместимость)
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