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.

Answers:

Answer

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:

Answer

No, it is not possible, consider:

var obj = {a:0}

function f (o: {a:x}) {} // not valid - unexpected token :
function f ({a}) {} // valid a === 0
function f ({a:x}) {} // valid x === 0, a is undefined - probably no use for this

The best you can do with the ES6 implementation is get access to nested props, not a reference to the object itself as well as nested props.

(would love to be proven wrong though, this is a feature I have looked for as well)

Answer

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 }});

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.