Object.assign()
Метод Object.assign() используется для копирования значений всех собственных перечисляемых свойств из одного или более исходных объектов в целевой объект. После копирования он возвращает целевой объект.
Синтаксис
Object.assign(target, . sources)
Параметры
Возвращаемое значение
Возвращается получившийся целевой объект.
Описание
Метод Object.assign() копирует из исходных объектов в целевой объект только перечисляемые и собственные свойства. Он использует внутренний метод [[Get]] на исходных объектах и внутренний метод [[Set]] на целевом объекте, так что он также вызывает геттеры и сеттеры. Именно поэтому он присваивает свойства вместо простого копирования или определения новых свойств. Это поведение может сделать метод непригодным для вливания новых свойств в прототип, если вливаемые исходные объекты содержат геттеры. Вместо него для копирования в прототипы определений свойств, включая признак их перечисляемости, следует использовать методы Object.getOwnPropertyDescriptor() и Object.defineProperty() .
Копируются свойства типов как String , так и Symbol .
В случае возникновения ошибки, например, когда свойство является незаписываемым, возбуждается исключение TypeError , а целевой объект target остаётся неизменным.
Обратите внимание, что метод Object.assign() не выкидывает исключения, если в качестве исходных значений выступают null или undefined .
Примеры
Пример: клонирование объекта
var obj = a: 1 >; var copy = Object.assign(>, obj); console.log(copy); //
Пример: слияние объектов
var o1 = a: 1 >; var o2 = b: 2 >; var o3 = c: 3 >; var obj = Object.assign(o1, o2, o3); console.log(obj); // console.log(o1); // < a: 1, b: 2, c: 3 >, изменился и сам целевой объект.
Пример: копирование символьных свойств
var o1 = a: 1 >; var o2 = [Symbol("foo")]: 2 >; var obj = Object.assign(>, o1, o2); console.log(obj); //
Пример: наследуемые и неперечисляемые свойства не копируются
var obj = Object.create( foo: 1 >, // foo является унаследованным свойством. bar: value: 2, // bar является неперечисляемым свойством. >, baz: value: 3, enumerable: true, // baz является собственным перечисляемым свойством. >, >, ); var copy = Object.assign(>, obj); console.log(copy); //
Пример: примитивы оборачиваются в объекты
var v1 = "123"; var v2 = true; var v3 = 10; var v4 = Symbol("foo"); var obj = Object.assign(>, v1, null, v2, undefined, v3, v4); // Примитивы будут обёрнуты, а null и undefined - проигнорированы. // Обратите внимание, что собственные перечисляемые свойства имеет только обёртка над строкой. console.log(obj); //
Пример: исключения прерывают текущую задачу копирования
var target = Object.defineProperty(>, "foo", value: 1, writable: false, >); // target.foo является свойством только-для-чтения Object.assign(target, bar: 2 >, foo2: 3, foo: 3, foo3: 3 >, baz: 4 >); // TypeError: "foo" is read-only // При присваивании свойству target.foo выбрасывается исключение console.log(target.bar); // 2, первый исходный объект успешно скопировался. console.log(target.foo2); // 3, первое свойство второго исходного объекта успешно скопировалось. console.log(target.foo); // 1, здесь было выброшено исключение. console.log(target.foo3); // undefined, метод assign завершился, свойство foo3 не скопировалось. console.log(target.baz); // undefined, третий исходный объект так же не скопировался.
Пример: копирование методов доступа
var obj = foo: 1, get bar() return 2; >, >; var copy = Object.assign(>, obj); console.log(copy); // < foo: 1, bar: 2 >, значением свойства copy.bar является значение, возвращаемое геттером obj.bar. // Такой вариант функции присваивания позволяет копировать методы доступа. function myAssign(target, . sources) sources.forEach((source) => Object.defineProperties( target, Object.keys(source).reduce((descriptors, key) => descriptors[key] = Object.getOwnPropertyDescriptor(source, key); return descriptors; >, >), ); >); return target; > var copy = myAssign(>, obj); console.log(copy); // < foo:1, get bar() < return 2 >>
Полифил
Этот полифил не поддерживает символьные свойства, поскольку ES5 всё равно не поддерживает символы:
if (!Object.assign) Object.defineProperty(Object, "assign", enumerable: false, configurable: true, writable: true, value: function (target, firstSource) "use strict"; if (target === undefined || target === null) throw new TypeError("Cannot convert first argument to object"); > var to = Object(target); for (var i = 1; i arguments.length; i++) var nextSource = arguments[i]; if (nextSource === undefined || nextSource === null) continue; > var keysArray = Object.keys(Object(nextSource)); for ( var nextIndex = 0, len = keysArray.length; nextIndex len; nextIndex++ ) var nextKey = keysArray[nextIndex]; var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); if (desc !== undefined && desc.enumerable) to[nextKey] = nextSource[nextKey]; > > > return to; >, >); >
Спецификации
Specification |
---|
ECMAScript Language Specification # sec-object.assign |
Совместимость с браузерами
BCD tables only load in the browser
Смотрите также
JavaScript объединить 2 объекта
Или еще вот таким образом можно «объединить тела» двух таких методов.
const a1 = < a: "50", b: "51", c: () =>, d: () => , e: () => >; const a2 = < a: "5", b: "6", c: () =>, d: () => >; const a3 = merge(a1, a2) //console.log(a3) console.log(a3.a) console.log(a3.b) a3.c() a3.d() a3.e() // function merge(a1, a2) < const re = /^[^<]+\<|\>$/g const o = Object.keys(a2).reduce((o, k) => < if (typeof a2[k] == 'function') < const a = [] if (a1[k]) a.push(a1[k].toString().replace(re, '')) a.push(a2[k].toString().replace(re, '')) o[k] = new Function(a.join(', ')) >else < o[k] = a2[k] >return o >, <>) Object.keys(a1).reduce((o, k) => a2[k] ? o : ( o[k] = new Function(a1[k].toString().replace(re, '')), o ), o) return o >
Но все это сделано только в рамках приведенных ТСом объектов. Не более того.
Слияние — JS: Объекты
Слияние (merge) — операция над объектами, выполняющая их объединение. Она появляется там, где необходимо данные одного объекта перенести в другой объект.
Слияние часто используется при работе с веб-формами. Например, когда пользователь меняет свои персональные данные в настройках аккаунта, измененные данные приходят в приложение в виде объекта. Данные из этого объекта нужно перенести в объект пользователя. Так происходит обновление пользователя:
// Такой пользователь есть в системе const user = name: 'Tirion', email: 'support@hexlet.io', age: 44 >; // Из формы пришли данные const data = name: 'Tirion 2', age: 33 >; // В результате должно получиться // < name: 'Tirion 2', email: 'support@hexlet.io', age: 33 >;
Решение в лоб — перенести каждое свойство отдельно:
user.name = data.name; user.age = data.age; // Где-то тут сохраняем пользователя в базе данных
Прямой перенос хорошо работает, когда данных мало и их структура не меняется. Если же данных много или в разные моменты времени могут приходить разные данные, то это превращается в кучу одинакового кода:
if (Object.hasOwn(data, 'name')) user.name = data.name; > // И так нужно перечислить все возможные свойства
С помощью слияния (часто говорят «мержа») мы можем сократить все до одной строчки:
Object.assign(user, data); console.log(user); // => < name: 'Tirion 2', email: 'support@hexlet.io', age: 33 >;
Метод Object.assign() берёт объект, переданный первым параметром, и переносит в него всё из объектов, переданных остальными параметрами. В нашей ситуации это один объект, переданный вторым параметром.
Слияние работает так. Если какое-то свойство было только в первом объекте, то оно остается тем, что и было. Если свойство присутствует во втором (и далее) объекте, то оно записывается в первый независимо от того, было оно там или нет. Поэтому, если свойство присутствовало и в первом объекте и во втором, то оно будет перезаписано значением из второго объекта:
const obj1 = a: 'a', b: 'b' >; const obj2 = c: 'c', b: 'v' >; Object.assign(obj1, obj2); console.log(obj1); // =>
У метода Object.assign() есть одно ограничение: он выполняет только поверхностное слияние. Вложенные объекты не сравниваются, а просто заменяются:
const obj1 = a: a: 1 > > const obj2 = a: b: 1 > > Object.assign(obj1, obj2); console.log(obj1); // => < a: < b: 1 >> // пример глубокого (рекурсивного) слияния // используется метод merge() библиотеки lodash import _ from 'lodash'; _.merge(obj1, obj2); // => < a: < a: 1, b: 1 >>
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях:
Объединить свойства двух или более объектов в JavaScript
В этом посте мы обсудим, как объединить свойства двух или более объектов в JavaScript.
1. Использование оператора спреда
Простое решение — использовать Оператор спреда чтобы расширить свойства указанных объектов до буквальных объектов (ES2018). Вот рабочий пример:
var object = < . . . obj1 , . . . obj2 >;
console . log ( object ) ;
Решение возвращает новый объект массива и может быть легко расширено для объединения любого количества объектов.
Обратите внимание, что свойства последующих объектов будут полностью перезаписаны свойствами предыдущих объектов с тем же ключом. Это верно и для следующих растворов.
2. Использование Object.assign() функция
The Object.assign() метод копирует все свойства из одного или нескольких исходных объектов в целевой объект и возвращает целевой объект. Вы можете использовать это как: