Q16: Implement a polyfill for Array.from().
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.