Is there a way to destructure a JS object in-place, instead of assigning the destructured variables to a scope?

Instead of doing this:

const { a, b, c } = obj;
someFunction(a, b, c);

I'd like to do this:

someFunction({a, b, c} from obj);

Or something functionally equivalent.

I'd like to do this in situations with these two stipulations:

  • I don't want to put the variable names into the enclosing scope.

  • I don't want to pass the whole object obj, therefore making the spread operator not an option.

The only option I'm left with is to use

someFunction(obj.a, obj.b, obj.c);

Which is fine in this case, but can lower readability when obj is instead a long identifier.

Is something like this possible? I tried using assignment in an expression as a workaround, but my IDE complained that it could not find names a, b, and c:

someFunction({a, b, c} = obj);
  • 1
    if you are targeting es6 environments you can define your function with a destructure parameter, eg function f({a,b,c}){ /*...*/ } or would you not want that since you dont want to pass the whole object – Patrick Evans Apr 21 at 3:22

One option is to use .map to extract the value of each property you want, and spread it into the argument list:

  ...['a', 'b', 'c'].map(prop => obj[prop])

Destructuring requires the creation of intermediate variables, unfortunately, which you don't want.

  • It is unfortunate that the intermediate is required, as it's just a needless performance penalty in some situations (like mine). As for your proposition, I like that it scales better than obj.property, but it's still quite verbose :/ enough so that I'm sure I couldn't throw it into production code without it failing code review. – AnthonyMonterrosa Apr 21 at 3:19
  • 4
    Performance is rarely something to worry about - code readability matters more in 99% of situations, and if you want to keep the code DRY and want to be able to use the pattern for any number of properties, I'm pretty sure this is the best pattern you'll be able to find. If this fails code review because it's too verbose, I think that's an indicator that there's an issue with code review, rather than an issue with the code here – CertainPerformance Apr 21 at 3:22
  • I agree with all of your statements, especially the last one (but sadly my opinion does not outweigh tradition). Maybe I should give it a go and see what happens. – AnthonyMonterrosa Apr 21 at 3:35

An IIFE should work:

((({ a, b, c }) => someFunction(a, b, c))(obj);
  • I like that this works, but I dislike the performance penalty of making a function whenever I need to call someFunction. Also, akin to the other answer, this is unusual-enough looking that I don't think it'd pass code review :/. – AnthonyMonterrosa Apr 21 at 3:20

This how I'd do it:

function foo( { x, y } ) {
	console.log( x, y );

foo( { y: 1, x: 2 } );	 // 2 1

As for the OP's specific request to not pass the whole object (or declare variables in the global scope). Destructuring the object to block-scoped variables would be the best way IMHO.

const obj = { x: 1, y: 2 }

function foo( x, y ) {
    console.log( x, y );

{   let { x, y } = obj;
    foo( x, y );   // 1 2

console.log(x) // "ReferenceError: x is not defined

  • Can you explain how this resolves my issue? I don't see a strong relation. – AnthonyMonterrosa Apr 21 at 3:36
  • 1
    You pass an object as an argument and destruct it as function parameters. I know that you've said that you don't want to pass the whole object as argument, still this's my recommendation. – Khalid Ali Apr 21 at 3:46
  • 1
    Right, but this means I'd have to be the one writing the function. Great for my own code, but there are many situations where I don't have control over the function's parameters e.g. libraries, or most cost when coding for a company. – AnthonyMonterrosa Apr 21 at 5:07
  • 1
    @@AnthonyMonterrosa if it's such a big issue, I would use this style as a wrapper function to your library call, eg function wrapLib({x, y}) { return library.expensiveCall(x,y)}. If the situation calls for it, the result can be cached. Alternatively, the TC39 are always looking for unique improvements to JS. – jayands Apr 21 at 11:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.