The upside and downside of lodash
Tags: functional, javascript, webdev, programming
Published: 2021-10-03 15:49:17

Lodash is a modern javaScript utility library that delivers modularity, performance and other task.

#### Upside
Lodash provides tools for making code cleaner and more functional. It supports modern browsing environments and helps in building modular applications. It makes working with arrays, numbers, objects and strings more easier. Lodash is also excellent for iterating arays, objects and strings as well as manipulating and testing values. Let us take a look at some lodash functions and how they improve functionality. We are going to compare them to the vanilla javaScript equivalent.
 The aim is to understand how this functionalities are achieved under the hood.

#### sortBy
It creates an array of elements sorted in ascending order by the results of running each element in a collection through each iteratee. This method performs a stable sort. It also preserves the original sort order of equal elements. the iteratees are invoked with a single argument: (value). It returns the new sorted array.

##### Lodash
First we import the function from lodash

```
 import {sortBy} from 'lodash';
```

Then we create an array of users

```
const users = [
  { 'user': 'fred', 'age': 48 },
  { 'user': 'brand', 'age': 36 },
  { 'user': 'fred', 'age': 40 },
  { 'user': 'brand', 'age': 34 }
];
```

We now apply the the lodash sortBy function to the array

```
_.sortBy(users, function(o) { return o.user; });
// => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]

_.sortBy(users, ['user', 'age']);
// => objects for [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]]

_.sortBy(users, 'user', function(o) {
  return Math.floor(o.age / 10);
});
// => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
```
We get the above result.

##### Vanilla javaScript

```
const users = [
  { 'user': 'fred', 'age': 48 },
  { 'user': 'brand', 'age': 36 },
  { 'user': 'fred', 'age': 40 },
  { 'user': 'brand', 'age': 34 }
];
```

```
const sortBy = (key) => {
  return (a, b) => (a[key] > b[key]) ? 1
   : ((b[key] > a[key]) ? -1 : 0);
};
```

We now use the native sort to modify the array in place. We also use the `concat()` method to copy the array before sorting.

```
users.concat().sort(sortBy('user'));
// => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]];

users.concat().sort(sortBy('user', 'age'));
// => objects for [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]];
```

#### Curry
Creates a function that accepts arguments of `func` and either invokes `func` returning its result if at least the number of arguments is specified or returns a `function` that accepts the remaining `func` arguments. The arguments of the `func` maybe specified if `func.length` is not sufficient

#####Lodash

```
import { curry } from 'lodash';
const abc = (a, b, c) => [a, b, c];
const curried = curry(abc);
curried(3)(4)(5);
```

For the code solution above check
https://dev.to/mcube25/javascript-advanced-functions-for-dummies-4i6g: 
[check for more info on currying]
(https://dev.to/mcube25/javascript-advanced-functions-for-dummies-4i6g)

##### Vanilla javaScript
First we define the number of expected arguments

```
const curry = func => {
  const expectedArgs = func.length;
  const curried = (...args) => {

  }
}
```

If enough arguments have been passed, we return the result of the function execution or else we continue adding to the list

```
const curry = func => {
  const expectedArgs = func.length;
  const curried = (...args) => {
    return args.length >= expectedArgs
      ? func(...args)
      : (...args2) => curried(...args.concat(args2))
  }
  return curried
}
```

For the code solution above check
https://dev.to/mcube25/javascript-advanced-functions-for-dummies-4i6g: 
[check for more info on currying]
(https://dev.to/mcube25/javascript-advanced-functions-for-dummies-4i6g)

#### Chunk
It creates an array of elements split into groups the length of the size. The size will be the second argument provided to the function.

##### Lodash
Import chunk from lodash

```
import { chunk } from 'lodash';
chunk(['boy', 'girl', 'brother', 'sister', 'uncle', 'aunt'], 2);
//=>[['boy', 'girl'], ['brother', 'sister'], [uncle', 'aunt']];
```

If collection can’t be split evenly, the final chunk will be the remaining elements.
Example

```
chunk(['boy', 'girl', 'brother', 'sister', 'uncle', 'aunt', 'father'], 2);
//=>[['boy', 'girl'], ['brother', 'sister'], [uncle', 'aunt'], [father]];
```

##### Vanilla javaScript
Using plain javaScript the lodash example can be written as 

```
const chunk = (arr, arrSize, cache = []) => {
  const temp = [...arr]
  if (arrSize <= 0) { return cache }
  while (temp.length) {
    cache.push(temp.splice(0, arrSize))
    return cache
  }
}
chunk(['boy', 'girl', 'brother', 'sister', 'uncle', 'aunt'], 2);
//=>[['boy', 'girl'], ['brother', 'sister'], [uncle', 'aunt']];
```

#### pullAt
This function removes elements from an array corresponding to indexes and returns an array of removed elements. This method mutates the array

##### Lodash

```
import { pullAt } from 'lodash';
const array = ['2', '3', '4', '5', '6'];
pullAt(array, [2, 4]);
//=>[4, 6]
```

##### Vanilla javaScript

```
const pullAt = (arr, idxs) => {
  idxs.reverse().map(
    idx => arr.splice(idx, 1)[0]
  ).reverse()
};

pullAt(array, [2, 4]);
//=>[4, 6]
```

#### Remove
This function removes all elements from an array that affirms or denies the subject in the proposition logic. It returns truthy for the array. It also returns an array of the removed elements. It is invoked with three arguments which are `(value, index, array)`. It mutates the array

##### Lodash

```
import { remove } from 'lodash';
const array = [1, 2, 3, 4, 5];
const even = remove(array, n => {
  return n % 2 === 0
});

// the array //=>[1, 3, 5];
// even //=> [2, 4];
```

##### Vanilla javaScript

```
const remove = (array, ix) => {
  const toRemove = [];
  const result = array.filter((item, i) =>
    ix(item) && toRemove.push(i)
  )
};
```

In order to not mutate the original array until the very end, we want to cache the indexes while preparing the result to return in the code above. Just before returning, we can remove the items making sure to start from the higher indexes to prevent them shifting at each removal.

```
const remove = (array, ix) => {
  const toRemove = [];
  const result = array.filter((item, i) =>
    ix(item) && toRemove.push(i)
  )
  toRemove.reverse().forEach(i => array.splice(i, 1))
  return result
}
const array = [1, 2, 3, 4, 5];
const even = remove(array, n => {
  return n % 2 === 0
});

// the array //=>[1, 3, 5];
// even //=> [2, 4];
```

####  Reduce
This function reduces a collection to a value that is the accumulated result of running each element in the collection through an iteratee. Each successive invocation is supplied the return value of the previous. If the accumulator is not given, then the first element of the collection is used as the initial value. The iteratee is invoked with four arguments: `(accumulator, value, index, collection)`

##### Lodash

```
import { reduce } from 'lodash';

reduce([3, 4], (sum, n) => sum + n, 0);
//=>7 
```

##### Vanilla javaScript

```
array = [3, 4];
array.reduce((sum, n) => sum + n, 0);
//=>7 
```

#### Before
It creates a function that invokes a `func` with the `this` binding and arguments of the created function while it is called less than `n` times. Subsequent calls to the created function returns the result of the last `func` invocation

##### Lodash 

```
import { before } from 'lodash';

(t, fn) => before(t, fn);
```

##### Vanilla javaScript

```
const before = (t, fn) => {
  let counter = 0;
  let res;
  return (...args) => {
    counter++;
    if (counter <= t) {
      res = fn(...args);
      return res
    } else {
      return res
    }
  }
}
```

#### Downside
As can be seen, the amount of code written when using lodash is minimal compared to using plain javaScript. But the downside of using lodash in an application is that it increases the size of the application which in turn affects the performance of such applications.