# Improving the speed of loop in javascript for objects

So I have a loop that works great, but doing some testing I notice it is a bit slow. I get an average time within the loop of about 0.11 seconds. Include that with some arrays containing a length of over 100 and the time starts making a big difference. So I mainly want to improve the speed of the loop without compromising the functionality it already has (which is taking a JSON object/array and turning it into an html format). Below is the code along with the function that is called within the loop.

let replacements = '';
let ind = 0;
for (let w in obj[key]) {
if (Array.isArray(obj[key])) {
if (Array.isArray(obj[key][w])) {
if (obj[key].length > 10) {
replacements += "<font color='green'>Array(" + obj[key].length + ")</font>"
break
}
replacements += ((ind == 0) ? "<font color='green'>Array(" : ", <font color='green'>Array(") + obj[key][w].length + ")</font>";
} else {
if (typeof obj[key][w] === 'object') {
replacements += ((ind == 0) ? "" : ", ") + "{...}";
} else {
replacements += ((ind == 0) ? "" : ", ") + ObjectString(obj[key][w], "preview");
}
}
} else {
if (Array.isArray(obj[key][w]) || typeof obj[key][w] === 'object') {
replacements += ((ind == 0) ? "" : ", ") + w + ": " + ((Array.isArray(obj[key][w])) ? "[...]" : "{...}");
} else {
replacements += ((ind == 0) ? "" : ", ") + w + ": ";
replacements += ObjectString(obj[key][w], "preview");
}
}
ind++;
}

function ObjectString(obj, type) { //~0.001-0.003 seconds
let objString = obj;
if (typeof objString == "string" && !objString.match(/<.*?>/g))
objString = "<font color='red'>\"" + objString + "\"</font>";
else if (/<.*?>/g.test(objString))
objString = ((type == "normal") ? "<pre>" + process(objString).replace(/</g, '&lt;').replace(/>/g, '&gt;') + "</pre>" + objString : "<font color='red'>\"...\"</font>");
else if (typeof objString == "number" || typeof objString == "boolean")
objString = "<font color=' #947cf6'>" + objString + "</font>";

return objString
}

function process(str) {//~0.001 seconds

var div = document.createElement('div');
div.innerHTML = str.trim();

return format(div, 0).innerHTML;
}


Hopefully this can be optimized to increase its speed, but if it can't then I would at least like some help to clean it up as I am sure this isn't the most effective way to do it. Thanks!

Edit: added the process function that was previous missing. Also for clarification I am using regular JSON arrays and objects that usually exceed 100 objects in the array. If you want an example of what that data could look like https://en.wikipedia.org/wiki/GeoJSON#Example has a good structure of some of the data I am parsing (containing both objects and arrays).

• What methods have you tried? I could be wrong, but for... in I think is slower than other methods, like a straight for(let x = 0; x < length; x++) method. To clean this up, you may want to look at a simple template engine like mustache. That would remove your html and probably do most of the heavy lifting. – Rager Oct 17 '19 at 16:18
• You are right with the for...in statement, they are generally slower. I tested moving it to a standard loop, but it seems like the major break is the check if its an array or object. – Manny K SoSo Oct 17 '19 at 16:39
• I think you're right. Is it a possibility to cast everything as desired type instead of checking? Or use the old JSON.parse(JSON.strigify(obj)) as a cast method? – Rager Oct 17 '19 at 16:57
• Or use Object.keys(obj).map() instead of checks. – Rager Oct 17 '19 at 16:59
• isArray and typeof can execute millions of times in 110ms and not the cause of the slowdown. It is the DOM as you create a div and then add HTML to it in process. That will be very slow, also the function format what ever it does? could make it even worse – Blindman67 Oct 17 '19 at 17:37

• Continuous repetitive string concatenation is bad for performance because each such operation requires re-hashing of the string due to String interning.
• Array enumeration using for-in loop is slower than for-of or a standard for loop.
• Things like obj[key][subkey] may be slow in a long loop so cache them in a variable.
• Do the proper performance measurements using Devtools Timeline profiler to find bottlenecks.

Here's an arguably more readable and hopefully faster example:

const parts = [];
const group = obj[key];

if (Array.isArray(group)) {
for (const val of group) {
if (parts.length) parts.push(', ');
if (Array.isArray(val)) {
const tooLong = group.length > 10;
const len = (tooLong ? group : val).length;
parts.push(<font color="green">Array(${len})</font>); if (tooLong) break; } else { parts.push(objectPreview(val)); } } } else { for (const [key, val] of Object.entries(group)) { parts.push(${parts.length ? ', ' : ''}${key}:${
Array.isArray(val) ? '[...]' : objectPreview(val)
});
}
}
const replacements = parts.join('');

function objectPreview(obj) {
let str = obj;
switch (typeof obj) {
case 'object':
str = '{...}';
break;
case 'string':
if (/<.*?>/.test(obj)) {
str = type === 'normal' ?
<pre>${process(obj).replace(/</g, '&lt;').replace(/>/g, '&gt;')}</pre>${obj} :
'<font color="red">"..."</font>';
} else {
str = <font color="red">"${obj}"</font>; } break; case 'number': case 'boolean': str = <font color="#947cf6">${obj}</font>;
break;
}
return str;
}

• I didn't realize that calling things like obj[key][subkey] caused slowdown's like it has. I will keep this in mind in the future. I also didn't think about using Template literals inside my code would clean it up that much, I will also keep this in mind for the future. And the switch case for readability was also something I didn't think of (since its easier to read and maintain in this form). With testing performance of 400+ entries (the most I encounter) I see no slow down. Thanks! – Manny K SoSo Oct 21 '19 at 13:11