Skip to content

Spread syntax

Internally in ixfx and in demos, the spread syntax is used a lot.

Making objects

Our primary use is making objects from the basis of an existing object. This allows us to maintain immutability.

For example, let’s say we have immutable Jane. We’re not using Object.freeze() to enforce immutability, but it’s something we’re striving for.

const jane = {
name: `Jane`,
size: 12,
colour: `red`
}

Her colour preference has changed to blue. Since she’s immutable we can’t just use jane.colour = 'blue'.

Rather, we make a new object:

const newJane = {
} // { }

Copy all the things over from jane:

const newJane = {
...jane
} // { name: `Jane`, size: 12, colour: `red` }

And then override or add new properties:

const newJane = {
...jane,
colour: `blue`
} // { name: `Jane`, size: 12, colour: `blue` }

Properties are assigned in the listed order. If we had swapped the lines, our change would have no effect because the old colour value would overwrite the new:

const newJane = {
colour: `blue`,
...jane
}; // { name: `Jane`, size: 12, colour: `red` }

In the above example we used two different variable names for clarity, but using let would allow us to recycle the name:

let jane = { name: `Jane`, size: 12, colour: `red` };
jane = {
...jane,
colour: `blue`
}

Making defaults

This syntax is also helpful for having some default options which are then selectively overridden, for example:

const defaultOptions = {
speed: 10,
direction: 90
}
function doAThing(userOptions) {
// Combine the two, with 'userOptions'
// overriding the defaults
const options = {
...defaultOptions,
...userOptions
};
}
doAThing({ speed: 12 });

Object.assign()

If you don’t have the spread syntax available (eg. on Espruino) you may be able to use Object.assign():

const myObj = { value: 5 };
const a = Object.assign({}, myObj, { value: 10 });
// Same as: const a = { ...myObj, value: 10 }

With Object.assign, the first parameter is the target, the object we want to copy things to. In this case we need a new object, so {} is provided. After that, list all the objects in order you want to copy. In the above example, first myObj is used, then the { value: 10 } anonymous object.

Manipulating arrays

The spread syntax can likewise be used with arrays

// Combine two arrays
const a = [1, 2, 3];
const b = [4, 5, 6];
const c = [...a, ...b]; // [1,2,3,4,5,6]
// Add a value to the beginning
const a = [1,2,3]
const b = [4, ...a]; // [4,1,2,3]
// End
const c = [5, ...a]]; // [1,2,3,5];
// Middle
const d = [6, ...a, 7]; // [6,1,2,3,7]

Function parameters

Another place you’ll see the spread operator is with functions.

function workIt(name, ...args) {
console.log(`Hello ${name}`)
for (const a of args) {
console.log(a);
}
}

This allows the function to have zero or more parameters that get passed in as a comma-separated list. In this case, we have one normal parameter, name, and then the spread parameter, args (but it can be called whatever you like).

// Call with no other args
workIt(`max`)
// ...with one
workIt(`max`, 1);
// ...or as many as we want
workIt(`cherry`, 1, 2, 3);

Inside the function, args is an array that can be used as normal (in this example using a for of loop).

Spreads can be provided when calling a function too. For example, if we have an array, but the function expects a comma-separated list of parameters, we can we can spread the array:

const arr = [1,2,3];
workIt(`hi`, arr); // This won't work as expected, `args` will end up being [[1,2,3]]
workIt(`hi`, ...arr); // That's better! `args` will be [1,2,3]
// ^ Same as calling: workIt(1, 2, 3)