javascriptobjectis-empty

What makes an empty object qualify as an Iterable or Array-like object?


Given Array.from takes an iterable or array-like object as it's first argument, why does it not throw an error when passed an empty object, like this:

let emptyObject = Array.from( {} )

At iterable is defined as an object that implements the iterable protocol or the iterator protocol. An empty object seemingly does neither:

let emptyObject = {}

console.log(emptyObject[Symbol.iterator])
console.log(emptyObject['next'])
console.log(Array.from(emptyObject))

An Array-like object has a length property and can be indexed (ref). An empty object does not have a length property.

let emptyObject = {}

console.log(emptyObject['length'])
console.log(Array.from(emptyObject))

How does an empty object qualify?


Solution

  • Array.from() works with array-like objects. More specifically it only really needs the length property:

    console.log( Array.from({length: 5}) ); //array with 5 slots

    This is defined in starting at step 7. of the Array.from algorithm

    23.1.2.1 Array.from ( items [ , mapfn [ , thisArg ] ] )

    [...]

    1. Let arrayLike be ! ToObject(items).
    2. Let len be ? LengthOfArrayLike(arrayLike).

    [...]

    LengthOfArrayLike is only this step:

    7.3.18 LengthOfArrayLike ( obj )

    [...]

    Return ℝ(? ToLength(? Get(obj, "length"))).

    Which means to retrieve the value of the length property of an object and defer to ToLength to convert it to a number. ToLength is defined as the following:

    7.1.20 ToLength ( argument )

    [...]

    1. Let len be ? ToIntegerOrInfinity(argument).
    2. If len ≤ 0, return +0𝔽.
    3. Return 𝔽(min(len, 253 - 1)). Therefore a missing length means argument is undefined which at step 1. would be converted to zero.