1

I am looking for the most concise way to have a new object out of the fields of the deconstructed one.

let obj = {
    a: 1,
    b: 2,
    c: null
}

Currently I have:

let {a, c} = obj;

let data = {a, c}

What I wished I would be having:

let data = {a, c} = obj;
// but data actually becomes {a, b, c}
// and not {a, b} as I wished it to be.
shuk
  • 1,533
  • 1
  • 11
  • 21
  • 1
    See https://stackoverflow.com/questions/25553910/one-liner-to-take-some-properties-from-object-in-es-6 – Nenad Vracar Jan 09 '19 at 16:58
  • It's not really clear what you're asking here. You want `data` to be identical to `obj` after this? Do you still have access to `obj`? If so, is your real ask "how do I clone an object"? If not, how can you expect to arrive back at the initial state of `obj` if you don't have the value of `b` or the original object laying around? – meager Jan 09 '19 at 16:59
  • 1
    @meagar no, they're requesting the opposite. Currently `data` just becomes a reference to `obj`, not a reference to `{ a, c }`. What they want is equivalent behavior to the second snippet in a single assignment statement. – Patrick Roberts Jan 09 '19 at 17:05
  • @meagar I edited the comment after let data = {a, c}. although I think the title was clear enough.. I am not looking to clone an object, but to store parts of it in a new variable smoothly, – shuk Jan 09 '19 at 17:06
  • @NenadVracar thanks! – shuk Jan 09 '19 at 17:06
  • The title doesn't really help, I can't understand "reconstruct partial deconstructed object es6" in the context of this question at all. You're asking about why `a = b = c` evaluates as `a = c; b = c`, and not `b = c; a = b`? The answer is because this is how assignment works in JavaScript, object restructuring isn't really part of this. – meager Jan 09 '19 at 17:10
  • @meagar I do not understand. if `obj = {a, b, c}` and I am trying to pick and assign only `{a, c}` to `data`, how does it translate to a = b = c? – shuk Jan 09 '19 at 17:16
  • 1
    The word you're probably after is ["pick"](https://underscorejs.org/#pick), or "slice". My `a = b = c` doesn't refer to the same values as your `{ a, b, c }`, I'm using them as generic placeholders when talking about parallel assignment. I should have said `x = y = z` will always behave like `x = z; y = z`, which is why your `data = { a, c } = obj` line always results in `data == obj`. It is functionally identical to `data = obj; { a, c } = obj`. The problem here is you've already chosen destructuring as an answer, when it's not really the right approach. – meager Jan 09 '19 at 17:29
  • 1
    The [annotated source for pick](https://underscorejs.org/docs/underscore.html#section-111) demonstrates how to correctly and performantly implement your own version of this function. – meager Jan 09 '19 at 17:35
  • @meagar cool! allow me time to let it sink :) – shuk Jan 09 '19 at 17:39

3 Answers3

3

Although your code looks fine may be if your task consists in cherrypicking keys and put it in another object destructuring is not the best approach:

const object = { a: 5, b: 6, c: 7  };
const picked = (({ a, c }) => ({ a, c }))(object);

console.log(picked)
husayt
  • 12,616
  • 7
  • 45
  • 75
Mosè Raguzzini
  • 12,776
  • 26
  • 36
  • 2
    I hadn't considered inlining the function... both intriguing and quite unreadable, but definitely should work. – Patrick Roberts Jan 09 '19 at 17:10
  • This *is* clever, but it's also obfuscating something that should be really simple, and I would certainly expect to see your original two-line version used over this in any shared codebase. There is no value in cramming this into one line, especially at such a high cost to readability. – meager Jan 09 '19 at 17:37
  • 1
    Also, not that it really matters, but this one-liner is 400x slower than your original two-line solution: https://jsperf.com/testaagwt14124oih1oij/1 – meager Jan 09 '19 at 17:42
  • @meagar was really worth noting – shuk Jan 09 '19 at 18:15
  • @meagar this is not 400x slower https://jsperf.com/testaagwt14124oih1oij/3 and still faster than lodash pick and pick test function. As the goal was "more coincise way to" and not "more performing" I think it fit the scope. – Mosè Raguzzini Jan 10 '19 at 09:01
0

You can define a function that will provide the destructured object as the return value, and assign the call to data:

const obj = {
  a: 1,
  b: 2,
  c: null
}
const partial = ({ a, c }) => ({ a, c })

const data = partial(obj)
console.log(data)

Unfortunately this isn't possible in one line without some setup, but the setup is worthwhile if you are creating the same partial object a lot of places in your source.

Patrick Roberts
  • 40,065
  • 5
  • 74
  • 116
0

Rather than rely on destructuring for this, you can implement a version of the commonly found "pick" function, that accepts as input an object and an array of keys to pull out of that object:

function pick(obj, keys) {
  return keys.reduce((memo, key) => {
    memo[key] = obj[key];
    return memo;
  }, {});
}

const obj = { a: 1, b: 2, c: 3 }
const data = pick(obj, ['a', 'b']); 

console.log(data); // { a: 1, b: 2}

Normally I would consider performance less important than readability, which is highly subjective. But in this case, both the pick solution above and the one-liners are orders of magnitude slower than your original two-liner, though pick wins out over the one-liner by a comparatively small margin: https://jsperf.com/testaagwt14124oih1oij

meager
  • 209,754
  • 38
  • 307
  • 315