Comprehensive Implementation and Performance Analysis of Filtering Object Arrays by Any Property Value in JavaScript

Dec 01, 2025 · Programming · 12 views · 7.8

Keywords: JavaScript | array filtering | object search | ES6 | performance optimization

Abstract: This article provides an in-depth exploration of efficient techniques for filtering arrays of objects in JavaScript based on search keywords matching any property value. By analyzing multiple implementation approaches using native ES6 methods and the Lodash library, it compares code simplicity, performance characteristics, and appropriate use cases. The discussion begins with the core combination of Array.prototype.filter, Object.keys, Array.prototype.some, and String.prototype.includes, examines the JSON.stringify alternative and its potential risks, and concludes with performance optimization recommendations and practical application examples.

In modern web development, processing arrays of objects and filtering them based on dynamic search criteria is a common requirement. Users typically want to search across all properties without specifying particular attributes. This article systematically introduces several implementation methods and analyzes their advantages and limitations.

Core Implementation: ES6 Native Function Composition

The most straightforward and recommended approach combines multiple array and string methods provided by ES6. The core concept is: iterate through each object in the array and check whether any property value contains the search keyword.

function filterByValue(array, searchString) {
    const lowerSearch = searchString.toLowerCase();
    return array.filter(obj => 
        Object.keys(obj).some(key => {
            const value = obj[key];
            return typeof value === 'string' && 
                   value.toLowerCase().includes(lowerSearch);
        })
    );
}

Let's break down this implementation:

  1. array.filter(): Creates a new array with all elements that pass the test
  2. Object.keys(obj): Gets all enumerable property names of the object
  3. .some(): Tests whether at least one property satisfies the condition
  4. .toLowerCase(): Normalizes case for case-insensitive search
  5. .includes(): Checks if a string contains a substring

Example application:

const users = [
    { name: 'Paul', country: 'Canada' },
    { name: 'Lea', country: 'Italy' },
    { name: 'John', country: 'Italy' }
];

console.log(filterByValue(users, 'lea'));
// Output: [{name: 'Lea', country: 'Italy'}]

console.log(filterByValue(users, 'ita'));
// Output: [{name: 'Lea', country: 'Italy'}, {name: 'John', country: 'Italy'}]

Alternative Approach: JSON.stringify Method and Its Limitations

Another method uses JSON.stringify() to convert the entire object to a string before searching:

function filterByValueJSON(array, searchString) {
    const lowerSearch = searchString.toLowerCase();
    return array.filter(obj => 
        JSON.stringify(obj).toLowerCase().includes(lowerSearch)
    );
}

While this approach offers more concise code, it has significant drawbacks:

Lodash Library Implementation

For projects already using Lodash, similar functionality can be achieved by combining multiple Lodash functions:

import _ from 'lodash';

function filterByValueLodash(array, searchString) {
    const lowerSearch = searchString.toLowerCase();
    return _.filter(array, obj => 
        _.some(_.values(obj), value => 
            _.isString(value) && 
            _.toLower(value).includes(lowerSearch)
        )
    );
}

The Lodash version provides better type checking and error handling but adds library dependency.

Performance Optimization Considerations

In practical applications, especially when processing large arrays, performance optimization is crucial:

  1. Cache conversion results: If the search keyword remains unchanged, cache the toLowerCase() result
  2. Early exit: The .some() method stops immediately after finding the first match, which is more efficient than .filter()
  3. Type checking: Ensure search is performed only on string properties to avoid calling string methods on numbers, booleans, etc.
  4. Index optimization: For frequent search scenarios, consider building search indexes

Edge Case Handling

A robust implementation needs to consider various edge cases:

function robustFilterByValue(array, searchString) {
    if (!Array.isArray(array) || !searchString) {
        return [];
    }
    
    const lowerSearch = String(searchString).toLowerCase().trim();
    
    return array.filter(obj => {
        if (!obj || typeof obj !== 'object') return false;
        
        return Object.keys(obj).some(key => {
            const value = obj[key];
            if (value == null) return false;
            
            const stringValue = String(value);
            return stringValue.toLowerCase().includes(lowerSearch);
        });
    });
}

This enhanced version handles: empty arrays, invalid search terms, null/undefined values, non-object elements, and other edge cases.

Practical Application Scenarios

This filtering technique is widely applied in:

When selecting an implementation approach, it's necessary to balance code simplicity, performance, and maintainability based on specific requirements. For most applications, the ES6 native method combination offers the best balance.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.