One of the problems in the chapter on Arrays and Collections in Modern JavaScript for the Impatient is

Implement a function that works exactly like the from function of the Array class. Pay careful attention to missing elements. What happens with objects that have keys whose numeric values are ≥ the length property? With properties that are not index properties?

This was a good way to try a few things in JavaScript. The code I wrote to do this seems to work well:

function myFrom (arrayLike, fn) {
    let result = [];
    // if iterable, create directly
    if (typeof arrayLike[Symbol.iterator] === 'function') {
        for (const e of arrayLike) {
            if (fn === undefined) {
                result.push(e);
            } else {
                if ( typeof fn !== 'function') {
                    throw new TypeError(`${fn} is not a function`);
                }
                result.push(fn(e));
            }
        }
        return result;
    }
    // create from an object with length propery
    for (let i = 0; i < arrayLike.length; i++) {
        result[i] = arrayLike[i];
    } // put map function here
    return result;
}

This returns the expected results net of the map function on the create from object as it is pretty much the same as the previous function map. If there are keys larger than the length property are not added. Properties that are not indexes are added as undefined.

I learned a couple of things doing this. Template literals are very handy for creating Error objects. Not having strongly typed function inputs means you have to test them instead of relying on a type in the function definition.