一个只记录最新调用的备忘录库
``` … ```
## `this` ### `memoize-one` correctly respects `this` control This 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): - new bindings (`new`) - explicit binding (`call`, `apply`, `bind`); - implicit binding (call site: `obj.foo()`); - default binding (`window` or `undefined` in `strict mode`); - fat arrow binding (binding to lexical `this`) - ignored this (pass `null` as `this` to explicit binding) ### Changes to `this` is considered an argument change Changes to the running context (`this`) of a function can result in the function returning a different value even though its arguments have stayed the same: ```js function getA() { return this.a; } const temp1 = { a: 20, }; const temp2 = { a: 30, }; getA.call(temp1); // 20 getA.call(temp2); // 30 ``` Therefore, in order to prevent against unexpected results, `memoize-one` 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). Generally 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). `memoize-One` 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. ## Clearing the memoization cache A `.clear()` property is added to memoized functions to allow you to clear it's memoization cache. This is helpful if you want to: - Release memory - Allow the result function to be called again without having to change arguments ```ts import memoizeOne from 'memoize-one'; function add(a: number, b: number): number { return a + b; } const memoizedAdd = memoizeOne(add); // first call - not memoized const first = memoizedAdd(1, 2); // second call - cache hit (result function not called) const second = memoizedAdd(1, 2); // clearing memoization cache memoizedAdd.clear(); // third call - not memoized (cache was cleared) const third = memoizedAdd(1, 2); ``` ## When your result function `throw`s > There is no caching when your result function throws If your result function `throw`s then the memoized function will also throw. The throw will not break the memoized functions existing argument cache. It means the memoized function will pretend like it was never called with arguments that made it `throw`. ``` … ``` ## Function properties Functions memoized with `memoize-one` do not preserve any properties on the function object. > This behaviour is correctly reflected in the TypeScript types ```ts import memoizeOne from 'memoize-one'; function add(a, b) { return a + b; } add.hello = 'hi'; console.log(typeof add.hello); // string const memoized = memoizeOne(add); // hello property on the `add` was not preserved console.log(typeof memoized.hello); // undefined ``` > If you feel strongly that `memoize-one` _should_ preserve function properties, please raise an issue. This decision was made in order to keep `memoize-one` as light as possible. For _now_, the `.length` property of a function is not preserved on the memoized function ```ts import memoizeOne from 'memoize-one'; function add(a, b) { return a + b; } console.log(add.length); // 2 const memoized = memoizeOne(add); console.log(memoized.length); // 0 ``` There is no (great) way to correctly set the `.length` property of the memoized function while also supporting ie11. Once we [remove ie11 support](https://github.com/alexreardon/memoize-one/issues/125) then we plan on setting the `.length` property of the memoized function to match the original function [→ discussion](https://github.com/alexreardon/memoize-one/pull/124). ## Memoized function `type` The resulting function you get back from `memoize-one` has _almost_ the same `type` as the function that you are memoizing ```ts declare type MemoizedFn any> = { clear: () => void; (this: ThisParameterType, ...args: Parameters): ReturnType; }; ``` - the same call signature as the function being memoized - a `.clear()` function property added - other function object properties on `TFunc` as not carried over You are welcome to use the `MemoizedFn` generic directly from `memoize-one` if you like: ```ts import memoize, { MemoizedFn } from 'memoize-one'; import isDeepEqual from 'lodash.isequal'; import { expectTypeOf } from 'expect-type'; // Takes any function: TFunc, and returns a Memoized function withDeepEqual any>(fn: TFunc): MemoizedFn { return memoize(fn, isDeepEqual); } function add(first: number, second: number): number { return first + second; } const memoized = withDeepEqual(add); expectTypeOf().toEqualTypeOf>(); ``` In this specific example, this type would have been correctly inferred too ```ts import memoize, { MemoizedFn } from 'memoize-one'; import isDeepEqual from 'lodash.isequal'; import { expectTypeOf } from 'expect-type'; // return type of MemoizedFn is inferred function withDeepEqual any>(fn: TFunc) { return memoize(fn, isDeepEqual); } function add(first: number, second: number): number { return first + second; } const memoized = withDeepEqual(add); // type test still passes expectTypeOf().toEqualTypeOf>(); ``` ## Performance ### Tiny `memoize-one` is super lightweight at [](https://www.npmjs.com/package/memoize-one) minified and [](https://www.npmjs.com/package/memoize-one) gzipped. (`1KB` = `1,024 Bytes`) ### Extremely fast `memoize-one` performs better or on par with than other popular memoization libraries for the purpose of remembering the latest invocation. The comparisons are not exhaustive and are primarily to show that `memoize-one` accomplishes remembering the latest invocation really fast. There is variability between runs. The benchmarks do not take into account the differences in feature sets, library sizes, parse time, and so on. Expand for resultsnode version `16.11.1` You can run this test in the repo by: 1. Add `"type": "module"` to the `package.json` (why is things so hard) 2. Run `yarn perf:library-comparison` **no arguments** | Position | Library | Operations per second | | -------- | -------------------------------------------- | --------------------- | | 1 | memoize-one | 80,112,981 | | 2 | moize | 72,885,631 | | 3 | memoizee | 35,550,009 | | 4 | m
暂无开放 Issues,或尚未同步最近议题。