Stop calling it spread operator

Stop calling it spread operator

You may know the 3 dots notations ...

On the web, hashnode too, you can find tons of articles that talk about this new operator, which has become essential if you need to clone arrays, objects, merge stuff or pass unlimited params to a function.

Sadly, it has been a huge misconception since it was introduced. Stackoverflow has over 10k questions about this operator, even though it really isn't.

First of all, what is an operator in Javascript ?

Semantically, in the context of ECMAScript, operators are just builtin functions that take in arguments and evaluate to a single value.

Common operators are:

  • Assignment Operators =, +=, =+ etc
  • Arithmetic Operators +, -, *, / etc
  • Comparison Operators ==, >, <, ≥ ,≤ etc
  • Logical Operators &&, ||, !x
  • Bitwise Operators & | ~
  • String Operators +
  • Other Operators delete, typeof, in, instanceof

Operators behave the same way every time. They always get the same result regardless of context. Operators define an action that will be done in the code. It's always the same action. Sometimes operators might be overloaded like +:

const numbers = 1 + 2
const letters = '1' + '2'
numbers // 3
letters // '12'

Why ... isn't an operator?

Let's do some test. We know that the operators are standalone and they return a single value. Three dots without contest generate an error:

const spreadLetters = [...letters]
spreadLetters // ['1','2']

const spreadLettersNoArray = ...letters
// Error: Uncaught SyntaxError: Unexpected token '...'

If spread 'operator' were a real operator, the latter would work fine because operators evaluate the expression to a single value but spread doesn't so it fails.

So, what is it?

We call it operator, but it is just a syntax. Syntax needs, necessary, a contest for work.

const arr = [1, 2, 3]
const obj = { foo: "hello", bar: "world" }

const getMax = Math.max(...arr)   // spread arguments in a function call
getMax // 3

const cloneArray = [...arr]  // spread an iterable var into an array
cloneArray // [1,2,3]

const cloneObj = { ...obj }  //spread a key:value list into an object 
cloneObj // { foo: "hello", bar: "world" }

Did you notice ? They look really similar, but they have different behave, based on the context. We can do the final test: use the same syntax in different contest:

{ ...undefined } // {}
[ ...undefined] // undefined is not iterable

Why the array casue an error, and the object continue working?

Write { ...undefined } is like write Object.assign({}, undefined) and quoting Object.assign() from ECMASCRIPT:

If the source object is undefined or null, let keys be an empty List

For the arrays the spread element works if the source element is iterable, where an iterable element must have a property with the key @@iterator.

We can check this operator just looking for the functions Symbol.iterator:

const array = [1,2,3]
array[Symbol.iterator] // ƒ values() { [native code] }

Since undefined doesn't have the iterator symbol, will cause an error.

Let me know your thoughts.