Object.assign: примеры (JAVASCRIPT)

Object.assign: принципы работы и практическое применение
Раздел: Объекты, Копирование
Object.assign(target (object), ...sources (object)): object

Основные сведения о Object.assign

Метод Object.assign() в JavaScript используется для копирования значений всех перечислимых собственных свойств из одного или нескольких исходных объектов в целевой объект. Этот метод возвращает измененный целевой объект.

Когда используется: Функция применяется для поверхностного копирования объектов, объединения нескольких объектов в один, создания копий конфигураций или добавления свойств в существующие объекты.

Аргументы:

  • target - целевой объект, в который будут скопированы свойства. Обязательный аргумент.
  • ...sources - один или несколько исходных объектов, чьи свойства копируются в целевой объект. Аргумент является необязательным; если он не передан, метод вернет объект target без изменений.

Возвращаемое значение: Измененный целевой объект target.

Метод копирует только перечислимые и собственные свойства исходных объектов. Значения копируются поверхностно: если свойство является объектом, копируется ссылка на этот объект, а не сам объект. Свойства с геттерами в исходных объектах копируются как обычные значения.

Базовые примеры использования

Копирование свойств одного объекта:

const target = { a: 1 };
const source = { b: 2, c: 3 };
const result = Object.assign(target, source);
console.log(result);
console.log(target);
{ a: 1, b: 2, c: 3 }
{ a: 1, b: 2, c: 3 }

Объединение нескольких объектов:

const obj1 = { a: 1 };
const obj2 = { b: 2 };
const obj3 = { c: 3 };
const result = Object.assign({}, obj1, obj2, obj3);
console.log(result);
{ a: 1, b: 2, c: 3 }

Перезапись свойств: Свойства с одинаковыми именами перезаписываются значениями из последующих объектов.

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const result = Object.assign(target, source);
console.log(result);
{ a: 1, b: 4, c: 5 }

Копирование примитивов: Примитивы-источники оборачиваются в объекты, копируются только их собственные свойства.

const result = Object.assign({}, null, undefined, 123, 'abc', true);
console.log(result);
{}

Похожие функции в JavaScript

Spread оператор (...): Позволяет поверхностно копировать или объединять объекты с более лаконичным синтаксисом. Не изменяет исходные объекты.

const obj1 = { a: 1 };
const obj2 = { b: 2 };
const merged = { ...obj1, ...obj2 };

Object.create(): Создает новый объект с указанным прототипом и свойствами. Используется для наследования прототипов, а не для копирования свойств.

Object.defineProperties(): Определяет новые или изменяет существующие свойства на объекте, позволяя задавать их атрибуты (перечислимость, конфигурируемость).

JSON.parse(JSON.stringify()): Используется для глубокого копирования объектов, но работает только с JSON-совместимыми данными (не копирует функции, undefined, Symbol).

Выбор метода: Object.assign предпочтителен для поверхностного копирования, когда требуется изменить целевой объект. Spread оператор лучше подходит для создания нового объекта без мутаций. Для глубокого копирования используют специализированные функции или библиотеки.

Типичные ошибки

Поверхностное копирование: Метод выполняет поверхностное копирование, что может привести к неожиданному изменению вложенных объектов.

const target = { nested: { a: 1 } };
const source = { nested: { b: 2 } };
const result = Object.assign(target, source);
console.log(result.nested);
// Изменение вложенного объекта в source отразится на result
source.nested.b = 99;
console.log(result.nested);
{ b: 2 }
{ b: 99 }

Неверное использование для глубокого клонирования: Object.assign не предназначен для глубокого копирования.

const original = { a: { b: 1 } };
const clone = Object.assign({}, original);
clone.a.b = 2;
console.log(original.a.b);
2

Копирование свойств-геттеров: Геттеры вычисляются, и копируется их значение, а не сам геттер.

const source = {
  get value() { return 42; }
};
const target = Object.assign({}, source);
console.log(Object.getOwnPropertyDescriptor(target, 'value'));
{ value: 42, writable: true, enumerable: true, configurable: true }

Пропуск символовых свойств: Object.assign копирует только строковые ключи и символы, если они являются перечислимыми.

Изменения в последних версиях

Метод Object.assign был введен в стандарте ECMAScript 2015 (ES6). С тех пор его спецификация остается стабильной, без существенных изменений в поведении.

В последних версиях JavaScript введены альтернативные способы копирования и объединения объектов, такие как spread оператор, который часто используется как более удобная замена для Object.assign при создании новых объектов. Однако Object.assign сохраняет свою актуальность, когда требуется явно изменить существующий объект.

Современные движки JavaScript оптимизируют производительность Object.assign, но важно учитывать, что его использование для создания множества промежуточных объектов может влиять на производительность.

Расширенные примеры

Создание объекта с методами и свойствами по умолчанию:

Пример javascript
const defaults = {
  color: 'red',
  size: 'medium'
};

function createButton(options) {
  return Object.assign({}, defaults, options);
}

const button = createButton({ color: 'blue', label: 'OK' });
console.log(button);
{ color: 'blue', size: 'medium', label: 'OK' }

Добавление свойств к экземпляру класса:

Пример javascript
class User {
  constructor(name) {
    this.name = name;
  }
}

const user = new User('Иван');
Object.assign(user, { age: 30, role: 'admin' });
console.log(user);
User { name: 'Иван', age: 30, role: 'admin' }

Использование с Symbol свойствами: Object.assign копирует символьные свойства, если они перечислимы.

Пример javascript
const id = Symbol('id');
const source = { [id]: 123, name: 'test' };
const target = Object.assign({}, source);
console.log(target[id]);
123

Очистка объекта с сохранением прототипа:

Пример javascript
function clearObject(obj) {
  const proto = Object.getPrototypeOf(obj);
  const cleared = Object.assign(Object.create(proto), {});
  Object.setPrototypeOf(obj, Object.getPrototypeOf(cleared));
  Object.keys(obj).forEach(key => delete obj[key]);
  return obj;
}

Копирование с преобразованием свойств:

Пример javascript
const source = { a: 1, b: 2, c: 3 };
const target = {};
Object.assign(target, ...Object.keys(source).map(key => ({ [key]: source[key] * 2 })));
console.log(target);
{ a: 2, b: 4, c: 6 }

Работа с неперечислимыми свойствами: Object.assign игнорирует неперечислимые свойства и свойства из цепочки прототипов.

Пример javascript
const parent = { inherited: 'value' };
const source = Object.create(parent, {
  ownProp: { value: 1, enumerable: true },
  hiddenProp: { value: 2, enumerable: false }
});

const target = Object.assign({}, source);
console.log(target);
{ ownProp: 1 }

Аналоги в других языках программирования

Python: Метод update() словарей – изменяет исходный словарь, добавляя пары ключ-значение из другого словаря.

target = {'a': 1}
source = {'b': 2}
target.update(source)
print(target)
{'a': 1, 'b': 2}

PHP: array_merge() – объединяет массивы, перезаписывая элементы с одинаковыми строковыми ключами.

$target = ['a' => 1];
$source = ['b' => 2];
$result = array_merge($target, $source);
print_r($result);
Array ( [a] => 1 [b] => 2 )

Java: putAll() в HashMap – копирует все отображения из указанной карты в текущую.

HashMap target = new HashMap<>();
target.put("a", 1);
HashMap source = new HashMap<>();
source.put("b", 2);
target.putAll(source);

C#: Метод CopyTo() или конструктор Dictionary – копирует элементы коллекции в массив или создает новый словарь на основе существующего.

Основное отличие от JavaScript: во многих языках аналогичные методы работают только со словарями или массивами, а не с произвольными объектами. Object.assign работает с любыми объектами, копируя их перечислимые свойства.

JS Object.assign function comments

En
Object.assign Copies values from one or more source objects to a target object