• Home   /  
  • Archive by category "1"

Es6 Spread Assignment Notebook

Destructuring assignment sounds complex. It reminds me of object oriented terms such as encapsulation and polymorphism — I’m convinced they were chosen to make simple concepts appear more sophisticated!

In essence, ECMAScript 6 (ES2015) destructuring assignment allows you to extract individual items from arrays or objects and place them into variables using a shorthand syntax. Those coming from PHP may have encountered the list() function which extracts arrays into variables in one operation. ES6 takes it to another level.

Presume we have an array:

We can extract these values by index in ES5:

ES6 destructuring permits a simpler and less error-prone alternative:

You can ignore certain values, e.g.

or use the spread operator () to extract remaining elements:

Destructuring also works on objects, e.g.

In this example, the variable names , and matched the object property names. We can also assign properties to variables with any name, e.g.

More complex nested objects can also be referenced, e.g.

This appears a little complicated but remember that in all destructuring assignments:

  • the left-hand side of the assignment is the destructuring target; the pattern which defines the variables being assigned
  • the right-hand side of the assignment is the destructuring source; the array or object which holds the data being extracted

There are a number of other caveats. First, you cannot start a statement with a curly brace because it looks like a code block, e.g.

You must either declare the variables, e.g.

or use parenthesis if variables are already declared, e.g.

You should also be wary of mixing declared and undeclared variables, e.g.

That’s the basics of destructuring. So when would it be useful? I’m glad you asked…

Easier Declaration

Variables can be declared without explicitly defining each value, e.g.

Admittedly, the destructured version is longer. It’s a little easier to read although that may not be the case with more items.

Variable Value Swapping

Swapping values in ES5 requires a temporary third variable but it’s far simpler with destructuring:

You’re not limited to two variables — any number of items can be rearranged, e.g.

Default Function Parameters

Presume we had a function to output our object:

In ES5, it’s necessary to parse this object to ensure appropriate defaults are available, e.g.

In ES6 we can assign a default value to any parameter, e.g.

but we can then use destructuring to extract values and assign defaults where necessary:

I’m not convinced this is easier to read but it is significantly shorter.

Returning Multiple Values from a Function

Functions can only return one value but that can be a complex object or multi-dimensional array. Destructuring assignment makes this more practical, e.g.

For-of Iteration

Consider an array of book information:

The ES6 for-of is similar to except that it extracts each value rather than the index/key, e.g.

Destructuring assignment provides further enhancements, e.g.

Regular Expression Handling

Regular expressions functions such as match return an array of matched items which can form the source of a destructuring assignment:

Destructuring Assignment Support

Destructuring assignment may not revolutionize your development life but it could save some considerable typing effort!

As of end 2015, support for destructuring assignment is still incomplete. It’s available in Firefox 34+ with basic features in Safari 7.1+. Experimental support is available in Node 4.0+ if you run Node with the flag but it’s best not to depend on it.

Until ES6 is generally available, compilers such as Babel and Traceur will translate ES6 destructuring assignments to an ES5 equivalent.

Craig is a freelance UK web consultant who built his first page for IE2.0 in 1995. Since that time he's been advocating standards, accessibility, and best-practice HTML5 techniques. He's written more than 1,000 articles for SitePoint and you can find him @craigbuckler

Spread syntax allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

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

For function calls:

myFunction(...iterableObj);

For array literals or strings:

[...iterableObj, '4', 'five', 6];

For object literals (new in ECMAScript 2018):

let objClone = { ...obj };

Examples

Spread in function calls

Replace apply

It is common to use in cases where you want to use the elements of an array as arguments to a function.

function myFunction(x, y, z) { } var args = [0, 1, 2]; myFunction.apply(null, args);

With spread syntax the above can be written as:

function myFunction(x, y, z) { } var args = [0, 1, 2]; myFunction(...args);

Any argument in the argument list can use spread syntax and it can be used multiple times.

function myFunction(v, w, x, y, z) { } var args = [0, 1]; myFunction(-1, ...args, 2, ...[3]);

Apply for new

When calling a constructor with , it's not possible to directly use an array and  ( does a and not a ). However, an array can be easily used with new thanks to spread syntax:

var dateFields = [1970, 0, 1]; // 1 Jan 1970 var d = new Date(...dateFields);

To use new with an array of parameters without spread syntax, you would have to do it indirectly through partial application:

function applyAndNew(constructor, args) {    function partial () {     return constructor.apply(this, args);    };    if (typeof constructor.prototype === "object") {    partial.prototype = Object.create(constructor.prototype);   }   return partial; } function myConstructor () {    console.log("arguments.length: " + arguments.length);    console.log(arguments);    this.prop1="val1";    this.prop2="val2"; }; var myArguments = ["hi", "how", "are", "you", "mr", null]; var myConstructorWithArguments = applyAndNew(myConstructor, myArguments); console.log(new myConstructorWithArguments); // (internal log of myConstructor): arguments.length: 6 // (internal log of myConstructor): ["hi", "how", "are", "you", "mr", null] // (log of "new myConstructorWithArguments"): {prop1: "val1", prop2: "val2"}

Spread in array literals

A more powerful array literal

Without spread syntax, to create a new array using an existing array as one part of it, the array literal syntax is no longer sufficient and imperative code must be used instead using a combination of , , , etc. With spread syntax this becomes much more succinct:

var parts = ['shoulders', 'knees']; var lyrics = ['head', ...parts, 'and', 'toes']; // ["head", "shoulders", "knees", "and", "toes"]

Just like spread for argument lists,  can be used anywhere in the array literal and it can be used multiple times.

Copy an array

var arr = [1, 2, 3]; var arr2 = [...arr]; // like arr.slice() arr2.push(4); // arr2 becomes [1, 2, 3, 4] // arr remains unaffected

Note: Spread syntax effectively goes one level deep while copying an array. Therefore, it may be unsuitable for copying multidimensional arrays as the following example shows (it's the same with and spread syntax).

var a = [[1], [2], [3]]; var b = [...a]; b.shift().shift(); // 1 // Now array a is affected as well: [[], [2], [3]]

A better way to concatenate arrays

is often used to concatenate an array to the end of an existing array. Without spread syntax this is done as:

var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; // Append all items from arr2 onto arr1 arr1 = arr1.concat(arr2);

With spread syntax this becomes:

var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1 = [...arr1, ...arr2];

is often used to insert an array of values at the start of an existing array.  Without spread syntax this is done as:

var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; // Prepend all items from arr2 onto arr1 Array.prototype.unshift.apply(arr1, arr2) // arr1 is now [3, 4, 5, 0, 1, 2]

With spread syntax this becomes [Note, however, that this creates a new array. Unlike , it does not modify the original array in-place]:

var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1 = [...arr2, ...arr1]; // arr1 is now [3, 4, 5, 0, 1, 2]

Spread in object literals

The Rest/Spread Properties for ECMAScript proposal (stage 4) adds spread properties to object literals. It copies own enumerable properties from a provided object onto a new object.

Shallow-cloning (excluding prototype) or merging of objects is now possible using a shorter syntax than .

var obj1 = { foo: 'bar', x: 42 }; var obj2 = { foo: 'baz', y: 13 }; var clonedObj = { ...obj1 }; // Object { foo: "bar", x: 42 } var mergedObj = { ...obj1, ...obj2 }; // Object { foo: "baz", x: 42, y: 13 }

Note that triggers setters whereas spread syntax doesn't.

Only for iterables

Spread syntax (other than in the case of spread properties) can be applied only to iterable objects:

var obj = {'key1': 'value1'}; var array = [...obj]; // TypeError: obj is not iterable

Spread with many values

When using spread syntax for function calls, be aware of the possibility of exceeding the JavaScript engine's argument length limit. See  for more details.

Rest syntax (parameters)

Rest syntax looks exactly like spread syntax, but is used for destructuring arrays and objects. In a way, rest syntax is the opposite of spread syntax: spread 'expands' an array into its elements, while rest collects multiple elements and 'condenses' them into a single element. See rest parameters.

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.

DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidEdge MobileFirefox for AndroidOpera for AndroidiOS SafariSamsung InternetNode.js
Spread in array literalsFull support 46Full support 12Full support 16No support NoFull support 37Full support 8Full support 46Full support 46Full support 12Full support 16Full support 37Full support 8 ? Full support Yes
Spread in function callsFull support 46Full support 12Full support 27No support NoFull support 37Full support 8Full support 46Full support 46Full support 12Full support 27Full support 37Full support 8 ? Full support Yes
Spread in destructuringFull support 49No support NoFull support 34No support NoFull support 37 ? Full support 49Full support 49No support NoFull support 34Full support 37 ? ? Full support Yes
Spread in object literals

Experimental

Full support 60No support NoFull support 55No support No ? No support NoFull support 60Full support 60No support NoFull support 55 ? No support No ? No support No

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 also

FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Spread in array literals46461216378 ?
Spread in function calls46461227378 ?
Spread in destructuring4949 No3437 ? ?
Spread in object literals6060 No55 ? No ?

One thought on “Es6 Spread Assignment Notebook

Leave a comment

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati *