70

I recently starting to drop underscore/lodash overuse on (some of) my projects and realize that there's no full support of find method in browsers. What's the difference between ES6 method find and using .shift() over filter results

var user = users.find(function() { ... } );

or

var user = users.filter(function() { ... } ).shift();

I imagine there's obvious optimization over "find" method (stop iterating on fist match), but can I get unexpected results using second approach? Should I use the polyfill instead? Why?

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
neiker
  • 8,887
  • 4
  • 29
  • 32

2 Answers2

132

Apart from the obvious (and noticeable) overhead, yes, the results might vary. filter runs till the end of the array, and invokes its callback on every item; in contrast to find which stops after having found one. When the callback throws an exception on one of these additionally iterated elements, the outcome is different.
I don't see any good reason not to use find.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 11
    IE doesn't support 'find'. – hanesjw Apr 10 '17 at 18:02
  • 30
    @hanesjw That's no reason not to use `find`, only a reason to install the [polyfill](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find#Polyfill) – Bergi Apr 10 '17 at 18:47
  • 82
    It's the reason not to use IE. – Sang Dang Mar 07 '18 at 11:15
  • 28
    note also that `filter` returns an `array` , while `find` return an `object` – Bourbia Brahim Jan 16 '19 at 23:33
  • @Bergi Accroding th [**MDN Docs**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find) `.find()` also invokes callback on every item as well till the end of index. Might've missed something? – ambianBeing Sep 04 '19 at 09:34
  • 1
    @ambianBeing "*until it finds one where `callback` returns `true`*". Or the end of the array, when it doesn't find such an item. – Bergi Sep 04 '19 at 13:28
  • typescript cannot infer types when you use `arr.find`. But it can infer the type when you use `arr.filter()[0]` – Cüneyt Aliustaoğlu Jun 11 '20 at 22:57
  • @CüneytAliustaoğlu `find` works [just fine in TypeScript](https://github.com/microsoft/TypeScript/blob/master/lib/lib.es2015.core.d.ts#L31-L32) and can also infer the result type. You might want to [ask a separate question](https://stackoverflow.com/questions/ask) if it doesn't work for you, please include your ts config. – Bergi Jun 12 '20 at 07:25
  • @Bergi I didn't say it doesn't work with TypeScript. Of course it does however TypeScript cannot "infer" the type with find. – Cüneyt Aliustaoğlu Jun 17 '20 at 04:31
  • @CüneytAliustaoğlu I'm saying that the *type inference* works fine for `find` in exactly the same way as for `filter` - see the example playground I linked – Bergi Jun 17 '20 at 07:45
24

Use a polyfill; users.filter(function() { ... } ).shift(); is throwing cycles away while triggering unnecessary garbage collection.

  • filter scans the entire array and creates another array
  • shift now has to change all the indexes on the temp array

A slightly less wasteful pattern would be to use users.filter(function() { ... } )[0]

Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • The slightly less wasteful pattern is going to be painful if the array can be empty. – Marc Dec 18 '19 at 10:27
  • 3
    @JackBlack You should be more descriptive. How is it going to be a pain? If `users` is empty in the example above, you will get `undefined`, which seems OK? – Ruan Mendes Dec 18 '19 at 15:13
  • You won't be able to access the first item in the array via [0] if there are no items, aka array is empty. – Marc Dec 23 '19 at 13:38
  • 1
    @JackBlack That doesn't make sense, yes, you get undefined, but no errors. It means your filter returned no results and is a fine result. – Ruan Mendes Dec 23 '19 at 16:24