Polyfill: filter()

Easy Important

Prompt

Imagine the JavaScript array method .filter() does not exist. Your task is to develop a polyfill for it, a function that behaves like .filter(), taking an array and a callback function as parameters. Program your solution in JavaScript and offer a concise explanation of your approach.

Playground

Hint 1

Consider what the native filter function does. It creates a new array with all elements that pass the test implemented by the provided function. Think about how you can achieve this process of selective filtering.

Hint 2

Your polyfill should add a new method to Array.prototype. How can you define a function that behaves like filter and attach it to the Array prototype?

Hint 3

The core of the filter function is to test each array element with the callback. If the element satisfies the condition in the callback, it should be included in the new array. Consider how you can iterate over the array elements and apply this logic.

Solution

Explanation

The filter method is one of the most useful tools in JavaScript's array manipulation toolkit. While map transforms each element, filter lets you selectively include or exclude elements based on a condition. This selective power makes it perfect for extracting exactly the data you need.

Let's dive into how our myFilter polyfill works:

We start by adding a method to the Array.prototype called myFilter. This function takes a callback function that will decide which elements to keep:

Array.prototype.myFilter = function (callback) {
// Implementation here
};

As with other array methods, we first check that the callback is actually a function:

if (typeof callback !== 'function') {
throw new Error(`${callback} is not a function`);
}

Next, we create a new array that will hold our filtered results:

let filteredArray = [];

Like map, the filter method doesn't change the original array - it creates a new one. But unlike map, the new array might not have the same length as the original.

We then iterate through each element in the array:

for (const element of this) {
if (callback(element)) {
filteredArray.push(element);
}
}

This is where the filtering magic happens. For each element, we call the callback function. This callback should return a boolean value - true if the element should be included in the result, or false if it should be excluded. Only elements that return true are added to our new array.

Finally, we return the filtered array:

return filteredArray;

The real power of filter comes from its ability to simplify complex data sets. Imagine you have an array of hundreds of user objects, but you only want to work with users who are active or who meet certain criteria. Rather than writing complex conditional logic throughout your code, you can use filter once to create a focused subset of data.

Here are some common scenarios where filter shines:

  1. Removing invalid data - Excluding null, undefined, or invalid entries
  2. Finding matching items - Creating a subset of items that match certain criteria
  3. Separating data - Dividing data into different groups based on properties
  4. Form validation - Identifying form fields with errors
  5. Search functionality - Finding items that match search terms

What makes filter special is that it preserves the original elements exactly as they are - unlike map, which transforms them. The elements in your filtered array are the same objects or values as in the original array, just fewer of them.

Common Pitfalls

  • Forgetting That Filter Returns a New Array: The original array remains unchanged. A common mistake is expecting the original array to be modified.

  • Returning Truthy/Falsy Values Instead of Booleans: While filter works with any truthy/falsy return value, for clarity it's best practice to explicitly return true or false from your callback.

  • Complex Filter Conditions: If your filter callback gets too complex, consider breaking it into a named function for better readability.

  • Side Effects in the Callback: The filter callback should be a pure function focused only on determining whether to include an element, not changing data or performing side effects.

00:00