Table of Contents#
- What is
_.findLastIndex()? - Syntax and Parameters
- How
_.findLastIndex()Works - Use Cases and Practical Examples
- Common Patterns and Best Practices
- Performance Considerations
- Alternatives and Compatibility
- Conclusion
- References
1. What is _.findLastIndex()?#
_.findLastIndex() returns the last index in an array where a specified condition (predicate) is satisfied. Unlike _.findIndex() (which searches left-to-right), it iterates from right-to-left. This is particularly useful when you need the last occurrence of an element matching criteria without manual array reversal.
Key Characteristics:#
- Right-to-Left Iteration: Searches the array backward.
- Predicate-Based: Uses a test function to determine matches.
- Returns
-1on Failure: If no match is found, returns-1. - Underscore Dependency: Requires Underscore.js (v1.7.0+).
2. Syntax and Parameters#
_.findLastIndex(array, [predicate], [context])Parameters Explained:#
| Parameter | Type | Required? | Description |
|---|---|---|---|
array | Array | Yes | The array to search. |
predicate | Function/Object/Array/String | Yes | Test function, property matcher, or key-value pair for element matching. |
context | Object | No | The this binding for the predicate function. |
Return Value:#
- Index (integer) of the last matching element.
-1if no match is found.
3. How _.findLastIndex() Works#
Internally, _.findLastIndex() iterates from the last index to the first, applying the predicate to each element. The predicate can be:
- Function: Directly tests the element (e.g.,
elem => elem.age > 30). - Object: Matches properties (e.g.,
{ status: 'active' }). - Array: Key-value pair (e.g.,
['status', 'active']). - String: Property name shorthand (e.g.,
'active'checks truthiness).
Iteration stops when the predicate returns true, returning the current index.
4. Use Cases and Practical Examples#
Example 1: Basic Usage with Function Predicate#
const users = [
{ id: 1, role: 'admin' },
{ id: 2, role: 'editor' },
{ id: 3, role: 'admin' },
];
const lastAdminIndex = _.findLastIndex(users, user => user.role === 'admin');
console.log(lastAdminIndex); // Output: 2Example 2: Object Predicate for Property Matching#
const tasks = [
{ title: 'Task A', done: false },
{ title: 'Task B', done: true },
{ title: 'Task C', done: true },
];
const lastCompleted = _.findLastIndex(tasks, { done: true });
console.log(lastCompleted); // Output: 2Example 3: Key-Value Pair Predicate#
const posts = [
{ id: 101, tags: ['tech'] },
{ id: 102, tags: ['health'] },
{ id: 103, tags: ['tech'] },
];
const lastTechPostIndex = _.findLastIndex(posts, ['tags', ['tech']]);
console.log(lastTechPostIndex); // Output: 2Example 4: Edge Cases and Context Binding#
const data = [0, null, '', false, undefined];
const lastTruthyIndex = _.findLastIndex(data, Boolean);
console.log(lastTruthyIndex); // Output: -1 (all are falsy!)
// Using context binding:
const checker = { threshold: 30 };
const scores = [20, 35, 15, 40];
const lastAboveThreshold = _.findLastIndex(
scores,
function(score) { return score > this.threshold; },
checker
);
console.log(lastAboveThreshold); // Output: 35. Common Patterns and Best Practices#
Pattern 1: Finding the Last Valid Entry#
Useful when newer invalid entries (e.g., null) override earlier valid ones:
const versions = [null, 'v2.1', 'v2.0', null];
const lastValid = _.findLastIndex(versions, ver => ver !== null);
console.log(lastValid); // Output: 2Pattern 2: Combining with _.pluck for Property Extraction#
const products = [
{ id: 1, stock: 0 },
{ id: 2, stock: 15 },
{ id: 3, stock: 0 },
];
const lastInStockIndex = _.findLastIndex(products, 'stock');
// Equivalent to: _.findLastIndex(products, product => !!product.stock)
console.log(lastInStockIndex); // Output: 1Best Practices:#
- Optimize Predicates: Avoid heavy computations in predicates (callbacks run for each element).
- Handle Sparse Arrays: Missing indices are skipped efficiently.
- Check for
-1: Always validate the return value before using the index. - Prefer Functions for Complex Logic: Use function predicates for dynamic conditions.
6. Performance Considerations#
- O(n) Complexity: Worst-case iterates the entire array. Prefer for moderately sized arrays (<10K elements).
- Large Arrays: Use manual loops or WebAssembly for performance-critical tasks.
- Optimization: Short-circuiting stops iteration after the first match from the right.
7. Alternatives and Compatibility#
Native Alternative (ES2023+):#
Modern browsers support Array.prototype.findLastIndex():
[10, 20, 30].findLastIndex(x => x > 15); // Returns 2Underscore Alternatives:#
_.findIndex(): Searches left-to-right._.lastIndexOf(): For exact value matches (no predicates).
8. Conclusion#
_.findLastIndex() is a versatile tool for efficiently locating the last occurrence of an element meeting specific criteria in an array. Its predicate flexibility and right-to-left search make it invaluable for scenarios like timestamp-based lookups or validation workflows. While native alternatives exist in modern JavaScript, Underscore.js provides robust cross-browser compatibility. Use it to simplify complex search logic while keeping code declarative and clean.