JavaScript delete operator might cause some unexpected performance issues.
"You think you know JavaScript? Think again." A perpetual state of existence for all who dare to love this language.
Search for a command to run...
"You think you know JavaScript? Think again." A perpetual state of existence for all who dare to love this language.
No comments yet. Be the first to comment.
Well, not really a guide. More like engineer-approved ramblings
While working on a backend built using typescript, graphql, and mongoDB I reached a point where I needed some code coverage to continue development. Documenting test cases in graphql playground wasn't scaling anymore and I'm strictly against using Go...
This is simple guide to get started with debugging typescript node application in VS Code using the Remote Development extension. The issue with this use-case is that the application files are mounted to the container, built there and then server run...
In this article I'm going to go over the steps to set deploy a private docker image on Elastic Beanstalk using docker-compose.yml. Beanstalk deployment supports docker-compose.yml out of the box and executes it when you push a zip containing this fil...
So I was working on some benchmarking with a piece of code in JavaScript and I was scratching my head over the runtimes that I was seeing. I literally could not make sense of what was happening. And in a wild attempt at debugging, I stumbled upon a quirk that I had never known.
The v8 engine does not really like the delete operator. And using this operator on an object can have a tangible impact on the performance of your code. In my case, it was almost 3 times worse performance than if I had manually set that key to undefined or false
That said, I was able to reproduce this in Safari v18.5 as well along with all Chromium based browsers. So not really sure if this behavior is limited to the v8 engine.
Here’s a simple code I wrote based on my experience to easily benchmark the performance impact of using delete vs. manually setting the key to something else. Note that in the code example here I’m setting it to false but using undefined yields similar results.
const mapDelete = {};
const benchmarkDelete = (i = 0) => {
while (i < 25) {
if (mapDelete[i]) {
delete mapDelete[i];
} else mapDelete[i] = true;
benchmarkDelete((i += 1));
}
};
const startDelete = performance.now();
benchmarkDelete();
const endDelete = performance.now();
console.log(`Execution time delete => ${endDelete - startDelete} milliseconds`);
const mapFalse = {};
const benchmarkFalse = (i = 0) => {
while (i < 25) {
if (mapFalse[i]) {
mapFalse[i] = false;
} else mapFalse[i] = true;
benchmarkFalse((i += 1));
}
};
const startFalse = performance.now();
benchmarkFalse();
const endFalse = performance.now();
console.log(`Execution time false => ${endFalse - startFalse} milliseconds`);
I ran this code in multiple environments such as Chrome, Safari and node and the results were more or less consistent. The first method’s execution time was around 3 times slower than that of the second method.
I tested with v24.2.0 which was the latest available version at the time of writing this article.

Tested on Version 136.0.7103.114 (Official Build) (arm64)on macOS 15.5

While Chrome and Node are both using Google’s v8 engine, Safari uses Apple’s own engine called JavaScriptCore, also known as Nitro. Tested on Safari 18.5 on macOS 15.5.

I tried to find the exact reason but I couldn’t really find anything definitive or official, but I did come across a couple of other articles and posts on StackOverflow talking about this or something close to this. The logic seems to be that when you use delete the underlying JS engine stops treating it like a conventional hash map and loses some of the optimizations it has for working with them.
This post goes into a lot more details about the underlying optimizations that v8 engine does, but I think something similar applies to most other engines as well.
If you care about the runtime and performance of your code/app and heavily use delete for objects that are used as lookups with very frequent read operations, then it might just be better to use a different approach or just set that key to undefined manually.