Var Object Function Homework

The two most used data structures in JavaScript are and .

Objects allow us to pack many pieces of information into a single entity and arrays allow us to store ordered collections. So we can make an object or an array and handle it as a single entity, or maybe pass it to a function call.

Destructuring assignment is a special syntax that allows us to “unpack” arrays or objects into a bunch of variables, as sometimes they are more convenient. Destructuring also works great with complex functions that have a lot of parameters, default values, and soon we’ll see how these are handled too.

Array destructuring

An example of how the array is destructured into variables:

Now we can work with variables instead of array members.

It looks great when combined with or other array-returning methods:

“Destructuring” does not mean “destructive”

It’s called “destructuring assignment”, because it “destructurizes” by copying items into variables. But the array itself is not modified.

It’s just a shorter way to write:

Works with any iterable on the right-side

…Actually, we can use it with any iterable, not only arrays:

Assign to anything at the left-side

We can use any “assignables” at the left side.

For instance, an object property:

The rest ‘…’

If we want not just to get first values, but also to gather all that follows – we can add one more parameter that gets “the rest” using three dots :

The value of is the array of the remaining array elements. We can use any other variable name in place of , just make sure it has three dots before it and goes last in the destructuring assignment.

Default values

If there are fewer values in the array than variables in the assignment, there will be no error. Absent values are considered undefined:

If we want a “default” value to replace the missing one, we can provide it using :

Default values can be more complex expressions or even function calls. They are evaluated only if the value is not provided.

For instance, here we use the function for two defaults. But it will run only for the missing one:

Object destructuring

The destructuring assignment also works with objects.

The basic syntax is:

We have an existing object at the right side, that we want to split into variables. The left side contains a “pattern” for corresponding properties. In the simple case, that’s a list of variable names in .

For instance:

Properties , and are assigned to the corresponding variables. The order does not matter. This works too:

The pattern on the left side may be more complex and specify the mapping between properties and variables.

If we want to assign a property to a variable with another name, for instance, to go into the variable named , then we can set it using a colon:

The colon shows “what : goes where”. In the example above the property goes to , property goes to , and is assigned to the same name.

For potentially missing properties we can set default values using , like this:

Just like with arrays or function parameters, default values can be any expressions or even function calls. They will be evaluated if the value is not provided.

The code below asks for width, but not the title.

We also can combine both the colon and equality:

The rest operator

What if the object has more properties than we have variables? Can we take some and then assign the “rest” somewhere?

The specification for using the rest operator (three dots) here is almost in the standard, but most browsers do not support it yet.

It looks like this:

Nested destructuring

If an object or an array contain other objects and arrays, we can use more complex left-side patterns to extract deeper portions.

In the code below has another object in the property and an array in the property . The pattern at the left side of the assignment has the same structure:

The whole object except that was not mentioned, is assigned to corresponding variables.

Finally, we have , , , and from the default value.

That often happens with destructuring assignments. We have a complex object with many properties and want to extract only what we need.

Even here it happens:

Smart function parameters

There are times when a function may have many parameters, most of which are optional. That’s especially true for user interfaces. Imagine a function that creates a menu. It may have a width, a height, a title, items list and so on.

Here’s a bad way to write such function:

In real-life the problem is how to remember the order of arguments. Usually IDEs try to help us, especially if the code is well-documented, but still… Another problem is how to call a function when most parameters are ok by default.

Like this?

That’s ugly. And becomes unreadable when we deal with more parameters.

Destructuring comes to the rescue!

We can pass parameters as an object, and the function immediately destructurizes them into variables:

We can also use more complex destructuring with nested objects and colon mappings:

The syntax is the same as for a destructuring assignment:

Please note that such destructuring assumes that does have an argument. If we want all values by default, then we should specify an empty object:

We can fix this by making the default value for the whole destructuring thing:

In the code above, the whole arguments object is by default, so there’s always something to destructurize.

Summary

  • Destructuring assignment allows for instantly mapping an object or array onto many variables.

  • The object syntax:

    This means that property should go into the variable and, if no such property exists, then value should be used.

  • The array syntax:

    The first item goes to , the second goes into , all the rest makes the array .

  • For more complex cases, the left side must have the same structure as the right one.

Unwanted elements of the array can also be thrown away via an extra comma:

In the code above, although the first and second elements of the array are skipped, the third one is assigned to , and the rest are also skipped.

In the previous chapter we saw the Object.entries(obj) method.

We can use it with destructuring to loop over keys-and-values of an object:

…And the same for a map:

In the examples above variables were declared right before the assignment: . Of course, we could use existing variables too. But there’s a catch.

This won’t work:

The problem is that JavaScript treats in the main code flow (not inside another expression) as a code block. Such code blocks can be used to group statements, like this:

To show JavaScript that it’s not a code block, we can wrap the whole assignment in brackets :

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

The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.

Syntax

var a, b, rest; [a, b] = [10, 20]; console.log(a); // 10 console.log(b); // 20 [a, b, ...rest] = [10, 20, 30, 40, 50]; console.log(a); // 10 console.log(b); // 20 console.log(rest); // [30, 40, 50] ({ a, b } = { a: 10, b: 20 }); console.log(a); // 10 console.log(b); // 20 // Stage 3 proposal ({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}); console.log(a); // 10 console.log(b); // 20 console.log(rest); //{c: 30, d: 40}

Description

The object and array literal expressions provide an easy way to create ad hoc packages of data.

var x = [1, 2, 3, 4, 5];

The destructuring assignment uses similar syntax, but on the left-hand side of the assignment to define what values to unpack from the sourced variable.

var x = [1, 2, 3, 4, 5]; var [y, z] = x; console.log(y); // 1 console.log(z); // 2

This capability is similar to features present in languages such as Perl and Python.

Array destructuring

Basic variable assignment

var foo = ['one', 'two', 'three']; var [one, two, three] = foo; console.log(one); // "one" console.log(two); // "two" console.log(three); // "three"

Assignment separate from declaration

A variable can be assigned its value via destructuring separate from the variable's declaration.

var a, b; [a, b] = [1, 2]; console.log(a); // 1 console.log(b); // 2

Default values

A variable can be assigned a default, in the case that the value unpacked from the array is .

var a, b; [a=5, b=7] = [1]; console.log(a); // 1 console.log(b); // 7

Swapping variables

Two variables values can be swapped in one destructuring expression.

Without destructuring assignment, swapping two values requires a temporary variable (or, in some low-level languages, the XOR-swap trick).

var a = 1; var b = 3; [a, b] = [b, a]; console.log(a); // 3 console.log(b); // 1

Parsing an array returned from a function

It's always been possible to return an array from a function. Destructuring can make working with an array return value more concise.

In this example, returns the values as its output, which can be parsed in a single line with destructuring.

function f() { return [1, 2]; } var a, b; [a, b] = f(); console.log(a); // 1 console.log(b); // 2

Ignoring some returned values

You can ignore return values that you're not interested in:

function f() { return [1, 2, 3]; } var [a, , b] = f(); console.log(a); // 1 console.log(b); // 3

You can also ignore all returned values:

[,,] = f();

Assigning the rest of an array to a variable

When destructuring an array, you can unpack and assign the remaining part of it to a variable using the rest pattern:

var [a, ...b] = [1, 2, 3]; console.log(a); // 1 console.log(b); // [2, 3]

Note that a will be thrown if a trailing comma is used on the left-hand side with a rest element:

var [a, ...b,] = [1, 2, 3]; // SyntaxError: rest element may not have a trailing comma

Unpacking values from a regular expression match

When the regular expression method finds a match, it returns an array containing first the entire matched portion of the string and then the portions of the string that matched each parenthesized group in the regular expression. Destructuring assignment allows you to unpack the parts out of this array easily, ignoring the full match if it is not needed.

function parseProtocol(url) { var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url); if (!parsedURL) { return false; } console.log(parsedURL); // ["https://developer.mozilla.org/en-US/Web/JavaScript", "https", "developer.mozilla.org", "en-US/Web/JavaScript"] var [, protocol, fullhost, fullpath] = parsedURL; return protocol; } console.log(parseProtocol('https://developer.mozilla.org/en-US/Web/JavaScript')); // "https"

Object destructuring

Basic assignment

var o = {p: 42, q: true}; var {p, q} = o; console.log(p); // 42 console.log(q); // true

Assignment without declaration

A variable can be assigned its value with destructuring separate from its declaration.

var a, b; ({a, b} = {a: 1, b: 2});

The round braces  around the assignment statement is required syntax when using object literal destructuring assignment without a declaration.

is not valid stand-alone syntax, as the on the left-hand side is considered a block and not an object literal.

However, is valid, as is

Assigning to new variable names

A property can be unpacked from an object and assigned to a variable with a different name than the object property.

var o = {p: 42, q: true}; var {p: foo, q: bar} = o; console.log(foo); // 42 console.log(bar); // true

Default values

A variable can be assigned a default, in the case that the value unpacked from the object is .

var {a = 10, b = 5} = {a: 3}; console.log(a); // 3 console.log(b); // 5

Assigning to new variables names and providing default values

A property can be both 1) unpacked from an object and assigned to a variable with a different name and 2) assigned a default value in case the unpacked value is .

var {a:aa = 10, b:bb = 5} = {a: 3}; console.log(aa); // 3 console.log(bb); // 5

Setting a function parameter's default value

ES5 version

function drawES5Chart(options) { options = options === undefined ? {} : options; var size = options.size === undefined ? 'big' : options.size; var cords = options.cords === undefined ? {x: 0, y: 0} : options.cords; var radius = options.radius === undefined ? 25 : options.radius; console.log(size, cords, radius); // now finally do some chart drawing } drawES5Chart({ cords: {x: 18, y: 30}, radius: 30 });

ES2015 version

function drawES2015Chart({size = 'big', cords = {x: 0, y: 0}, radius = 25} = {}) { console.log(size, cords, radius); // do some chart drawing } drawES2015Chart({ cords: {x: 18, y: 30}, radius: 30 });

In the function signature for above, the destructured left-hand side is assigned to an empty object literal on the right-hand side: . You could have also written the function without the right-hand side assignment. However, if you leave out the right-hand side assignment, the function will look for at least one argument to be supplied when invoked, whereas in its current form, you can simply call without supplying any parameters. The current design is useful if you want to be able to call the function without supplying any parameters, the other can be useful when you want to ensure an object is passed to the function.

Nested object and array destructuring

var metadata = { title: 'Scratchpad', translations: [ { locale: 'de', localization_tags: [], last_edit: '2014-04-14T08:43:37', url: '/de/docs/Tools/Scratchpad', title: 'JavaScript-Umgebung' } ], url: '/en-US/docs/Tools/Scratchpad' }; var {title: englishTitle, translations: [{title: localeTitle}]} = metadata; console.log(englishTitle); // "Scratchpad" console.log(localeTitle); // "JavaScript-Umgebung"

For of iteration and destructuring

var people = [ { name: 'Mike Smith', family: { mother: 'Jane Smith', father: 'Harry Smith', sister: 'Samantha Smith' }, age: 35 }, { name: 'Tom Jones', family: { mother: 'Norah Jones', father: 'Richard Jones', brother: 'Howard Jones' }, age: 25 } ]; for (var {name: n, family: {father: f}} of people) { console.log('Name: ' + n + ', Father: ' + f); } // "Name: Mike Smith, Father: Harry Smith" // "Name: Tom Jones, Father: Richard Jones"

Unpacking fields from objects passed as function parameter

function userId({id}) { return id; } function whois({displayName, fullName: {firstName: name}}) { console.log(displayName + ' is ' + name); } var user = { id: 42, displayName: 'jdoe', fullName: { firstName: 'John', lastName: 'Doe' } }; console.log('userId: ' + userId(user)); // "userId: 42" whois(user); // "jdoe is John"

This unpacks the , and from the user object and prints them.

Computed object property names and destructuring

Computed property names, like on object literals, can be used with destructuring.

let key = 'z'; let {[key]: foo} = {z: 'bar'}; console.log(foo); // "bar"

Rest in Object Destructuring

The Rest/Spread Properties for ECMAScript proposal (stage 3) adds the rest syntax to destructuring. Rest properties collect the remaining own enumerable property keys that are not already picked off by the destructuring pattern.

let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40} a; // 10 b; // 20 rest; // { c: 30, d: 40 }

Invalid JavaScript identifier as a property name

Destructuring can be used with property names that are not valid JavaScript identifiers by providing an alternative identifer that is valid.

const foo = { 'fizz-buzz': true }; const { 'fizz-buzz': fizzBuzz } = foo; console.log(fizzBuzz); // "true"

Specifications

Browser compatibility

The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Basic support4914411 No Yes8
Computed property names491434 No Yes No
Rest in arrays4914234 No Yes No
Rest in objects60 No55 No Yes No
FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Basic support494914411 Yes8 ?
Computed property names49491434 Yes No ?
Rest in arrays494914234 Yes No ?
Rest in objects6060 No55 Yes No ?

1. Firefox provided a non-standard destructuring implementation from Firefox 2 to 40.

2. From version 14: this feature is behind the preference.

DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidEdge MobileFirefox for AndroidOpera for AndroidiOS SafariSamsung InternetNode.js
Basic supportFull support 49Full support 14Full support 41

Notes

Full support 41

Notes

Notes Firefox provided a non-standard destructuring implementation from Firefox 2 to 40.
No support NoFull support YesFull support 8Full support 49Full support 49Full support 14Full support 41

Notes

Full support 41

Notes

Notes Firefox provided a non-standard destructuring implementation from Firefox 2 to 40.
Full support YesFull support 8 ? Full support Yes
Computed property namesFull support 49Full support 14Full support 34No support NoFull support YesNo support NoFull support 49Full support 49Full support 14Full support 34Full support YesNo support No ? Full support Yes
Rest in arraysFull support 49Full support 14

Disabled

Full support 14

Disabled

Disabled From version 14: this feature is behind the preference.
Full support 34No support NoFull support YesNo support NoFull support 49Full support 49Full support 14

Disabled

Full support 14

Disabled

Disabled From version 14: this feature is behind the preference.
Full support 34Full support YesNo support No ? Full support Yes
Rest in objects

Experimental

Full support 60No support NoFull support 55No support NoFull support YesNo support NoFull support 60Full support 60No support NoFull support 55Full support YesNo support No ? Full support Yes

Legend

Full support
Full support
No support
No support
Compatibility unknown
Compatibility unknown
Experimental. Expect behavior to change in the future.
Experimental. Expect behavior to change in the future.
See implementation notes.
See implementation notes.
User must explicitly enable this feature.
User must explicitly enable this feature.

See also

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *