Removing unneeded objects from an array before rendering I'm making a function that adds a new object to an array and removes the oldest if it has reached a specific length. Click the button in the example below. All objects are drawn until its array reaches a length of 5 when the oldest is removed.
Is there a better, more processor and memory efficient way to do this instead of needlessly throwing the oldest entry at the garbage collector?


let c = document.getElementById("context");
let ctx = c.getContext("2d");
let particles = [];

function addParticle() {
  particles.push({
    x: Math.random() * 800,
    y: Math.random() * 500,
    width: Math.random() * 100 + 50,
    height: Math.random() * 100 + 50,
    color: '#' + Math.floor(Math.random() * 16777215).toString(16)
  });

  if (particles.length &gt; 5) particles.shift();

  draw();
}

function draw() {
  ctx.clearRect(0, 0, 800, 500);

  for (let i = 0; i &lt; particles.length; i++) {
    ctx.fillStyle = particles[i].color;
    ctx.fillRect(particles[i].x, particles[i].y, particles[i].width, particles[i].height);
  }
}
&lt;button onclick="addParticle();"&gt;Add&lt;/button&gt;
&lt;canvas id="context" width="800" height="500"&gt;&lt;/canvas&gt;
I think the current code is just fine from an efficiency standpoint. The overhead of a single small object is essentially nothing. Even if 1000 such objects were created and then got GC'd every time the button was clicked, on any remotely modern device, the performance impact would almost certainly be imperceptible.
If you really wanted to be more efficient, it might be very slightly more efficient to use a rotating modulo index that gets used to assign the new object instead of re-shuffling the array indicies with unshift, but with only 5 elements in the array, it's not something worth worrying about. Better to worry about performance tweaks only if

The improvement is easy to implement and doesn't make the code harder to read, or
You've tested the script on a low-end device and know that something isn't running as fast as it should - in which case you should run a check to see what section(s) of the code are causing the bottleneck(s), and then work on improving only those bottlenecks.

IMO, anything else is premature optimization - your efforts are better spent elsewhere, such as making the code clean and readable, which usually matters far more than performance.
And there are a number of improvements you could make on the code quality front:
Use const by default - only use let when you must reassign the variable name. Using const makes the code more readable when one can identify at a glance that something isn't going to be reassigned.
Avoid inline handlers - they have a whole bunch of problems, including a demented scope chain which virtually requires global pollution, mixing page content with presentation, and ugly escaping issues. When you have an event listener you want to attach to an element, better to use addEventListener.
Abstract iteration When iterating, unless you actually need to work with the index, it's more abstract and more readable to work with the element being iterated over directly instead. For example, rather than particles[i].width, it'd be nicer to use particle.width, or even just width extracted from the particle. You can do this by invoking Array#forEach or the array's iterator.
ID You have &lt;canvas id=&quot;context&quot; width=&quot;800&quot; height=&quot;500&quot;&gt;&lt;/canvas&gt;. But the canvas is not the 2d context - giving the element an ID of context is somewhat misleading. Also, IDs create global variables by default, unfortunately, which can sometimes lead to hard-to-understand bugs. You can select the canvas with querySelector('canvas') instead. (If you had a larger page and collisions were possible, you could give the element unique classes instead; classes do not create global identifiers.)


const button = document.querySelector('button');
button.addEventListener('click', addParticle);

const ctx = document.querySelector('canvas').getContext("2d");
const particles = [];

function addParticle() {
  particles.push({
    x: Math.random() * 800,
    y: Math.random() * 500,
    width: Math.random() * 100 + 50,
    height: Math.random() * 100 + 50,
    color: '#' + Math.floor(Math.random() * 16777215).toString(16)
  });

  if (particles.length &gt; 5) particles.shift();

  draw();
}

function draw() {
  ctx.clearRect(0, 0, 800, 500);
  particles.forEach(({ color, x, y, width, height }) =&gt; {
    ctx.fillStyle = color;
    ctx.fillRect(x, y, width, height);
  });
}
&lt;button&gt;Add&lt;/button&gt;
&lt;canvas width="800" height="500"&gt;&lt;/canvas&gt;