Q16: Implement a polyfill for Array.from().

Difficulty:IntermediateTopic:Iterables

Answer

Array.from() creates a new array from an iterable or array-like object. It can also map each element through an optional callback.

if (!Array.myFrom) {
  Array.myFrom = function (source, mapFn, thisArg) {
    if (source == null) {
      throw new TypeError("Cannot convert null or undefined to an array");
    }

    if (mapFn !== undefined && typeof mapFn !== "function") {
      throw new TypeError("Mapping function must be callable");
    }

    const result = [];
    const mapper = mapFn === undefined ? null : mapFn;
    let index = 0;

    if (typeof source[Symbol.iterator] === "function") {
      for (const value of source) {
        result.push(
          mapper ? mapper.call(thisArg, value, index) : value
        );
        index++;
      }

      return result;
    }

    const object = Object(source);
    const length = Math.min(
      Math.max(Number(object.length) || 0, 0),
      Number.MAX_SAFE_INTEGER
    );

    for (let i = 0; i < length; i++) {
      const value = object[i];
      result.push(mapper ? mapper.call(thisArg, value, i) : value);
    }

    return result;
  };
}

console.log(Array.myFrom("hello"));
// ["h", "e", "l", "l", "o"]

console.log(Array.myFrom([1, 2, 3], n => n * 2));
// [2, 4, 6]

Explanation

An iterable exposes Symbol.iterator. Examples include strings, arrays, sets, and maps. An array-like object instead exposes a length and indexed properties.

The implementation above demonstrates both paths, but a standards-compliant version must handle length conversion, maximum array length, constructor behavior, and iterator errors precisely.

Key Takeaways
  • Array.from supports iterables and array-like objects.
  • Its optional mapping function transforms elements during array creation.