0

TLDR: How to use destructuring to speed up updating parts of one object based on another object of the same interface?

I would like to use the new ECMA2015 - 2017 JavaScript to refactor my code.

For simplicity let's say I have an object, looking like this:

export interface myObj {
  name:           string;
  id:             number;
  description:    string;
  someBool:       boolean;
  anotherBool:    boolean;
}

(Export interface works, because I'm working in Angular using Typescript).

Here is the old es5 function:

updateMyObj = function(oldObj, newObj) {
  var someBoolSaved = oldObj.someBool;
  var anotherBoolSaved = oldObj.anotherBool;
  oldObj = newObj;
  oldObj.someBool = someBoolSaved;
  oldObj.anotherBool = anotherBoolSaved;
}

As you can see the function should update some parts of the oldObj, but also keep some parts.

Here is my attempt at refactoring the code:

updateObj(oldObj, newObj) {
  let {someBool, anotherBool} = oldObj;
  oldObj = newObj;
  // Here is the part where I don't know how to proceed.
}

But I don't know, how I can now assign the oldObj's bools to the saved bools.

An inelegant way would be

oldObj.someBool = someBool;
oldObj.anotherBool = anotherBool;

which in this example would be fine. But in my actual task, this costs many lines of code which is why I want to refactor.

I just can't figure out the right syntax.

My attempts at coding this look similar like this:

oldObj = {someBool, anotherBool}

but this doesn't work.

halfer
  • 19,824
  • 17
  • 99
  • 186
J. Hesters
  • 13,117
  • 31
  • 133
  • 249
  • 1
    `export interface ...`? Even the ES2018 draft doesn't have `interface` mean anything yet, it remains a "future reserved word." – T.J. Crowder Mar 26 '18 at 13:24
  • That is because I'm using Angular with Typescript I guess. I edited that in the question :) – J. Hesters Mar 26 '18 at 13:26
  • 2
    "*`oldObj = newObj;`*" - sorry what? I think you should first start to simplify your ES5 code to `function updateMyObj(oldObj, newObj) { newObj.someBool = oldObj.someBool; newObj.anotherBool = oldObj.anotherBool; }` – Bergi Mar 26 '18 at 13:27
  • Thank you @Bergi. That is even shorter. How would you write that in ES6+ though? – J. Hesters Mar 26 '18 at 13:28
  • @J.Hesters Not any different, actually. It's quite straightforward and simple. The technique mentioned in the duplicate and by T.J.Crowder doesn't gain much. – Bergi Mar 26 '18 at 13:29

2 Answers2

3

If you want to assign the destructured value to a property, you do that by specifying the property on the right-hand side of a : in the destructuring.

For instance: The following assigns newObj.a and newObj.c to oldObj.a and oldObj.c:

({a: oldObj.a, c: oldObj.c} = newObj);
//   ^^^^^^^^-----^^^^^^^^---- destinations for a and c

(The () are necessary because otherwise the { at the beginning looks like the beginning of a block. If we were already in an expression context, you wouldn't need them.)

const oldObj = {a: "old a", b: "old b"};
const newObj = {a: "new a", c: "new c"};
({a: oldObj.a, c: oldObj.c} = newObj);
console.log(oldObj);

As Bergi points out in a comment on the question, it doesn't really buy you much over

oldObj.a = newObj.a;
oldObj.c = newObj.c;

That's one reason various pick notations have kicked around (that one's seen activity quite recently). If that proposal were accepted (and it doesn't even have a champion yet, so don't hold your breath), you'd have oldObj.{a, c} = newObj;.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Of course, if this were at the beginning of a compilation unit, one might **also** want a `;` to avoid it being mistaken for a function argument if you combined it after other code... :-) – T.J. Crowder Mar 26 '18 at 13:34
  • Thank you T.J. :) These pick notations look good, I hope they get accepted. And I will still go for your answer, because in my real life use case, it is indeed way more that just two lines, that need that treatment :) – J. Hesters Mar 26 '18 at 13:42
  • (I should have known this was already answered. My bad.) – T.J. Crowder Mar 26 '18 at 13:53
0

const newObj = { ...oldObject, someBool: true, anotherBool: false};

Edit:

Is updating the old object really what you want to do?

In your original code you mutate oldObj as a side-effect of the function. This is generally regarded as bad practise. The following is an example of a pure function with no side effects.

const firstObj = { name: 'hi', someBool: true, anotherBool: true };
const secondObj = { name: 'bye', someBool: false }; 
const thirdObj = mergeObjects(firstObj, secondObj);
// work with thirdObj from now on

function mergeObjects(firstObj, secondObj): myObj {
  return { 
    ...secondObj,
    firstObj.someBool,
    firstObj.anotherBool 
  }
}
Mongoose
  • 69
  • 4