--- title: Object.assign() slug: Web/JavaScript/Reference/Global_Objects/Object/assign translation_of: Web/JavaScript/Reference/Global_Objects/Object/assign ---
La funzione Object.assign()
copia tutte le proprietà enumerabili da uno o più oggetti di origine in un oggetto di destinazione. Restituisce l'oggetto di destinazione.
Object.assign(target, ...sources)
target
sources
La funzione Object.assign()
copia soltanto le proprietà enumerabili appartenenti agli oggetti di origine (non quelle che fanno parte della loro catena dei prototipi) in un oggetto di destinazione. Utilizza [[Get]]
sugli oggetti di origine e [[Put]]
su quello di destinazione, quindi invoca getter e setter, quando presenti. Quindi assegna le proprietà, piuttosto che limitarsi a copiarle o a definirne di nuove. Ciò lo rende inadatto per aggiungere nuove proprietà in un prototipo se le proprietà vengono copiate da un oggetto contenente getter o setter. Per copiare le proprietà, incluso il fatto di essere enumerabili o no, in un prototipo, bisognerebbe usare {{jsxref("Object.defineProperty()")}}.
Vengono copiate sia le proprietà aventi come nomi delle {{jsxref("String", "stringhe")}} che dei {{jsxref("Symbol", "simboli")}}.
In caso di errore, per esempio se una proprietà non è sovrascrivibile, viene generato un {{jsxref("TypeError")}}, e l'oggetto di destinazione rimane invariato.
Notare che Object.assign()
non genera un errore se uno dei valori di origine è {{jsxref("null")}} o {{jsxref("undefined")}}.
Si potrebbe pensare di clonare un oggetto semplicemente assegnandolo ad un altra variabile:
var obj = { a: 1 }; var copia = obj; console.log(obj, copia); // { a: 1 }, { a: 1 } obj.a = 2; console.log(obj, copia); // { a: 2 }, { a: 2 } // Ma copia.a non valeva 1?
Utilizzando Object.assign()
il problema non si verifica:
var obj = { a: 1 }; var copia = Object.assign({}, obj); console.log(obj, copia); // { a: 1 }, { a: 1 } obj.a = 2; console.log(obj, copia); // { a: 2 }, { a: 1 }
var o1 = { a: 1 }; var o2 = { b: 2 }; var o3 = { c: 3 }; var obj = Object.assign(o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 } console.log(o1); // { a: 1, b: 2, c: 3 }, le proprietà vengono aggiunte all'oggetto di destinazione
var o1 = { a: 1 }; var o2 = { [Symbol("foo")]: 2 }; var obj = Object.assign({}, o1, o2); console.log(obj); // { a: 1, Symbol(foo): 2 }
var obj = Object.create({ foo: 1 }, { // foo è una proprietà ereditata bar: { value: 2 // bar è una proprietà non-enumerabile }, baz: { value: 3, enumerable: true // baz è una proprietà enumerabile } }); var copia = Object.assign({}, obj); console.log(copia); // { baz: 3 }
var v1 = '123'; var v2 = true; var v3 = 10; var v4 = Symbol("foo"); var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); // I valori primitivi vengono trasformati in oggetti, null e undefined ignorati. // Notare che solo le stringhe hanno proprietà enumerabili console.log(obj); // { "0": "1", "1": "2", "2": "3" }
var destinazione = Object.defineProperty({}, 'foo', { value: 1, writeable: false }); // destinazione.foo non può essere modificata Object.assign(destinazione, { bar: 2 }, { foo2: 3, foo: 3, foo3: 3 }, { baz: 4 }); // TypeError: "foo" is read-only // L'eccezione viene generata quando si modifica destinazione.foo console.log(destinazione.bar); // 2, Il primo oggetto viene copiato correttamente console.log(destinazione.foo2); // 3, La prima proprietà del secondo oggetto viene copiata correttamente console.log(destinazione.foo); // 1, L'eccezione viene generata qui console.log(destinazione.foo3); // undefined, la funzione ha già finto di copiare console.log(destinazione.baz); // undefined, la funzione ha già finto di copiare
var obj = { foo: 1, get bar() { return 2; } }; var copia = Object.assign({}, obj); console.log(copia); // { foo: 1, bar: 2 }, non viene copiato il getter obj.bar, ma il suo valore // Questa funzione copia mantenendo getter e setter 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 copia = myAssign({}, obj); console.log(copia); // { foo:1, get bar() { return 2 } }
Questo polyfill non supporta i simboli (che comunque non sono supportati da ECMAScript 5):
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; } nextSource = Object(nextSource); 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; } }); }
Specifica | Stato | Commenti |
---|---|---|
{{SpecName('ES2015', '#sec-object.assign', 'Object.assign')}} | {{Spec2('ES2015')}} | Definizione iniziale. |
Funzionalità | Chrome | Edge | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
Supporto di base | {{CompatChrome("45")}} | {{CompatVersionUnknown}} | {{CompatGeckoDesktop("34")}} | {{CompatNo}} | {{CompatOpera("32")}} | {{CompatSafari("9")}} |
Funzionalità | Android | Chrome for Android | Edge | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|---|
Supporto di base | {{CompatNo}} | {{CompatChrome("45")}} | {{CompatVersionUnknown}} | {{CompatGeckoMobile("34")}} | {{CompatNo}} | {{CompatNo}} | {{CompatVersionUnknown}} |