← Daily Logs
GreatFrontEnd

Implement Array.prototype.filter

EasyJul 1, 2026arraypolyfillprototype

Reimplement filter as `myFilter` — easy until you remember the two things the spec cares about that a naive loop misses: sparse-array holes and the full `(value, index, array)` callback signature plus `thisArg`.

The problem

Add `Array.prototype.myFilter(callbackFn, thisArg)` that returns a new array of the elements for which `callbackFn` returns truthy. Naming it `myFilter` keeps the real `filter` intact for the autograder.

Two spec details do the real work here. Holes in a sparse array like `[1, , 3]` must be skipped entirely, not passed to the callback. And the callback receives `(value, index, array)`, with an optional `thisArg` that sets `this` inside it.

The approach

Use a classic indexed `for` loop, not `for...of`. That choice is the crux: `for...of` walks holes and hands you `undefined` for them, which is exactly what the spec says *not* to do. A counting loop lets me test each index explicitly instead.

Guard every index with `i in this` — that's the idiomatic hole check, true only for indices that actually exist, so gaps are skipped. For the survivors I call `callbackFn.call(thisArg, this[i], i, this)`, which both binds `thisArg` and passes the full `(value, index, array)` triple the spec promises. Truthy results get pushed onto the result array.

The solution

js
/**
 * @template T
 * @param {(value: T, index: number, array: Array<T>) => boolean} callbackFn
 * @param {unknown} [thisArg]
 * @returns {Array<T>}
 */
Array.prototype.myFilter = function (callbackFn, thisArg) {
  const result = [];
  for (let i = 0; i < this.length; i++) {
    if (i in this && callbackFn.call(thisArg, this[i], i, this)) {
      result.push(this[i]);
    }
  }
  return result;
};

Time O(n)Space O(n)

All entries