15

The new destructuring assignment features of ES6 are fairly well known now (live copy on Babel's REPL); in the case of variables that already exist:

let a, b;                 // Existing variables
let o = {a: "a", b: "b"}; // An object to get values from
// ...
({a, b} = o);             // Set them to the props from `o`
console.log(a);           // "a"
console.log(b);           // "b"

Is there a simple converse in ES6? Setting properties on an existing object based on variables with the same name? (Other than the obvious o.a = a; o.b = b;)

Note I'm not talking about when creating an object, we could do that with the wonderful new object initializer syntax that lets us not repeat the names unnecessarily:

let a = "a";
let b = "b";
let o = {a, b};

But if I already have an object, can I do some kind of structuring assignment in ES6?

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    It sounds like you want the object initializer shorthand to be able to `extend` existing objects. Do I understand correctly? – Evan Davis Jun 17 '15 at 17:14
  • @Mathletics: Or some other mechanism with that sort of result, yes. – T.J. Crowder Jun 17 '15 at 17:15
  • I'm not getting your question. So you have an existing object `{a : "a"}`. You have a variable b with the value "b". What do you want to do exactly? –  Jun 17 '15 at 17:25
  • @torazaburo: *(Sorry, editing error in my earlier comment made it clear as mud.)* Starting with `a`, `b`, and `o` where `o` refers to an object, I want the result I'd get with `o.a = a; o.b = b;` via some kind of structuring syntax. E.g., as I said above, the converse of how `({a, b} = o);` in ES6 lets me get what I'd get from `a = o.a; b = o.b;` in ES5. – T.J. Crowder Jun 17 '15 at 17:35
  • possible duplicate of [Is it possible to destructure onto an existing object? (Javascript ES6)](http://stackoverflow.com/q/29620686/1048572) – Bergi Jun 17 '15 at 18:37
  • @Bergi: It's definitely *similar*, but not quite th same. My starting point isn't two objects, it's variables and an object. Solutions may well require a temporary object (mine below does), but I was frankly hoping for a solution that didn't. Call it "related." :-) – T.J. Crowder Jun 17 '15 at 18:43

2 Answers2

11

The closest I've come up with is to use Object.assign and a temporary object (live copy):

let a = "a", b = "b";             // The variables
let obj = {c: "c"};               // The existing object
Object.assign(obj, {a, b});       // "Structuring" assignment, sort of
console.log(JSON.stringify(obj)); // "{"c":"c","a":"a","b":"b"}

It's fairly simple, but it's a function call and a temporary object.


Update: Bergi points out in a comment that there's a strawman proposal (link now dead) for a := operator that will do this, and one of their first use cases is indeed the use case that primarily lead me to this question: Constructors:

// From strawman proposal linked above, doesn't actually exist yet!
class Point {
   constructor(x,y) {
      this := {x,y}  //define and initialize x and y properties of new object
      //   ^^
   }
}

So given that strawman exists, I suspect for now the assign is going to be the best I can do in ES6. The old wiki with the strawman is offline, and there's nothing about := in the proposals repo.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 2
    There isn't anything I can think of better than this. At the end of the day, shorthand object properties are the only way to collapse key and value, so creating a temporary object is necessary. – loganfsmyth Jun 17 '15 at 17:38
  • @loganfsmyth: Thanks. ES6 is so rich that I was wondering if I'd missed something. I half expected to get a near-instant reply pointing to something obvious and feel like a dolt. :-) – T.J. Crowder Jun 17 '15 at 17:40
  • This is as close as you're gonna get – Benjamin Gruenbaum Jun 17 '15 at 17:42
  • It's not bad at all :) For what it's worth objects should generally keep a structure so this sort of pattern is useful (at least until we figure more uses) in one place in particular - the constructor where it can be a very clean options object merge or assignment . Like https://gist.github.com/benjamingr/f105209f1a6274aad550 – Benjamin Gruenbaum Jun 17 '15 at 17:46
  • @BenjaminGruenbaum: And that's after all the [games you can play](http://stackoverflow.com/a/30863086/157247) with destructured arguments and default values! ;-) – T.J. Crowder Jun 17 '15 at 17:53
1

Some experimental stuff, building on top of your answer.

If you wanted to get a little cheeky you could emulate the assignment portion of it with a setter. Definitely not practical, but it's a fun way to see what the behaviour might look like on the outside, if maybe you could empty assign o[] =. (Babel)

let a = '1', b = '2';
let o = {z: '26'};

Object.defineProperty(Object.prototype, '', {
  set: function (o) {
    Object.assign(this, o);
  }, configurable: true
});

o[''] = {a, b};

Same issues you face with your answer, actually more, but some food for thought.

Oka
  • 23,367
  • 6
  • 42
  • 53