--- title: Object.assign() slug: Web/JavaScript/Reference/Global_Objects/Object/assign tags: - ECMAScript 2015 - JavaScript - Method - Object - Довідка translation_of: Web/JavaScript/Reference/Global_Objects/Object/assign ---
Метод Object.assign()
призначено для копіювання у цільовий об'єкт всіх особистих (не успадкованих) перелічуваних властивостей одного або декількох об'єктів. Метод повертає цільовий об'єкт.
{{EmbedInteractiveExample("pages/js/object-assign.html")}}
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
Object.assign(target, ...sources)
target
sources
Цільовий об'єкт.
Властивості цільового об'єкта будуть заміщені властивостями вхідних об'єктів, якщо вони мають той самий ключ. Пізніші властивості вхідних об'єктів схожим чином заміщують більш ранні.
Метод Object.assign()
копіює лише перелічувані та особисті властивості з кожного джерела у цільовий об'єкт. Він використовує [[Get]]
на вхідних об'єктах та [[Set]]
на цільовому об'єкті, а отже, здійснює виклики гетерів і сетерів. Таким чином, він присвоює властивості, а не просто копіює чи визначає нові властивості. Ця особливість може зробити метод непридатним для приєднання нових властивостей до прототипу, якщо вхідні джерела містять гетери.
Для копіювання визначень властивостей разом з їх перелічуваністю у прототип натомість скористайтеся методами {{jsxref("Object.getOwnPropertyDescriptor()")}} та {{jsxref("Object.defineProperty()")}}.
Копіюються властивості обох типів: як {{jsxref("String","рядкові")}}, так і {{jsxref("Symbol","символьні")}}.
В разі помилки, наприклад, якщо властивість є недоступною для запису, викидається помилка {{jsxref("TypeError")}}, а об'єкт target
може бути змінений, якщо будь-які властивості були додані до викидання помилки.
Заувага: Object.assign()
не викидає помилок, якщо серед джерел є значення {{jsxref("null")}} чи {{jsxref("undefined")}}.
const obj = { a: 1 }; const copy = Object.assign({}, obj); console.log(copy); // { a: 1 }
Для створення глибокої копії необхідно скористатись альтернативними методами, тому що метод Object.assign()
копіює значення властивостей. Якщо значенням джерела буде посилання на об'єкт, метод скопіює лише значення посилання.
function test() { 'use strict'; let obj1 = { a: 0 , b: { c: 0}}; let obj2 = Object.assign({}, obj1); console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}} obj1.a = 1; console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}} console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}} obj2.a = 2; console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}} console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}} obj2.b.c = 3; console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}} console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}} // Глибока копія obj1 = { a: 0 , b: { c: 0}}; let obj3 = JSON.parse(JSON.stringify(obj1)); obj1.a = 4; obj1.b.c = 4; console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}} } test();
const o1 = { a: 1 }; const o2 = { b: 2 }; const o3 = { c: 3 }; const obj = Object.assign(o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 } console.log(o1); // { a: 1, b: 2, c: 3 }, змінено сам цільовий об'єкт
const o1 = { a: 1, b: 1, c: 1 }; const o2 = { b: 2, c: 2 }; const o3 = { c: 3 }; const obj = Object.assign({}, o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 }
Властивості перезаписуються однойменними властивостями інших об'єктів, що стоять далі в списку параметрів.
const o1 = { a: 1 }; const o2 = { [Symbol('foo')]: 2 }; const obj = Object.assign({}, o1, o2); console.log(obj); // { a : 1, [Symbol("foo")]: 2 } Object.getOwnPropertySymbols(obj); // [Symbol(foo)]
const obj = Object.create({ foo: 1 }, { // властивість foo належить до ланцюжка прототипів об'єкта obj bar: { value: 2 // bar є неперелічуваною властивістю }, baz: { value: 3, enumerable: true // baz є перелічуваною особистою властивістю } }); const copy = Object.assign({}, obj); console.log(copy); // { baz: 3 }
const v1 = 'абв'; const v2 = true; const v3 = 10; const v4 = Symbol('foo'); const obj = Object.assign({}, v1, null, v2, undefined, v3, v4); // Прості величини будуть загорнуті, null та undefined ігноруються. // Зауважте, лише рядкові обгортки можуть мати особисті неперелічувані властивості. console.log(obj); // { "0": "а", "1": "б", "2": "в" }
const 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, третє джерело також не буде скопійоване
const obj = { foo: 1, get bar() { return 2; } }; let copy = Object.assign({}, obj); console.log(copy); // { foo: 1, bar: 2 }, значенням copy.bar буде значення, що поверне геттер obj.bar // Ця функція присвоювання повністю скопіює дескриптори function completeAssign(target, ...sources) { sources.forEach(source => { let descriptors = Object.keys(source).reduce((descriptors, key) => { descriptors[key] = Object.getOwnPropertyDescriptor(source, key); return descriptors; }, {}); // За замовчуванням, метод Object.assign копіює перелічувані властивості типу Symbol також Object.getOwnPropertySymbols(source).forEach(sym => { let descriptor = Object.getOwnPropertyDescriptor(source, sym); if (descriptor.enumerable) { descriptors[sym] = descriptor; } }); Object.defineProperties(target, descriptors); }); return target; } var copy = completeAssign({}, obj); console.log(copy); // { foo:1, get bar() { return 2 } }
Наведений {{Glossary("Polyfill", "поліфіл")}} не підтримує символьних властивостей, позаяк ES5 не має такого типу:
if (typeof Object.assign != 'function') { // Має бути writable: true, enumerable: false, configurable: true Object.defineProperty(Object, "assign", { value: function assign(target, varArgs) { // .length функції дорівнює 2 'use strict'; if (target == null || target === undefined) { throw new TypeError('Cannot convert undefined or null to object'); } var to = Object(target); for (var index = 1; index < arguments.length; index++) { var nextSource = arguments[index]; if (nextSource != null && nextSource !== undefined) { for (var nextKey in nextSource) { // Запобігає помилок, коли hasOwnProperty заміщено if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; } } } } return to; }, writable: true, configurable: true }); }
Специфікація |
---|
{{SpecName('ESDraft', '#sec-object.assign', 'Object.assign')}} |
{{Compat("javascript.builtins.Object.assign")}}