MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/MDN-dev-survey

This is a new technology, part of the ECMAScript 2015 (ES6) standard.
This technology's specification has been finalized, but check the compatibility table for usage and implementation status in various browsers.

Sommario

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.

Sintassi

Object.assign(target, ...sources)

Parametri

target
L'oggetto di destinazione.
sources
Gli oggetti di origine.

Descrizione

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 Object.defineProperty().

Vengono copiate sia le proprietà aventi come nomi delle stringhe che dei simboli.

In caso di errore, per esempio se una proprietà non è sovrascrivibile, viene generato un TypeError, e l'oggetto di destinazione rimane invariato.

Notare che Object.assign() non genera un errore se uno dei valori di origine è null o undefined.

Esempi

Clonare un oggetto

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() non succede più questo problema:

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 }

Unire più oggetti

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

Copiare proprietà aventi come indici dei simboli

var o1 = { a: 1 };
var o2 = { [Symbol("foo")]: 2 };

var obj = Object.assign({}, o1, o2);
console.log(obj); // { a: 1, Symbol(foo): 2 }

Le proprietà ereditate o non-enumerabili non vengono copiate

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 }

I valori primitivi vengono trasformati in oggetti

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" }

Se viene generata un eccezione, la funzione si ferma

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

Copiare i getter

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 } }

Polyfill

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;
    }
  });
}

Specifiche

Specifica Stato Commenti
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Object.assign' in that specification.
Standard Definizione iniziale.

Compatibilità con i browser

Funzionalità Chrome Edge Firefox (Gecko) Internet Explorer Opera Safari
Supporto di base 45 (Yes) 34 (34) No support 32 9
Funzionalità Android Chrome for Android Edge Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Supporto di base No support 45 (Yes) 34.0 (34) No support No support (Yes)

Vedi anche

Tag del documento e collaboratori

 Hanno collaborato alla realizzazione di questa pagina: narsenico, kdex, claudio-destro, gpbl, nicolo-ribaudo
 Ultima modifica di: narsenico,