UNPKG

6.39 kBMarkdownView Raw
1# memoizeOne
2
3A memoization library which only remembers the latest invocation
4
5[![Build Status](https://travis-ci.org/alexreardon/memoize-one.svg?branch=master)](https://travis-ci.org/alexreardon/memoize-one) [![codecov](https://codecov.io/gh/alexreardon/memoize-one/branch/master/graph/badge.svg)](https://codecov.io/gh/alexreardon/memoize-one) [![dependencies](https://david-dm.org/alexreardon/memoize-one.svg)](https://david-dm.org/alexreardon/memoize-one) [![SemVer](https://img.shields.io/badge/SemVer-2.0.0-brightgreen.svg)](http://semver.org/spec/v2.0.0.html)
6
7## Rationale
8
9Cache invalidation is hard:
10
11> There are only two hard things in Computer Science: cache invalidation and naming things.
12>
13> *Phil Karlton*
14
15So keep things simple and just use a cache size of one.
16
17Unlike other memoization libraries, `memoizeOne` only remembers the latest arguments and result. No need to worry about cache busting mechanisms such as `maxAge`, `maxSize`, `exlusions` and so on which can be prone to memory leaks. `memoizeOne` simply remembers the last arguments, and if the function is next called with the same arguments then it returns the previous result.
18
19## Usage
20
21### Standard usage
22
23```js
24import memoizeOne from 'memoize-one';
25
26const add = (a, b) => a + b;
27const memoizedAdd = memoizeOne(add);
28
29memoizedAdd(1, 2); // 3
30
31memoizedAdd(1, 2); // 3
32// Add function is not executed: previous result is returned
33
34memoizedAdd(2, 3); // 5
35// Add function is called to get new value
36
37memoizedAdd(2, 3); // 5
38// Add function is not executed: previous result is returned
39
40memoizedAdd(1, 2); // 3
41// Add function is called to get new value.
42// While this was previously cached,
43// it is not the latest so the cached result is lost
44```
45[Play with this example](http://www.webpackbin.com/NkCiYkz_M)
46
47### Custom equality function
48You can also pass in a custom function for checking the equality of two items.
49
50```js
51import memoizeOne from 'memoize-one';
52import deepEqual from 'lodash.isEqual';
53
54const identity = x => x;
55
56const defaultMemoization = memoizeOne(identity);
57const customMemoization = memoizeOne(identity, deepEqual);
58
59const result1 = defaultMemoization({foo: 'bar'});
60const result2 = defaultMemoization({foo: 'bar'});
61
62result1 === result2 // false - difference reference
63
64const result3 = customMemoization({foo: 'bar'});
65const result4 = customMemoization({foo: 'bar'});
66
67result3 === result4 // true - arguments are deep equal
68```
69[Play with this example](http://www.webpackbin.com/NJW-tJMdf)
70
71#### Type signature
72Here is the expected [flow](http://flowtype.org) type signature for a custom equality function:
73
74```js
75type EqualityFn = (a: any, b: any) => boolean;
76```
77
78## Installation
79
80```bash
81# yarn
82yarn add memoize-one
83
84# npm
85npm install memoize-one --save
86```
87
88## Module usage
89
90### ES6 module
91
92```js
93import memoizeOne from 'memoize-one';
94```
95
96### CommonJS
97
98If you are in a CommonJS environment (eg [Node](https://nodejs.org)), then **you will need add `.default` to your import**:
99
100```js
101const memoizeOne = require('memoize-one').default;
102```
103
104## `this`
105
106### memoizeOne correctly respects `this` control
107
108This library takes special care to maintain, and allow control over the the `this` context for **both** the original function being memoized as well as the returned memoized function. Both the original function and the memoized function's `this` context respect [all the `this` controlling techniques](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md):
109
110- new bindings (`new`)
111- explicit binding (`call`, `apply`, `bind`);
112- implicit binding (call site: `obj.foo()`);
113- default binding (`window` or `undefined` in `strict mode`);
114- fat arrow binding (binding to lexical `this`)
115- ignored this (pass `null` as `this` to explicit binding)
116
117### Changes to `this` is considered an argument change
118
119Changes to the running context (`this`) of a function can result in the function returning a different value event though its arguments have stayed the same:
120
121```js
122function getA() {
123 return this.a;
124}
125
126const temp1 = {
127 a: 20,
128};
129const temp2 = {
130 a: 30,
131}
132
133getA.call(temp1); // 20
134getA.call(temp2); // 30
135```
136
137Therefore, in order to prevent against unexpected results, `memoizeOne` takes into account the current execution context (`this`) of the memoized function. If `this` is different to the previous invocation then it is considered a change in argument. [further discussion](https://github.com/alexreardon/memoize-one/issues/3).
138
139Generally this will be of no impact if you are not explicity controlling the `this` context of functions you want to memoize with [explicit binding](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md#explicit-binding) or [implicit binding](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md#implicit-binding). `memoizeOne` will detect when you are manipulating `this` and will then consider the `this` context as an argument. If `this` changes, it will re-execute the original function even if the arguments have not changed.
140
141## Performance :rocket:
142
143### Tiny
144`memoizeOne` is super lightweight at `457 bytes` minified and `299 bytes` gzipped. (`1kb` = `1000 bytes`)
145
146### Extremely fast
147`memoizeOne` performs better or on par with than other popular memoization libraries for the purpose of remembering the latest invocation.
148
149**Results**
150- [simple arguments](https://www.measurethat.net/Benchmarks/ShowResult/4452)
151- [complex arguments](https://www.measurethat.net/Benchmarks/ShowResult/4488)
152
153The comparisions are not exhaustive and are primiarly to show that `memoizeOne` accomplishes remembering the latest invocation really fast. The benchmarks do not take into account the differences in feature sets, library sizes, parse time, and so on.
154
155## Code health :thumbsup:
156
157- Tested with all built in [JavaScript types](https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch1.md).
158- [100% code coverage](https://codecov.io/gh/alexreardon/memoize-one).
159- [Continuous integration](https://travis-ci.org/alexreardon/memoize-one) to run tests and type checks.
160- [`Flow` types](http://flowtype.org) for safer internal execution and external consumption. Also allows for editor autocompletion.
161- Follows [Semantic versioning (2.0)](http://semver.org/) for safer consumption.
162- No dependencies
\No newline at end of file