Object.assign()

Este articulo necesita una revisión técnica. Cómo puedes ayudar.

Este articulo necesita una revisión editorial. Cómo puedes ayudar.

Esta traducción está incompleta. Por favor, ayuda a traducir este artículo del inglés.

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.

Resumen

El método Object.assign() es usado para copiar los valores de todas la propiedades propias enumerables de uno o más objetos fuente a un objeto destino. Regresará el objeto destino. 

Sintaxis

Object.assign(objetivo, ...fuentes)

Parámetros

Objetivo
El objeto destino.
Fuentes
Los objetos origen.

Valor de retorno

El objeto destino es regresado.

Descripción

Las propiedades in el objetivo será sobreescrita por propiedades en los recursos si estos tienen la misma clave. Propiedades posteriores de los recursos podrán reescribir las anteriores.

El método Object.assign() copia solo las propiedades enumerables y propias del objeto origen al objeto destino. Usa [[Get]] en la origen y [[Set]] en el destino, por lo que invocará los métodos de acceso y establecimiento (getters y setters). Por consiguiente asignará propiedades frente a solo copiar o definir propiedades nuevas. Esto puede hacer que sea inadecuado para fusionar propiedades nuevas en un prototipo si la fusión de fuentes contiene métodos de acceso (getters). Para copiar definiones de propiedades, incluyendo sus enumerabilidad, en prototipos, Object.getOwnPropertyDescriptor() y Object.defineProperty() debería ser usado en su lugar.

Ambos prototipos, StringSymbol, son copiados.

En caso de un error, por ejemplo si un prototipo es no tiene capacidad de escritura, un TypeError será arrojado, y el objeto objetivo se mantendrá sin cambios.

Note que Object.assign() no arroja una excepción sobre valores fuente nullundefined.

Ejemplos

Clonando un objeto

var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }

Advertencia para clonado profundo

Para clonar profundamente, necesitamos usar otra alternativa. Esto debido a que Object.assign() copia la referencia de la propiedad cuando se asignada es un objeto.

function test() {
  let a = { b: {c:4} , d: { e: {f:1}} }
  let g = Object.assign({},a)
  let h = JSON.parse(JSON.stringify(a));
  console.log(g.d) // { e: { f: 1 } }
  g.d.e = 32
  console.log('g.d.e set to 32.') // g.d.e set to 32.
  console.log(g) // { b: { c: 4 }, d: { e: 32 } }
  console.log(a) // { b: { c: 4 }, d: { e: 32 } }
  console.log(h) // { b: { c: 4 }, d: { e: { f: 1 } } }
  h.d.e = 54
  console.log('h.d.e set to 54.') // h.d.e set to 54.
  console.log(g) // { b: { c: 4 }, d: { e: 32 } }
  console.log(a) // { b: { c: 4 }, d: { e: 32 } }
  console.log(h) // { b: { c: 4 }, d: { e: 54 } }
}
test();

Fusionando objetos

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 }, objeto objetivo es cambiado en sí mismo.

Fusionando objetos con propiedades similares

var o1 = { a: 1, b: 1, c: 1 };
var o2 = { b: 2, c: 2 };
var o3 = { c: 3 };

var obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 

Las propiedades son sobreescritas por otros objetos que tienen las mismas propiedades en otros parámetros

Copiando propiedades de tipo símbolo

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

var obj = Object.assign({}, o1, o2);
console.log(obj); // { a: 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox)
Object.getOwnPropertySymbols(obj); // [Symbol(foo)]

Propiedades heredadas y propiedades no enumerables no pueden ser copiadas

var obj = Object.create({ foo: 1 }, { // foo es una propiedad heredada.
  bar: {
    value: 2  // bar es una propiedad no enumberable.
  },
  baz: {
    value: 3,
    enumerable: true  // baz es una propiedad propia enumerable.
  }
});

var copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }

Primitivos serán envueltos en objetos

var v1 = '123';
var v2 = true;
var v3 = 10;
var v4 = Symbol('foo')

var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); 
// Primitives will be wrapped, null and undefined will be ignored.
// Note, only string wrappers can have own enumerable properties.
console.log(obj); // { "0": "1", "1": "2", "2": "3" }

Excepciones interrumpirán la tarea de copiado andante

var target = Object.defineProperty({}, 'foo', {
  value: 1,
  writeable: false
}); // target.foo is a read-only property

Object.assign(target, { bar: 2 }, { foo2: 3, foo: 3, foo3: 3 }, { baz: 4 });
// TypeError: "foo" is read-only
// The Exception is thrown when assigning target.foo

console.log(target.bar);  // 2, the first source was copied successfully.
console.log(target.foo2); // 3, the first property of the second source was copied successfully.
console.log(target.foo);  // 1, exception is thrown here.
console.log(target.foo3); // undefined, assign method has finished, foo3 will not be copied.
console.log(target.baz);  // undefined, the third source will not be copied either.

Copiando métodos de acceso.

var obj = {
  foo: 1,
  get bar() {
    return 2;
  }
};

var copy = Object.assign({}, obj); 
console.log(copy); 
// { foo: 1, bar: 2 }, the value of copy.bar is obj.bar's getter's return value.

// This is a assign function can copy accessors.
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 } }

Polyfill

Este polyfill no soporta propiedades simbolo, en ES5 no se tienen simbolos de cualquier forma.

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

Especificaciones

Especificación Estado Comentario
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Object.assign' in that specification.
Standard Definición inicial

Compatibilidad de navegadores

Caracteristica Chrome Firefox (Gecko) Internet Explorer Opera Safari
Soporte básico 45 34 (34) No support No support No support
Caracteristica Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Soporte básico No support No support 34.0 (34) No support No support No support

Ver tambien

Etiquetas y colaboradores del documento

 Colaboradores en esta página: sgmonda, dzegarra, fortil, raerpo, uliseschino, mishelashala, fscholz
 Última actualización por: sgmonda,