A Lodash Reference But With My Preferred Methods
Tags: javascript
Published: 2020-09-07 17:35:23

In most programming languages, there is a library of utility functions that compliment the basic operations and built-in functions in those languages. Some languages even have a large and well known community-supported library of useful functions that developers use commonly. Lodash is one such library for Javascript.

Lodash's focus is on **functional programming.** Lodash takes several common operations in Javascript and makes them available in a functional programming form. The result is that code is shorter and more compact. But this is not the only functionality Lodash provides. It also has string manipulation, math, and list/array functions.

I admit I am kind of weak in functional programming so in this article I didn't cover all of the functional programming functions but I did cover the ones that resemble normal functions, in other words the ones I like, so don't mind me. 😅

Lodash was influenced by Underscore.js, which in turn was influenced by Prototype.js, both utility libraries like Lodash. Many of the Underscore.js developers are now maintaining Lodash so this library is updated more offten than Underscore. (Prototype.js is a massively used library that according to Wikipedia is used by [2.2% of all websites](https://en.wikipedia.org/wiki/Prototype_JavaScript_Framework) and provides a couple widely needed convenience functions. I might cover that library in a future post.)

## Installation

Alright so let's get to obtaining this library. It is available as both a browser script and an NPM module. The NPM module can be installed with npm or yarn in the usual way:

```sh
npm install --save lodash
```

And imported using `var _ = require('lodash');`. The browser script can be included in HTML with `<script src="lodash.js"></script>`.

That's it! Now you have the entire Lodash library at your fingertips.

Special attention however needs to be given at importing from Node. In the Node version of Lodash, you are able to import only part of the module. From their [site](https://lodash.com/), these are the different parts you can import:

```js
// Load the full build.
var _ = require('lodash');
// Load the core build.
var _ = require('lodash/core');
// Load the FP build for immutable auto-curried iteratee-first data-last methods.
var fp = require('lodash/fp');
 
// Load method categories.
var array = require('lodash/array');
var object = require('lodash/fp/object');
 
// Cherry-pick methods for smaller browserify/rollup/webpack bundles.
var at = require('lodash/at');
var curryN = require('lodash/fp/curryN');
```

## Functions

Lodash has different categories of methods and I will break them down in different sections. Obviously I won't cover all of them, only the main ones (subject to my opinion 🙂)

I assume the full Lodash library has been imported to variable `_`. The underscore is part of the reason the library is named "Lodash", because it is usually imported to this variable. Arguably the official documentation presents these function in the most accessible form but it doesn't hurt to have it in different places.

### Array Functions

`_.chunk(array, [size=1])`: Splits an array into chunks

> Creates an array of elements split into groups the length of size. If array can't be split evenly, the final chunk will be the remaining elements.

`_.compact(array)`: Remove false values from an array

> Creates an array with all falsey values removed. The values false, null, 0, "", undefined, and NaN are falsey.

`_.concat(array, [values])`: Concatenate arrays

> Creates a new array concatenating array with any additional arrays and/or values.

`_.drop(array, [n=1])`: Remove array elements from the beginning

> Creates a slice of array with n elements dropped from the beginning.

`_.dropRight(array, [n=1])`: Remove array elements from the end

> Creates a slice of array with n elements dropped from the end.

`_.flattenDeep(array)`: Flattens nested arrays

> Recursively flattens array.

`_.reverse(array)`: Reverses an array

> Reverses array so that the first element becomes the last, the second element becomes the second to last, and so on.
>
> Note: This method mutates array and is based on Array#reverse.

`_.slice(array, [start=0], [end=array.length])`: Create a slice of an array

> Creates a slice of array from start up to, but not including, end.
>
> Note: This method is used instead of Array#slice to ensure dense arrays are returned.

`_.uniq(array)`: Create a copy of arrays without duplicate values

> Creates a duplicate-free version of an array, using SameValueZero for equality comparisons, in which only the first occurrence of each element is kept. The order of result values is determined by the order they occur in the array.

`_.without(array, [values])`: Filter values out of an array

> Creates an array excluding all given values using SameValueZero for equality comparisons.

### Collection Functions

A reminder, a collection is a sequence of items, it could also be an array. Arrays guarrentee the items will be iterated in order, whereas if the collection is a set, it will be iterated in a random order.

`_.forEach(collection, [iteratee=_.identity])`: Call a function for each collection.

> Iterates over elements of collection and invokes iteratee for each element. The iteratee is invoked with three arguments: (value, index|key, collection). Iteratee functions may exit iteration early by explicitly returning false.

`_.every(collection, [predicate=_.identity])`: Tests if an expression is true for all collection elements

> Checks if predicate returns truthy for all elements of collection. Iteration is stopped once predicate returns falsey. The predicate is invoked with three arguments: (value, index|key, collection).
>
> Note: This method returns true for empty collections because everything is true of elements of empty collections.

`_.some(collection, [predicate=_.identity])`: Tests if an expression is true for any of the collection elements

> Checks if predicate returns truthy for any element of collection. Iteration is stopped once predicate returns truthy. The predicate is invoked with three arguments: (value, index|key, collection).

`_.filter(collection, [predicate=_.identity])`: Return a new collection with items not matching a *predicate* expression filtered out

> Iterates over elements of collection, returning an array of all elements predicate returns truthy for. The predicate is invoked with three arguments: (value, index|key, collection).

`_.find(collection, [predicate=_.identity], [fromIndex=0])`: Return the index of the first collection item that matches a *predicate* expression.

> Iterates over elements of collection, returning the first element predicate returns truthy for. The predicate is invoked with three arguments: (value, index|key, collection).

`_.includes(collection, value, [fromIndex=0])`: Checks if an item is in a collection.

> Checks if value is in collection. If collection is a string, it's checked for a substring of value, otherwise SameValueZero is used for equality comparisons. If fromIndex is negative, it's used as the offset from the end of collection.

`_.sample(collection)`: Get a random element from a collection

> Gets a random element from collection.

`_.sampleSize(collection, [n=1])`: Get `n` random elements from a collection

> Gets n random elements at unique keys from collection up to the size of collection.

`_.shuffle(collection)`: Returns a collection of shuffled elements in the original collection

> Creates an array of shuffled values, using a version of the Fisher-Yates shuffle.


### Math Functions

We have `add`, `ceil`, `divide`, `floor`, `max`, `mean`, `min`, `multiply`, `round`, `subtract` and `sum` functions, which do what you'd expect them to o if you are versed in mathematics. These need no introduction in my opinon.


### Date Functions

There is only one method in this category and that is `now`.

`_.now()`: Return current time in milliseconds since epoch

> Gets the timestamp of the number of milliseconds that have elapsed since the Unix epoch (1 January 1970 00:00:00 UTC).

### Functional Methods

`_.after(n, func)`: Calls `func` once the function `after` returns is called `n` or more times.

> This method creates a function that invokes func once it's called n or more times.

Example:

```js
var saves = ['profile', 'settings'];
 
var done = _.after(saves.length, function() {
  console.log('done saving!');
});
 
_.forEach(saves, function(type) {
  asyncSave({ 'type': type, 'complete': done });
});
// => Logs 'done saving!' after the two async saves have completed.
```

`_.bind(func, thisArg, [partials])`: Creates a function that is bound to an object `thisArg`. The `partials` are a list of arguments to apply to it. Some of the partials can have the placeholder value `_` (the Lodash imported var) to skip applying some arguments. You can use it to apply the arguments after a certain number while calling the `bind()`ed function with the ones you did not bind.

> Creates a function that invokes func with the this binding of thisArg and partials prepended to the arguments it receives.
>
> The _.bind.placeholder value, which defaults to _ in monolithic builds, may be used as a placeholder for partially applied arguments.
>
> Note: Unlike native Function#bind, this method doesn't set the "length" property of bound functions.

```js
function greet(greeting, punctuation) {
  return greeting + ' ' + this.user + punctuation;
}
 
var object = { 'user': 'fred' };
 
var bound = _.bind(greet, object, 'hi');
bound('!');
// => 'hi fred!'
 
// Bound with placeholders.
var bound = _.bind(greet, object, _, '!');
bound('hi');
// => 'hi fred!'
```

`_.debounce(func, [wait=0], [options={}])`: Creates a function that calls `func` and delays for `wait` milliseconds between calls.

> Creates a debounced function that delays invoking func until after wait milliseconds have elapsed since the last time the debounced function was invoked. The debounced function comes with a cancel method to cancel delayed func invocations and a flush method to immediately invoke them.

`_.delay(func, wait, [args])`: Call `func` after `wait` milliseconds.

> Invokes func after wait milliseconds. Any additional arguments are provided to func when it's invoked.

`_.memoize(func, [resolver])`: Saves the result of `func` to the cache inside the returned variable (*memoizes* the result, also known as caching it so that the result from cache is used When the returned function is called instead of invoking `func` a second time).

In Javascript you can have a function variable but having arbitrary properties with `Object` values, that's the variable returned by `memoize`.

> Creates a function that memoizes the result of func. If resolver is provided, it determines the cache key for storing the result based on the arguments provided to the memoized function. By default, the first argument provided to the memoized function is used as the map cache key. The func is invoked with the this binding of the memoized function.

`_.throttle(func, [wait=0], [options={}])`: Returns a function based on `func` that limits execution to once every `wait` milliseconds.

I wish I knew about this earlier. It would have been very helpful for my earlier [Javascript doesn't sleep](https://dev.to/zenulabidin/javascript-doesn-t-sleep-471j) post.

To my understanding, the difference between this and `debounce` is that `debounce` will queue each execution of `func` until the `wait` time has passed, so you end up with a lot of calls to `func` happening simultaneously. Whereas this function discards the call entirely if the `wait` time hasn't passed yet. There is also a helpful article that explains the difference between the two called [Debouncing and Throttling Explained Through Examples](https://css-tricks.com/debouncing-throttling-explained-examples/), so be sure to check that out as well.

## And we're done

If you see any errors in this post, please let me know so I can correct them.

---
Sources:
https://lodash.com/docs/4.17.15