Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destructuring assignment in function call while preserving the object [duplicate]

Is there a way to do something like the following?

f = (o:{a:x}) {
    console.log(o);
    console.log(x);
}
f({a:0});
//Should Print:
//{a:0}
//0

To get the same result as the this.

f = function(o) {
    var {a:x} = o;
    console.log(o);
    console.log(x);
}
f({a:0});
//Prints
//{a:0}
//0

I would like to deconstruct the object inside the function parameters while also passing the object to the function so that the object can be modified.

like image 538
Diasiare Avatar asked Jul 17 '17 13:07

Diasiare


People also ask

What is Destructuring assignment?

Destructuring Assignment is a JavaScript expression that allows to unpack values from arrays, or properties from objects, into distinct variables data can be extracted from arrays, objects, nested objects and assigning to variables.

What is Destructuring assignment in es6?

The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.

What does Destructuring do exactly when would you use it?

Destructuring is a JavaScript expression that allows us to extract data from arrays, objects, and maps and set them into new, distinct variables. Destructuring allows us to extract multiple properties, or items, from an array​ at a time.


2 Answers

TL;DR

Objects - losing properties:

let f = ({ a: x, ...o }) => {
    console.log(o);
    console.log(x);
};
f({ a: 0, b: 1, c: 2 });
// x is: 0
// o is: { b: 1, c: 2 }

Objects - preserving properties:

let f = (o) => {
    let { a: x } = o;
    console.log(o);
    console.log(x);
};
f({ a: 0, b: 1, c: 2 });
// x is: 0
// o is: { a: 0, b: 1, c: 2 }

Arrays - losing elements:

let f = ([x, ...a]) => {
    console.log(a);
    console.log(x);
};
f([0, 1, 2]);
// x is: 0
// a is: [1, 2]

Arrays - preserving elements:

let f = (a) => {
    let [x] = a;
    console.log(a);
    console.log(x);
};
f([0, 1, 2 ]);
// x is: 0
// a is: [0, 1, 2]

Note that the examples above that preserve properties put the same object in o (or array in a) that was used when calling the function, not a copy. To use a shallow copy you can use the examples below:

Objects - preserving properties, creating a new object:

let f = ({ ...o }) => {
    let { a: x } = o;
    console.log(o);
    console.log(x);
};
f({ a: 0, b: 1, c: 2 });
// x is: 0
// o is: { a: 0, b: 1, c: 2 }

Arrays - preserving elements, creating a new array:

let f = ([...a]) => {
    let [x] = a;
    console.log(a);
    console.log(x);
};
f([0, 1, 2]);
// x is: 0
// a is: [1, 2]

Explanation

If you want to preserve all of the properties of the original object in o then you need the explicit destructuring step in the body of your function: let { a: x } = o; but if you want to preserve only those properties that were not put into x then you may be able to use the destructuring as described below (in the future when it's supported). See Examples below for details.

Note that I originally assumed that you want destructuring as you would get when destructuring arrays - but maybe that's not what you want - thanks to Karen Grigoryan for pointing it out in the comments.

A syntax that should logically work would be not this:

let f = (o: { a: x }) => {
    console.log(o);
    console.log(x);
};

but this:

let f = ({ a: x, ...o }) => {
    console.log(o);
    console.log(x);
};

(But I would be (positively) surprised if that worked natively on any platform today or even in transpilers. This would need support for rest operator in object destructuring combined with unpacking fields from objects passed as function parameters. Theoretically there's no reason it shouldn't work. In practice it likely doesn't.)

Note that ({ a: x, ...o }) => ... when invoked as f({ a: 0, b: 1 }) would put only { b: 1 } in o and would put 0 in x - just like ([x, ...a]) => ... when invoked as f([0, 1]) would put only [1] in a and would put 0 in x.

This means that using destructuring with rest parameters - for objects and arrays alike - would not preserve the entire array or object in the rest variable but only that data that was not explicitly captured otherwise.

This means that no matter if you're destructuring arrays or objects, you need to put the explicit destructuring step in the body of your functions instead of relying on the parameter syntax if you want to have the original array or object intact.

See:

  • Rest_in_Object_Destructuring on MDN
like image 56
rsp Avatar answered Oct 04 '22 00:10

rsp


For nested object destructuring you can use an assignment operator to extract the nested reference value.

let {
  o,
  a = o.a
} = {
  o: {
    a: 'x'
  }
}


console.log(o);
console.log(a)

Similarly, you can destructure the function caller

const f = ({ o,a=o.a } = {a:y}) => {
    console.log(o)
    console.log(a)
};

f({o:{a: 0 }});
like image 28
Rick Avatar answered Oct 03 '22 22:10

Rick