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 arraysconst a = [1, 2, 3];const b = [4, 5, 6];const c = [...a, ...b]; // [1,2,3,4,5,6]
// Add a value to the beginningconst a = [1,2,3]const b = [4, ...a]; // [4,1,2,3]// Endconst c = [5, ...a]]; // [1,2,3,5];// Middleconst 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 argsworkIt(`max`)// ...with oneworkIt(`max`, 1);// ...or as many as we wantworkIt(`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)