mediumJS ES5#60

Array.filter manually

Prompt

Implement your own version of Array.prototype.filter as myFilter(arr, predicate). Keep elements whose predicate result is TRUTHY (not just === true), return a new array, and pass (element, index, array) to the predicate.

Solution

function myFilter(arr, predicate) {
  var result = []
  for (var i = 0; i < arr.length; i++) {
    if (predicate(arr[i], i, arr)) result.push(arr[i])
  }
  return result
}
Mentor's take

Filter is map's sibling with a different contract: instead of transforming every element, it selects a subset — output length is 0 to n, and crucially the kept elements are the same references as the input's, not copies. That identity preservation matters in practice: filtering a list of objects and then mutating one mutates the original too. A senior mentions that unprompted, because it's the bug that follows "I filtered it, so it's a new array, right?" — new array, same objects.

Two contract details the tests pin down. First, truthiness, not strict equality with true: the spec coerces the predicate's return value, which is exactly why arr.filter(Boolean) works as the idiomatic compact-the-falsy-values one-liner. Guarding with === true would break that idiom and half the predicates in real codebases. Second, the full (element, index, array) triple — index-based selection like "every other row" is a legitimate, common use.

Note what filter deliberately isn't: it can't short-circuit (that's find/some), and it always walks the whole array. Chaining filter().map() costs two passes and an intermediate array — fine almost always, worth collapsing into one reduce only when a profiler says so.

Red flag: if (predicate(arr[i]) === true). It looks defensive and is actually wrong — it silently drops every predicate that returns a truthy non-boolean, including filter(Boolean).

Say it: "Filter keeps the same element references under a truthiness test — the array is new, the objects aren't, and that distinction is where post-filter mutation bugs come from."