JSFiddle - React, Tailwind, and code Playground
HTML
<div id="infoContainer" style="width:500px;">
<div>
Click the corresponding buttons below to benchmark counting object properties
using for...in versus Object.keys().
</div>
<table style="margin-top:10px;">
<tr>
<td style="padding-right:10px;width:0.01px;">
<button id="benchmarkButtonA">for (const key in obj) { ... }</button>
</td>
<td id="benchmarkResultsA"></td>
</tr>
<tr style="border-top-width:10px;">
<td style="padding-right:10px;width:0.01px;">
<button id="benchmarkButtonB">Object.keys(obj)</button>
</td>
<td id="benchmarkResultsB"></td>
</tr>
</table>
</div>
CSS
* {
margin: 0;
border: 0;
padding: 0;
box-sizing: border-box;
border-style: solid;
}
html {
height: 100%;
overflow: hidden;
font-size: 14px;
color: #ffffff;
}
body {
height: 100%;
overflow: hidden;
font-family: sans-serif;
background-color: #808080;
-webkit-user-drag: none;
position: relative;
}
.click-through {
&,
& * {
pointer-events: none;
}
}
table {
display: table;
width: 100%;
table-layout: auto;
border-collapse: collapse;
border-spacing: 0;
empty-cells: show;
}
tr,
td,
th {
vertical-align: middle;
}
tr {
border-color: transparent;
}
table.list > * > tr > *:first-child {
white-space: nowrap;
text-align: right;
width: 0.01px;
}
#infoContainer {
position: absolute;
inset: 0 auto auto 0;
background-color: rgba(0, 0, 0, 0.75);
padding: 10px;
z-index: 10;
}
button {
width:100%;
background-color: #005dc6;
color: #ffffff;
padding: 10px;
border-radius: 5px;
cursor: pointer;
position: relative;
white-space:nowrap;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
JavaScript
const iterations = 100_000_000;
const iterationsStr = addCommas(iterations);
const infoContainer = document.getElementById('infoContainer');
const benchmarkButtonA = document.getElementById('benchmarkButtonA');
const benchmarkButtonB = document.getElementById('benchmarkButtonB');
const benchmarkResultsA = document.getElementById('benchmarkResultsA');
const benchmarkResultsB = document.getElementById('benchmarkResultsB');
const obj = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
};
benchmarkButtonA.onclick = () => {
const t = benchmark(() => {
let i = 0;
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
i++;
}
}
const len = i;
});
benchmarkResultsA.innerHTML = `
${iterationsStr} iterations: ${t} seconds
`;
};
benchmarkButtonB.onclick = () => {
const t = benchmark(() => {
const len = Object.keys(obj).length;
});
benchmarkResultsB.innerHTML = `
${iterationsStr} iterations: ${t} seconds
`;
};
function benchmark(f) {
let t = performance.now();
for (let i = 0; i < iterations; i++) {
f();
}
return roundFloat((performance.now() - t) / 1000, 3);
}
function roundFloat(input, places) {
// see "Solution 2" in the StackOverflow answer
// from https://stackoverflow.com/a/48764436/3163495
const p = Math.pow(10, places || 0);
const n = input * p * (1 + Number.EPSILON);
return Math.round(n) / p;
}
function addCommas(input) {
let parts = input.toString().split('.');
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return parts.join('.');
}