Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spreading undefined in array vs object

Why does spreading undefined in an object return an empty object? {...undefined} // equals {}:

console.log({...undefined})

And Why does spreading undefined in an array give you an error? [...undefined] // type error:

console.log([...undefined])
like image 575
0xtimur Avatar asked Nov 07 '17 10:11

0xtimur


People also ask

Can you spread an array of objects?

Spread syntax can be used when all elements from an object or array need to be included in a new array or object, or should be applied one-by-one in a function call's arguments list. There are three distinct places that accept the spread syntax: Function arguments list ( myFunction(a, ... iterableObj, b) )

Can I spread undefined?

Spreading into an Array We need an empty array at end because we cannot spread undefined or null into an array (they are not iterables). Spreading an empty array into another just keeps the array intact.

Does spread operator work on objects?

Object spread operator can be used to clone an object or merge objects into one. The cloning is always shallow. When merging objects, the spread operator defines new properties while the Object.

Does spread operator work on arrays?

The spread operator unpacks elements of iterable objects such as arrays, sets, and maps into a list. The rest paramter is also denoted by three dots (…). However, it packs the remaining arguments of a function into an array. The spread operator can be used to clone an iterable object or merge iterable objects into one.


2 Answers

As noted in the comments, and summarized by @ftor from #687, object spread is equivalent1 to Object.assign() (issues #687, #45), whereas spread in array literal context is iterable spread.

Quoting Ecma-262 6.0, Object.assign() is defined as:

19.1.2.1 Object.assign ( target, ...sources )

The assign function is used to copy the values of all of the enumerable own properties from one or more source objects to a target object. When the assign function is called, the following steps are taken:

  1. Let to be ToObject(target).
  2. ReturnIfAbrupt(to).
  3. If only one argument was passed, return to.
  4. Let sources be the List of argument values starting with the second argument.
  5. For each element nextSource of sources, in ascending index order, do
    1. If nextSource is undefined or null, let keys be an empty List.
    2. Else, ...

...followed by the description of copying own properties. The draft of Object Rest/Spread Properties is here. It is not a part of the Ecma-262 6.0.

A SpreadElement in an array literal expression is defined to begin as follows:

SpreadElement : ... AssignmentExpression

  1. Let spreadRef be the result of evaluating AssignmentExpression.
  2. Let spreadObj be GetValue(spreadRef).
  3. Let iterator be GetIterator(spreadObj).
  4. ReturnIfAbrupt(iterator).

And since undefined does not have a property with the key @@iterator, a TypeError is thrown, based on the steps of GetIterator. The standard is not an easy read, but if I'm not mistaken, the path to error is GetIterator -> GetMethod -> GetV -> ToObject, which throws a TypeError for undefined and null.

A simple remedy to using variables with possibly undefined value in array initialization is to use a default:

const maybeArray = undefined; const newArray = [ ...(maybeArray || []) ]; 

1: There is a difference in how setters are handled.

like image 145
Ilja Everilä Avatar answered Sep 19 '22 06:09

Ilja Everilä


Normally, uses of ...x requires x to be iterable because the point of ... is normally to flatten an iterable into its components.

However, {...x} requires x to be enumerable because we don't just need values, but keys along with them.

null is not iterable. It has no components, so it doesn't make sense to iterate over null. (for (const item of null) will similarly fail.)

However, null is enumerable. null is sometime treated as an object, this is one of those cases, and objects are enumerable because they can have properties. (for (const prop in null) will similarly succeed.)

like image 36
ikegami Avatar answered Sep 19 '22 06:09

ikegami