src/util.js
function forEach(item, method, context) {
    let type = getType(item);
    switch(type) {
        case types.date:
        case types.function:
        case types.object:
        case types.regexp:
            if (!item[Symbol.iterator]) {
                for (let [key, value] of _entries(item)) {
                    if (item.hasOwnProperty(key))
                        method.call(context, value, key, item);
                }
            }
            else { // shenanigans
                for (let value of item) {
                    // do we want to check if value is array, and spread it across value/key?
                    method.call(context, value, undefined, item);
                }
            }
            break;
        case types.arguments:
        case types.array:
            for (let i = 0; i < item.length; i++)
                method.call(context, item[i], i, item);
            break;
        case types.map:
            for (let [key, value] of item)
                method.call(context, value, key, item);
            break;
        case types.set:
            for (let value of item) // treat keys and values as equivalent for sets
                method.call(context, value, value, item);
            break;
        default:
            // if unknown type, then check for Symbol.iterator
            if (item[Symbol.iterator]) {
                for (let value of item[Symbol.iterator]())
                    method.call(context, value, undefined, item);
            }
            else if (!typeset.has(type) && type && type.constructor) {
                for (let [ key, value ] of _entries(item)) {
                    if (item.hasOwnProperty(key)) // necessary with _entries?
                        method.call(context, value, key, item);
                }
            }
            break;
    }
    return item;
}
function forEach(item, method, context) {
    let type = getType(item);
    switch(type) {
        case types.date:
        case types.function:
        case types.object:
        case types.regexp:
            if (!item[Symbol.iterator]) {
                for (let [key, value] of _entries(item)) {
                    if (item.hasOwnProperty(key))
                        method.call(context, value, key, item);
                }
            }
            else { // shenanigans
                for (let value of item) {
                    // do we want to check if value is array, and spread it across value/key?
                    method.call(context, value, undefined, item);
                }
            }
            break;
        case types.arguments:
        case types.array:
            for (let i = 0; i < item.length; i++)
                method.call(context, item[i], i, item);
            break;
        case types.map:
            for (let [key, value] of item)
                method.call(context, value, key, item);
            break;
        case types.set:
            for (let value of item) // treat keys and values as equivalent for sets
                method.call(context, value, value, item);
            break;
        default:
            // if unknown type, then check for Symbol.iterator
            if (item[Symbol.iterator]) {
                for (let value of item[Symbol.iterator]())
                    method.call(context, value, undefined, item);
            }
            else if (!typeset.has(type) && type && type.constructor) {
                for (let [ key, value ] of _entries(item)) {
                    if (item.hasOwnProperty(key)) // necessary with _entries?
                        method.call(context, value, key, item);
                }
            }
            break;
    }
    return item;
}
function forEach ( item , method , context ) { let type = getType ( item ) ; switch ( type ) { case types . date : case types . function : case types . object : case types . regexp : if ( ! item [ Symbol . iterator ] ) { for ( let [ key , value ] of _entries ( item ) ) { if ( item . hasOwnProperty ( key ) ) method . call ( context , value , key , item ) ; } } else { // shenanigans
 for ( let value of item ) { // do we want to check if value is array, and spread it across value/key?
 method . call ( context , value , undefined , item ) ; } } break ; case types . arguments : case types . array : for ( let i = 0 ; i < item . length ; i ++ ) method . call ( context , item [ i ] , i , item ) ; break ; case types . map : for ( let [ key , value ] of item ) method . call ( context , value , key , item ) ; break ; case types . set : for ( let value of item ) // treat keys and values as equivalent for sets
 method . call ( context , value , value , item ) ; break ; default : // if unknown type, then check for Symbol.iterator
 if ( item [ Symbol . iterator ] ) { for ( let value of item [ Symbol . iterator ] ( ) ) method . call ( context , value , undefined , item ) ; } else if ( ! typeset . has ( type ) && type && type . constructor ) { for ( let [ key , value ] of _entries ( item ) ) { if ( item . hasOwnProperty ( key ) ) // necessary with _entries?
 method . call ( context , value , key , item ) ; } } break ; } return item ; }
Generic interface for looping over an iterable,
and executing a provided method for each item.

@param {any} item The item over which to iterate.
@param {Function} method The callback to execute for each iterated value.
@param {any} context The optional context to pass to each callback.
@returns {any} A reference to the original item.
Generic interface for looping over an iterable and executing a provided method for each item .