Spidermonkey 1.7 implements a kind of compound assignment known

as *destructuring assignment*. (You may have seen

destructuring assignment before, in Python or Ruby, for example.) In a

destructuring assignment, the value on the right-hand side of the

equals sign is an array or object (a “structured” value) and the

left-hand side specifies one or more variable names using a syntax

that mimics array and object literal syntax. When a destructuring

assignment occurs, one or more values are extracted (“destructured”)

from the value on the right and stored into the variables named on the

left. In addition to its use with the regular assignment operator,

destructuring assignment can also be used when initializing newly

declared variables with ` var`

and

` let`

.

Destructuring assignment is simple and powerful when working

with arrays, and is particularly useful with functions that return

arrays of values. It can become confusing and complex when used with

objects and nested objects, however. Examples demonstrating both

simple and complex uses follow.

Here are simple destructuring assignments using arrays of

values:

```
let [x,y] = [1,2]; // Same as let x=1, y=2
[x,y] = [x+1,y+1]; // Same as x = x + 1, y = y+1
[x,y] = [y,x]; // Swap the value of the two variables
console.log([x,y]); // Prints [3,2]
```

Notice how destructuring assignment makes it easy to work with

functions that return arrays of values:

```
// Convert [x,y] coordinates to [r,theta] polar coordinates
function polar(x,y) {
return [Math.sqrt(x*x+y*y), Math.atan2(y,x)];
}
// Convert polar to Cartesian coordinates
function cartesian(r,theta) {
return [r*Math.cos(theta), r*Math.sin(theta)];
}
let [r,theta] = polar(1.0, 1.0); // r=Math.sqrt(2), theta=Math.PI/4
let [x,y] = cartesian(r,theta); // x=1.0, y=1.0
```

The number of variables on the left of a destructuring

assignment does not have to match the number of array elements on the

right. Extra variables on the left are set to ` undefined`

, and extra values on the right are

ignored. The list of variables on the left can include extra commas to

skip certain values on the right:

```
let [x,y] = [1]; // x = 1, y = undefined
[x,y] = [1,2,3]; // x = 1, y = 2
[,x,,y] = [1,2,3,4]; // x = 2, y = 4
```

There is no syntax to assign all unused or remaining values (as

an array) to a variable. In the second line of code above, for

example, there is no way to assign ` [2,3]`

to ` y`

.

The value of a destructuring assignment is the complete data

structure on the right-hand side, not the individual values that are

extracted from it. Thus, it is possible to “chain” assignments like

this:

```
let first, second, all;
all = [first,second] = [1,2,3,4]; // first=1, second=2, all=[1,2,3,4]
```

Destructuring assignment can even be used with nested arrays. In

this case, the left-hand side of the assignment should look like a

nested array literal:

```
let [one, [twoA, twoB]] = [1, [2,2.5], 3]; // one=1, twoA=2, twoB=2.5
```

Destructuring assignment can also be performed when the

right-hand side is an object value. In this case, the left-hand side

of the assignment looks something like an object literal: a

comma-separated and brace delimited list of property name and variable

name pairs. The name to the left of each colon is a property name, and

the name to the right of each colon is a variable name. Each named

property is looked up in the object on the right-hand side of the

assignment, and its value (or ` undefined`

) is assigned to the corresponding

variable. This type of destructuring assignment can get confusing,

especially because it is often tempting to use the same identifier for

both property and variable name. In the example below, be sure that

you understand that ` r`

, ` g`

, and ` b`

are property names and ` red`

,

` green`

, and ` blue`

are variable names:

```
let transparent = {r:0.0, g:0.0, b:0.0, a:1.0}; // A RGBA color
let {r:red, g:green, b:blue} = transparent; // red=0.0,green=0.0,blue=0.0
```

The next example copies global functions of the ` Math`

object into variables, which might

simplify code that does a lot of trigonometry:

```
// Same as let sin=Math.sin, cos=Math.cos, tan=Math.tan
let {sin:sin, cos:cos, tan:tan} = Math;
```

Just as destructuring assignment can be used with nested arrays,

it can be used with nested objects. In fact, the two syntaxes can be

combined to describe arbitrary data structures. For example:

```
// A nested data structure: an object that contains an array of objects
let data = {
name: "destructuring assignment",
type: "extension",
impl: [{engine: "spidermonkey", version: 1.7},
{engine: "rhino", version: 1.7}]
};
// Use destructuring assignment to extract four values from the data structure
let ({name:feature, impl: [{engine:impl1, version:v1},{engine:impl2}]} = data) {
console.log(feature); // Prints "destructuring assignment"
console.log(impl1); // Prints "spidermonkey"
console.log(v1); // Prints 1.7
console.log(impl2); // Prints "rhino"
}
```

Note that nested destructuring assignments like this may make

your code harder to read rather than simplifying it. There is an

interesting regularity that can help you to make sense of the complex

cases, however. Think first about a regular (single-value) assignment.

After the assignment is done, you can take the variable name from the

left-hand side of the assignment and use it as an expression in your

code, where it will evaluate to whatever value you assigned it. In

destructuring assignment, we’ve said that the left-hand side uses a

syntax like array literal syntax or like object literal syntax. But

notice that after the destructuring assignment is done, the code that

looks like an array literal or object literal from the left-hand side

will actually work as a valid array literal or object literal

elsewhere in your code: all the necessary variables have been defined

so that you can cut-and-paste the text on the left of the equals sign

and use it as an array or object value in your code.