Spread Destructuring

Say we have an object with 20 properties...

const person = {
  name: "Alian",
  age: 13,
  // 18 more properties

...and we need to destructure and use all of them. The larger the object is, the more code we need to write.

We could use an easy cheat here.

const { ... } = person;

Say we need all the properties of person except age.

const { ..., -age } = person; // I call it the exclusion operator.

Say we need to rename name to username.

const { ..., name: username } = person;

This is kind of like the below example. I guess a new syntactical sugar won't hurt.

JS: use spread to exclude properties - DEV Community

Note - It does not have to be the spread operator (...). It could be a * or anything sensible.

Thank you :grinning:.

The deprecated with feature is similar, however, it involved a lot more magic than what you're proposing which is probably part of the reason why it got deprecated.

But, there's other reasons too - if I understand correctly, it's really hard for an engine to optimize this kind of logic, since it's impossible to know ahead of time what will be inside that object at the time of destructuring, therefor, it's impossible to know ahead of time which local variables need to be declared at that point.

It's even hard for humans to know, which is a reason why I wouldn't be a fan of this feature. It opens up a whole lot of pitfalls, like the following:

function getProps(user, callback)
  const { ... } = user
  callback(username, age)

Tell me - is that callback referring to the passed-in parameter, or is it a function found on the user object? (You never know in userland code, people write some weird stuff, and it could be that the callback being used was actually supposed to be on the user object).

I find it much more clear if you explicitly destructure what you need, or if you just say user.username and user.age directly. You can even rename your object to a single-character name - yes in some books that are not a great practice, but in my book, it's much better practice then the above example.


very true; In a gist, It violates referential transparency.
how is this bad, here's what Wikipedia has to say:

The importance of referential transparency is that it allows the programmer and the compiler to reason about program behavior as a rewrite system. This can help in proving correctness, simplifying an algorithm, assisting in modifying code without breaking it, or optimizing code by means of memoization, common subexpression elimination, lazy evaluation, or parallelization.

1 Like

How would you ensure this doesn't shadow variables from outer/global scope, like Object, console etc?

1 Like

A syntax that can add arbitrary items to a scope dynamically would likely hinder performance. As engines wouldn't be able to statically analyse the members of the scopes.

async function main() {
   // Which symbols should this closure capture?
   let callback = () => {
     // is this globalThis.GlobalVariable or `result.GlobalVariable` from -
     GlobalVariable.method();                                          // |
   };                                                                  // |
   setTimeout(callback, 5000);                                         // |
                                                                       // |
   let result = await getSomething();                                  // |
   let { ... } = result; // <---------------------------------------------


Thank you all for the responses. I was making the backend for an app with Node, where the client could send some details regarding a product for the server to add to the database. I ended up destructuring the entire object sent by the client. That's why I thought of this proposal. I did not know this could cause performance issues. Thanks for telling me :)

1 Like

@ethanlal04 This is the real reason with got dropped from strict mode - engines couldn't properly analyze the dynamic scoping for general variables. And this in effect is a with declared with var/let/const rather than using a special syntax construct.