Script Preparation code:
x
 
var obj = {};
for (i = 1000; i > 0; i--) {
  if (i%2 == 0) {
    obj[i] = 'String';
  } else {
    obj[i] = [ 'Array of String', 'Array of String' ];
  }
}
Tests:
  • forEach

     
    function ClassList(collection={}) {
        const classNames = {};
        const keys = Object.keys(collection);
        keys.forEach((key) => {
            const innerCollection = collection[key];
            const collectionCheck = Object.prototype.toString.call(innerCollection);
            switch (collectionCheck) {
            case '[object Object]': {
                const innerKeys = Object.keys(innerCollection);
                if (innerKeys.length === 0) {
                    classNames[key] = '';
                    break;
                }
                let classList = [];
                innerKeys.forEach((innerKey) => {
                    if (!innerCollection[innerKey] || !innerCollection[innerKey].length) {
                        return;
                    }
                    const innerCollectionCheck = Object.prototype.toString.call(innerCollection[innerKey]);
                    switch (innerCollectionCheck) {
                    case '[object Array]':
                        classList.push(...innerCollection[innerKey]);
                        break;
                    case '[object String]':
                        classList.push(innerCollection[innerKey]);
                        break;
                    }
                });
                classNames[key] = classList.reduce((acc, cl) => (acc += cl + ' '), '');
                break;
            }
            case '[object Array]':
                classNames[key] = innerCollection.reduce((acc, cl) => (acc += cl + ' '), '');
                break;
            case '[object String]':
                classNames[key] = innerCollection;
                break;
            }
        });
        return classNames;
    }
    ClassList( obj );
  • Recursive 1

     
    function recursor(obj, primaryKey, keys = [], classList = {}) {
        for (let k in obj) {
            const currentCol = obj[k];
            
            primaryKey = keys.indexOf(k) > -1 ? k : primaryKey;
            classList[primaryKey] = classList[primaryKey] || '';
            switch (Object.prototype.toString.call(currentCol)) {
            case '[object Object]': {
                classList[primaryKey] = '';
                if ( Object.keys(currentCol).length === 0 ) {
                    break;
                }
                recursor(currentCol, primaryKey, keys, classList);
                break;
            }
        
            case '[object Array]':
                classList[primaryKey] += currentCol.join(' ') + ' ';
                break;
        
            case '[object String]':
                classList[primaryKey] += currentCol + ' ';
                break;
            }
        }
        return classList;
    }
    function ClassList(collection = {}) {
        const keys = Object.keys(collection);
        return recursor(collection, false, keys);
    }
    ClassList( obj );
  • Recursive flatten

     
    function ClassList(collection = {}) {
        const result = {};
        function flatten(node, str) {
            const nodeType = Object.prototype.toString.call(node);
            
            switch (nodeType) {
                case '[object String]': {
                    str += node + ' ';
                    break;
                }
                case '[object Array]': {
                    str += node.join(' ') + ' ';
                    break;
                }
                case '[object Object]': {
                    for (const key in node) {
                        str += flatten(node[key], '');
                    }
                    break;
                }
            }
            
            return str;
        }
        for (const key in collection) {
            result[key] = flatten(collection[key], '').trimEnd();
        }
        return result;
    }
    ClassList(obj);
Rendered benchmark preparation results:

Suite status: <idle, ready to run>

Previous results

Experimental features:

  • Test case name Result
    forEach
    Recursive 1
    Recursive flatten

    Fastest: N/A

    Slowest: N/A

Latest run results:
Run details: (Test run date: 4 years ago)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15
Safari 13 on Mac OS X 10.15.6
View result in a separate tab
Test name Executions per second
forEach 2047.9 Ops/sec
Recursive 1 279.8 Ops/sec
Recursive flatten 1535.8 Ops/sec