¿Es posible desestructurarse sobre un objeto existente? (Javascript ES6)


Por ejemplo, si tengo dos objetos:

var foo = {
  x: "bar",
  y: "baz"
}

Y

var oof = {}

Y quería transferir los valores x e y de foo a oof. ¿Hay alguna forma de hacerlo usando la sintaxis de desestructuración es6?

Tal vez algo como:

oof{x,y} = foo
Author: Bergi, 2015-04-14

14 answers

Aunque feo y un poco repetitivo, puedes hacer

({x: oof.x, y: oof.y} = foo);

Que leerá los dos valores del objeto foo, y los escribirá en sus respectivas ubicaciones en el objeto oof.

Personalmente prefiero leer

oof.x = foo.x;
oof.y = foo.y;

O

['x', 'y'].forEach(prop => oof[prop] = foo[prop]);

Sin embargo.

 43
Author: loganfsmyth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-07 17:22:26

No, desestructuring no admite expresiones de miembros en abreviaturas, sino solo nombres de propiedad simples en el momento actual. Ha habidoconversaciones sobre este tipo de debate, pero ninguna propuesta lo convertirá en ES6.

Usted podría ser capaz de utilizar Object.assign sin embargo, si no necesita todas las propiedades propias, todavía puede hacer

var foo = …,
    oof = {};
{
    let {x, y} = foo;
    Object.assign(oof, {x, y})
}
 28
Author: Bergi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-26 14:00:06

IMO esta es la forma más fácil de lograr lo que estás buscando:

let { prop1, prop2, prop3 } = someObject;
let data = { prop1, prop2, prop3 };

  // data === { prop1: someObject.prop1, ... }

Básicamente, desestructure en variables y luego use la abreviatura del inicializador para crear un nuevo objeto. No hay necesidad de Object.assign

Creo que esta es la forma más legible, de todos modos. Por la presente, puede seleccionar los accesorios exactos de someObject que desee. Si tiene un objeto existente en el que solo desea fusionar los apoyos, haga algo como esto:

let { prop1, prop2, prop3 } = someObject;
let data = Object.assign(otherObject, { prop1, prop2, prop3 });
    // Makes a new copy, or...
Object.assign(otherObject, { prop1, prop2, prop3 });
    // Merges into otherObject

Otra forma, posiblemente más limpia, de escribirlo is:

let { prop1, prop2, prop3 } = someObject;
let newObject = { prop1, prop2, prop3 };

// Merges your selected props into otherObject
Object.assign(otherObject, newObject);

Uso esto para POST muchas solicitudes donde solo necesito unos pocos datos discretos. Pero, estoy de acuerdo en que debería haber una línea única para hacer esto.

 9
Author: Zfalen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-09 00:15:22

Aparte de Object.assign está la sintaxis de propagación de objetos que es una propuesta de Etapa 2 para ECMAScript.

var foo = {
  x: "bar",
  y: "baz"
}

var oof = { z: "z" }

oof =  {...oof, ...foo }

console.log(oof)

/* result 
{
  "x": "bar",
  "y": "baz",
  "z": "z"
}
*/

Pero para usar esta característica necesitas usar stage-2 o transform-object-rest-spread plugin para babel. Aquí hay una demostración en babel con stage-2

 7
Author: Gaafar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-15 14:33:58

Complemento de BabelJS

Si está utilizando BabelJS ahora puedes activar mi plugin babel-plugin-transform-object-from-destructuring (consulte el paquete npm para la instalación y el uso ).

Tuve el mismo problema descrito en este hilo y para mí fue muy agotador cuando creas un objeto a partir de una expresión desestructurante, especialmente cuando tienes que cambiar el nombre, agregar o eliminar una propiedad. Con este plugin el mantenimiento de tales escenarios es mucho más fácil para usted.

Objeto ejemplo

let myObject = {
  test1: "stringTest1",
  test2: "stringTest2",
  test3: "stringTest3"
};
let { test1, test3 } = myObject,
  myTest = { test1, test3 };

Se puede escribir como:

let myTest = { test1, test3 } = myObject;

Ejemplo de matriz

let myArray = ["stringTest1", "stringTest2", "stringTest3"];
let [ test1, , test3 ] = myArray,
  myTest = [ test1, test3 ];

Se puede escribir como:

let myTest = [ test1, , test3 ] = myArray;
 4
Author: Matthias Günter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-05 07:40:58

Es totalmente posible. Pero no en una declaración.

var foo = {
    x: "bar",
    y: "baz"
};
var oof = {};
({x: oof.x, y: oof.y} = foo); // {x: "bar", y: "baz"}

(Note el paréntesis alrededor de la declaración.) Pero ten en cuenta que la legibilidad es más importante que el código-golf :).

Fuente: http://exploringjs.com/es6/ch_destructuring.html#sec_assignment-targets

 3
Author: Hampus Ahlgren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-14 23:22:13

Puedes usar la reestructuración para eso de esta manera:

const foo = {x:"a", y:"b"};
const {...oof} = foo; // {x:"a", y:"b"} 

O combinar ambos objetos si oof tiene valores:

const foo = {x:"a", y:"b"};
let oof = {z:"c"}
oof = Object.assign({}, oof, foo)
 1
Author: CampSafari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-09 09:17:59

SECO

var a = {a1:1, a2: 2, a3: 3};
var b = {b1:1, b2: 2, b3: 3};

const newVar = (() => ({a1, a2, b1, b2})).bind({...a, ...b});
const val = newVar();
console.log({...val});
// print: Object { a1: 1, a2: 2, b1: 1, b2: 2 }

O

console.log({...(() => ({a1, a2, b1, b2})).bind({...a, ...b})()});
 1
Author: user5733033,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-07 01:56:03

Esto funciona en chrome 53.0.2785.89

let foo = {
  x: "bar",
  y: "baz"
};

let oof = {x, y} = foo;

console.log(`oof: ${JSON.stringify(oof)});

//prints
oof: {
  "x": "bar",
  "y": "baz"
}
 0
Author: user1577390,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-09 22:05:03

Se me ocurrió este método:

exports.pick = function pick(src, props, dest={}) {
    return Object.keys(props).reduce((d,p) => {
        if(typeof props[p] === 'string') {
            d[props[p]] = src[p];
        } else if(props[p]) {
            d[p] = src[p];
        }
        return d;
    },dest);
};

Que puedes usar así:

let cbEvents = util.pick(this.props.events, {onFocus:1,onBlur:1,onCheck:'onChange'});
let wrapEvents = util.pick(this.props.events, {onMouseEnter:1,onMouseLeave:1});

Es decir, puede elegir qué propiedades desea y colocarlas en un nuevo objeto. A diferencia de _.pick también puede cambiarles el nombre al mismo tiempo.

Si desea copiar los props en un objeto existente, simplemente establezca el arg dest.

 0
Author: mpen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-31 19:57:52

Esto es una especie de engaño, pero puedes hacer algo como esto...

const originalObject = {
  hello: 'nurse',
  meaningOfLife: 42,
  your: 'mom',
};

const partialObject = (({ hello, your }) => {
  return { hello, your };
})(originalObject);

console.log(partialObject); // ​​​​​{ hello: 'nurse', your: 'mom' }​​​​​

En la práctica, creo que rara vez querrías usar eso. Lo siguiente es mucho más claro... pero no tan divertido.

const partialObject = {
  hello: originalObject.hello,
  your: originalObject.your,
};

Otra ruta completamente diferente, que incluye la limpieza con el prototipo (cuidado ahora...):

if (!Object.prototype.pluck) {
  Object.prototype.pluck = function(...props) {
    return props.reduce((destObj, prop) => {
      destObj[prop] = this[prop];

      return destObj;
    }, {});
  }
}

const originalObject = {
  hello: 'nurse',
  meaningOfLife: 42,
  your: 'mom',
};

const partialObject2 = originalObject.pluck('hello', 'your');

console.log(partialObject2); // { hello: 'nurse', your: 'mom' }
 0
Author: Bart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-05 22:15:44

Puede devolver el objeto desestructurado en una función arrow y usar Object.assign () para asignarlo a una variable.

const foo = {
  x: "bar",
  y: "baz"
}

const oof = Object.assign({}, () => ({ x, y } = foo));
 0
Author: Ben Copeland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-10 19:25:33

Esta es la solución más legible y más corta que se me ocurrió:

let props = { 
  isValidDate: 'yes',
  badProp: 'no!',
};

let { isValidDate } = props;
let newProps = { isValidDate };

console.log(newProps);

Saldrá { isValidDate: 'yes' }

Sería bueno algún día poder decir algo como let newProps = ({ isValidDate } = props) pero desafortunadamente no es algo que ES6 soporte.

 0
Author: Patrick Michaelsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-09 17:33:35

No es una manera hermosa, ni lo recomiendo, pero es posible de esta manera, solo por conocimiento.

const myObject = {
  name: 'foo',
  surname: 'bar',
  year: 2018
};

const newObject = ['name', 'surname'].reduce(
  (prev, curr) => (prev[curr] = myObject[curr], prev),
  {},
);

console.log(JSON.stringify(newObject)); // {"name":"foo","surname":"bar"}
 0
Author: Sornii,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-07 12:15:16