Is it possible to destructure an object into existing variables? - javascript

I am trying to extract variables using object destructuring but those variables already exist, something like this
const x=1, y=2 // Those should be 1 and 2
const {x,y} = complexPoint
const point = {x,y}
Is there any way to do this without renaming the destructuring variables?.
Some like this and updating point avoiding const definition?
const point = {x,y} = complexPoint
The expected result should be as using object destructuring
const x=1, y=2 // Those should be 1 and 2
const point = {
x:complexPoint.x,
y:complexPoint.y
}

You can do this with array destructuring, i.e.:
const complexPoint = [1,2];
let x, y;
[x,y] = complexPoint;
As for object destructuring, an equivalent syntax would not work as it would throw off the interpreter:
const complexPoint = {x:1,y:2};
let x, y;
{x,y} = complexPoint; // THIS WOULD NOT WORK
A workaround could be:
const complexPoint = {x:1,y:2};
let x, y;
[x,y] = [complexPoint.x, complexPoint.y];
// Or
[x,y] = Object.values(complexPoint);
UPDATE:
It appears you can destructure an object into existing variables by wrapping the assignment in parenthesis and turning it into an expression. So this should work:
const complexPoint = {x:1,y:2};
let x, y;
({x,y} = complexPoint); // THIS WILL WORK

here it can be done like this.
const complexPoint = {x: 1, y: 2, z: 3};
const simplePoint = ({x, y}) => ({x, y});
const point = simplePoint(complexPoint);
console.log(point);
In a single line looks like this:
const complexPoint = {x: 1, y: 2, z: 3};
// can be written as
const point2 = (({x, y}) => ({x, y}))(complexPoint);
console.log(point2);

It's not 100% clear to me what you want to do.
If you want to update point with two properties of complexPoint
You can actually destructure an object into anything that is assignable. Most often you will destructure into variables, but you can also destructure into properties.
Example:
const point = {x: 1, y: 2};
const otherPoint = {x:3, y: 4};
({x: point.x, y: point.y} = otherPoint);
// ^ ^
// parenthesis are necessary otherwise the runtime will interpret {
// as the start of a block
console.log(point);
Of course this can become difficult to read the more properties you have. You can also just assign them directly, the good old fashioned way:
point.x = otherPoint.x;
point.y = otherPoint.y;
Or with a loop:
for (const prop of ['x','y']) {
point[prop] = otherPoint[prop];
}
If you want to create a new object from an existing object
Create a helper function to "pick" the properties from the existing object. Such a function is provided here.
const point = pick(otherPoint, 'x', 'y');

After the destructuring, you can use the destructured data and save it as an object to another variable.
If we have this object:
const obj={"property":"value","property2":"value"};
You can destructure data from it like this:
const {property}=obj;
If we want to assign the destructured data only to another variable, We would do this:
const newVariable ={property};
Now the newVariable value will be equal to:
{"property":"value"}

Related

Assign full array to destructuring variable

In Clojure destructuring it's possible to also have a binding for the full array using :as, is something similar possible in Javascript?
For example,
const queue = [[1, 2]];
const [x, y :as pos] = queue.shift();
where x would be 1, y would be 2 and pos would be [1, 2]?
or is an extra in-between step necessary, like
const queue = [[1, 2]];
const pos = queue.shift();
const [x, y] = pos;
You can't get the parent and nested properties at the same time during destructuring.
I'd do it separately for readability
const queue = [ [1, 2] ],
pos = queue.shift(),
[x, y] = pos;
BUT, it is possible to do it in single line. If you destructure the array like an object. Get the 0 property to a variable and destructure the nested array
const queue = [ [1, 2] ];
const { 0: pos, 0: [x, y] } = queue
console.log(x, y)
console.log(pos)

React js rename & destructure array length

I have a reduce function like below:
let el = scopes.reduce ((tot, {actions}) => tot + actions.length, 0);
I tried to transform it like this, but it seems that it is not the correct way:
let el = scopes.reduce ((tot, {actions.length: len}) => tot + len, 0);
Is there a way to do this or it is not possible.
You were close, but you use nesting rather than dot notation:
// Outer −−−−−−−−−−−−−−−−−−−−v−−−−−−−−−−−−−−−−−−−−−−v
let el = scopes.reduce((tot, {actions: {length: len}}) => tot + len, 0);
// Inner −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^−−−−−−−−−−−−^
Live Example:
const scopes = [
{actions: [1, 2, 3]},
{actions: []},
{actions: [4, 5]}
];
let el = scopes.reduce((tot, {actions: {length: len}}) => tot + len, 0);
console.log(el); // 5
The key thing to remember with destructuring is that the syntax is identical to object and array literals, complete with nesting; it's just that the information flow is the other direction. In an object literal, for instance, the data flows right to left, from the source (source) to the target (prop):
let source = 42;
let obj = {prop: source};
// <−−−−−*
in destructuring, the data flows left to right, from the source (prop) to the target (target):
let {prop: target};
// *−−−−−>
console.log(target); // 42
and the target can be a variable, an object property, or even another destructuring pattern. That's what we're using above: The target of the actions property is the destructuring pattern {length: len}, which puts the value of length into the variable len. Here's Figure 7-1 from my new book (see my profile for links):
You could also use shorthand notation and use length in your callback:
let el = scopes.reduce((tot, {actions: {length}}) => tot + length, 0);
Live Example:
const scopes = [
{actions: [1, 2, 3]},
{actions: []},
{actions: [4, 5]}
];
let el = scopes.reduce((tot, {actions: {length}}) => tot + length, 0);
console.log(el); // 5

snippet for creating object from destructured array

For example, I had an array with 3 numbers:
var arr = [124, -50, 24];
and I need to convert this array to the object:
{
x: 124,
y: -50,
z: 24
}
I don`t want to use "old-style" syntax for this, for example:
{
x: arr[0],
y: arr[1],
z: arr[2]
}
so for now, I`m using that syntax:
const [x, y, z] = [...arr];
const obj = {x, y, z};
But, is there is any way to do this with a straight dectructuring array to object without need of temporary variables?
As it was already mentioned in the comment you can use an Immediately Invoked Function Expression (IIFE) to create the object in a single step, but it's less readable then multiple steps.
const arr = [124, -50, 24];
const obj = (([x, y, z]) => ({ x, y, z }))(arr);
console.log(obj);
You can also do
const obj = {};
([obj.x, obj.y, obj.z] = arr);
to avoid the temporary variables, but I'd question whether that's an improvement.
Just use this
let obj = {...arr}

Multiple object properties assignment in Javascript

Is there some kind of shorthand for this?
object.position.x = position.x
object.position.y = position.y
object.position.z = position.z
object.rotation.x = rotation.x
object.rotation.y = rotation.y
object.rotation.z = rotation.z
Thanks for your time.
Yes you can use Object.assign().
var obj = {}
var position = {x: 1, y: 2, z: 3}
var rotation = {x: 1, y: 2, z: 3}
obj.position = Object.assign({}, position);
obj.rotation = Object.assign({}, rotation);
console.log(obj)
If you only want to take specific properties from object you can create your pick function using map() to get array of objects and later use spread syntax to assign each object.
var obj = {}
var position = {x: 1, y: 2, z: 3}
var rotation = {x: 1, y: 2, z: 3}
function pick(obj, props) {
return props.map(e => ({[e]: obj[e]}))
}
obj.position = Object.assign({}, ...pick(position, ['x', 'y']));
obj.rotation = Object.assign({}, ...pick(rotation, ['x', 'y', 'z']));
console.log(obj)
You could use a direct approach by assigning the objects directly,
object.position = position;
object.rotation = rotation;
or with an array and the keys with iterating the properties.
['x', 'y', 'z'].forEach(function (k) {
object.position[k] = position[k];
object.rotation[k] = rotation[k];
});
With ES6 Spread Operator you can do it easier in one line, for the question sample:
object = {...object, position, rotation}
Just notice it will replace new properties with old one
My advice: DON'T USE ANY "CLEVER" LOOPS AND DYNAMIC SH*T
Reasons:
It's just a few lines, not a ton of lines, don't do overengineering
It's so much readable, that even IDE can help you with autosuggestions
You can also use a for...in loop, it's simple and quite readable. Example:
for ( const property in position ) {
object.position[property] = position[property];
}
MDN reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

Swap entire arrays in Javascript

When I try to make a function to swap 2 arrays, the original arrays are left unaltered.
function swap(x, y) {
var temp = x; x = y; y = temp;
}
u=[1, 0];
v=[0, 1];
swap(u, v);
console.log(u);
console.log(v);
This results in u as [1, 0] and v as [0, 1]. The values haven't been changed after the function call to swap.
On the other hand, if I do this without a function call:
u=[1, 0];
v=[0, 1];
var temp = u;
u = v;
v = temp;
console.log(u);
console.log(v);
Then they're swapped correctly, with u as [0, 1] and v as [1, 0].
I thought Javascript arrays are passed by reference, not by value. Am I misunderstanding something here?
Javascript does not have the ability to pass a reference to the u and v variables themselves. So, no assignment to x or y in your swap() function will change what is assigned to u or v. Javascript passes a reference to the object that u and v hold. Thus, you can't change the u and v variables from within swap(). You can change the contents of the object that they point to and thus properties of the object that u and v point to can be modified.
Since I have a C/C++ background, I think of what Javascript does when passing objects as "pass by pointer". When you call swap(u, v), what is passed to the swap() function is a pointer to the array that u also points to. So, now you have two variables u and x both "pointing" at the same array. Thus, if you modify that actual array, then since u points at that same array, both will see the modification. But, nothing you do inside the swap() function can change what object u or v actually point to.
In Javascript, the only way to change what object the original variables point to is to make them properties of an object and pass the object like this:
function swap(obj, x, y) {
var temp = obj[x]; obj[x] = obj[y]; obj[y] = temp;
}
var container = {};
container.u = [1, 0];
container.v = [0, 1];
swap(container, "u", "v");
console.log(container.u);
console.log(container.v);
If you don't mind rewriting both arrays from scratch, you can copy all the contents of one array to a temporary, then copy one array over to the other and then copy the temporary array contents back to the first original. This is not very efficient and there is probably a better way to solve your original problem, but it can be done.
function swap(x, y) {
// remove all elements from x into a temporary array
var temp = x.splice(0, x.length);
// then copy y into x
x.push.apply(x, y);
// clear y, then copy temp into it
y.length = 0;
y.push.apply(y, temp);
}
Getting the terminology on these "reference/value" questions is tricky, but I will do my best.
What you have for your Object / Array variables are really just references. Unlike C++, saying "x = y" does not actually copy the object's variables over to a new memory location. Internally, it's just copying a pointer location over. The language does not have constructions to "automatically recreate" something like an object or array in a new instance; if for some reason, you want to maintain two copies of an array, you will need to explicitly create it then copy over values (ie, = []; or = new Array(); or a copying function like = oldArray.map(...))
A little code example that might conceptually help. These same rules apply between objects and arrays.
a = {}; // In case you haven't seen it, this is like shorthand of "new Object();"
b = {};
c = b;
console.log(a === b); // false
console.log(b === c); // true
b.property = "hello";
console.log(c.property) // hello
Just like Java, JavaScript is pass-by-value only. Assigning to local variables in a function never has any effect on anything outside the function.
They are passed by reference, but they are also assigned by reference. When you write x = y you aren't modifying either of the arrays, you're just making your local variable x refer to the same array as y.
If you want to swap the array contents, you have to modify the arrays themselves:
function swap(x,y) {
var temp = x.slice(0);
x.length = 0;
[].push.apply( x, y );
y.length = 0;
[].push.apply( y, temp );
}
Feb 2022 Solution to Swap 2 Entire Array Contents.
You can use destructuring to swap the 2 arrays:
let a = [ 1, 2, 3, 4 ];
let b = ['a','b','c','d'];
[a,b] = [b,a]; // swap
console.log(a); // ["a", "b", "c", "d"]
console.log(b); // [1, 2, 3, 4, 5]
let a = [ 1, 2, 3, 4 ];
let b = ['a','b','c','d'];
[a,b] = [b,a]; // swap
console.log(a); // ["a", "b", "c", "d"]
console.log(b); // [1, 2, 3, 4, 5]
To swap 2 arrays you may use
Version 1
let arrA = [1,2,3,4];
let arrB = ['Eve', 'Bar', 'Foo'];
let tempArr = [arrA, arrB]; // constructing new array
arrA = tempArr [1];
arrB = tempArr [0];
Version 1 (shorthanded)
let arrA = [1,2,3,4];
let arrB = ['Eve', 'Bar', 'Foo'];
// RHS : construction a new array
// LHS : destruction of array
[arrB, arrA ] = [arrA, arrB];
Version 2 (spread operator)
let arrA = [1,2,3,4];
let arrB = ['Eve', 'Bar', 'Foo'];
let arrC = [...arrB]
arrB = [...arrA]
arrA = [...arrC]

Categories

Resources