Internal extend call.
Performance abstraction to bypass all the argument shenanigans,
as we know we will only be extending two items at a time internally.

@param {any} a The item on which to extend the second.
@param {any} b The item to extend onto the first.
@returns {any} The reference to the first item.
function _extend(a, b) {
    forEach(b, (bVal, key) => {
        let type = typeForExtend(a);
        switch(type) {
            case types.array:
            case types.object:
                if (a[key] === undefined || a[key] === null)
                    a[key] = b[key];
                else if (isExtendable(a[key], b[key]))
                    _extend(a[key], b[key]);
                break;
            case types.set:
                if (!a.has(bVal))
                    a.add(bVal);
                break;
            case types.map:
                if (!a.has(key))
                    a.set(key, bVal);
                else {
                    let aVal = a.get(key);
                    if (aVal === undefined || aVal === null)
                        a.set(key, bVal);
                    else if (isExtendable(aVal, bVal))
                        _extend(aVal, bVal);
                }
                break;
        }
    });
    return a;
}