Lightweight, modern utility library for node and browser
- Easy to use
- Lightweight (~7.5kb minified, ~2.5kb gzip)
- Node and browser support
- Native esm and cjs support
- Treeshakeable by default
- Support for all iterable types
- Support for async iterables and async iterator functions
- Support for quickjs
- 0 dependencies
I wanted a lighter weight, modern utility library. I had written a bunch of methods over the years that I use between projects as needed, so I decided to normalize them, add a type system, and consolidate them into this package. I also wanted to be able to add different methods for environments like node or browser, not have to use polyfills, and support async iteration.
Add lo as a dependency for your app and install via npm
npm install lo@github:danmasta/lo --save
Install a specific version
npm install lo@github:danmasta/lo#v0.0.1 --save
Import or require the package in your app
import lo from 'lo';
Import specific functions only
import { each, isFunction } from 'lo';
This package exports a browser version which excludes functions that depend on node specific apis and includes some browser specific types. If you use a bundler it should automatically be able to resolve the browser entry point. If you want to explicity import it you can do that too:
import lo from 'lo/browser';
This package is different from other utility libraries in that it defines collection types for iteration. By default, if it is not a collection type, it is iterated as a whole object.
The current collection types are defined as:
Array
Map
Set
TypedArray
Array Iterator
String Iterator
Map Iterator
Set Iterator
Generator
AsyncGenerator
Iterator
AsyncIterator
Buffer
NodeList
What is not a collection type:
Boolean
Number
BigInt
String
Symbol
Function
Object
ArrayBuffer
DataView
Stream
- ...other
Object
types such asRegExp
,Date
,Promise
,Error
, etc
When using iterator functions like each
, map
, tap
, some
, every
, filter
, remove
, and iterate
the default mode is to iterate as a collection. This means they will iterate on whole objects only, and not on the properties of a single object. For iterating the properties of a single object you can use the functions forIn
and forOwn
.
This means if you pass a single object instead of a collection type it will treat the object as a one-object collection and iterate one time:
import { each } from 'lo';
let obj = { 1: true, 2: false };
each(obj, (val, key) => {
console.log(key, val);
});
// 0 { 1: true, 2: false }
Each iterator function has the following signature:
method(iterable, iteratorFn, collection?)
Where collection
is true
by default. If you want to use an iterator method to iterate the properties of a single object you can set the collection
argument to false
:
import { each } from 'lo';
let obj = { 1: true, 2: false };
each(obj, (val, key) => {
console.log(key, val);
}, false);
// 1 true
// 2 false
Note: All iterator functions work for any iterable type including Array
, Map
, Set
, Iterator
, and Generator
.
Methods to iterate the properties of individual objects and iterables: forIn
, and forOwn
.
Methods for iterating collections of objects: each
, map
, tap
, some
, every
, filter
, remove
, and iterate
.
Using the forEach
method works slightly different from other iterator methods. It defers to the object's own forEach
method if it exists. This means it works for things like Array
, Map
, Set
, Iterator
, and Buffer
, but will also work for Streams
.
All iteration methods can be stopped early by returning the BREAK
symbol:
import { map, BREAK } from 'lo';
let arr = [1, 2, 3, 4];
map(arr, val => {
return val % 3 === 0 ? BREAK : val*2;
});
// [2, 4]
A common task during iteration is checking for nil
(null
or undefined
) values. This package has support for filtering nil
values for various iteration methods. It will ignore nil
values before the iterator function is called. It will also filter return values for functions that return, such as map
, some
, and, every
. To use, just append NotNil
to the function name:
import { mapNotNil as map } from 'lo';
let arr = [1, undefined, 2, 3, null];
map(arr, val => {
return val % 3 === 0 ? undefined : val;
});
// [1, 2]
Methods that support nil
filtering include: each
, map
, tap
, some
, every
, filter
, remove
Every iteration method also supports both async iterables and async iterator functions. You don't need to do anything special, just use them as normal:
import { map } from 'lo';
async function* list () {
yield 1;
yield 2;
yield 3;
}
await map(list(), async val => {
return await val*2;
});
// [2, 4, 6]
A list of methods and some documentation can be found here
Tests are currently run using mocha and chai. To execute tests run make test
. To generate unit test coverage reports run make coverage
If you have any questions feel free to get in touch