memoize.js (2603B)
1 /** 2 * @license Apache-2.0 3 * 4 * Copyright (c) 2018 The Stdlib Authors. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 'use strict'; 20 21 // MODULES // 22 23 var isFunction = require( '@stdlib/assert/is-function' ); 24 var setReadOnly = require( './../../define-nonenumerable-read-only-property' ); 25 var identity = require( './../../identity-function' ); 26 var hasOwnProp = require( '@stdlib/assert/has-own-property' ); 27 28 29 // MAIN // 30 31 /** 32 * Returns a memoized function. 33 * 34 * @param {Function} fcn - function to memoize 35 * @param {Function} [hashFunction] - function to map a set of arguments to a single value identifying that set 36 * @throws {TypeError} first argument must be a function 37 * @throws {TypeError} second argument must be a function 38 * @returns {Function} memoized function 39 * 40 * @example 41 * function factorial( n ) { 42 * var prod; 43 * var i; 44 * prod = 1; 45 * for ( i = n; i > 1; i-- ) { 46 * prod *= i; 47 * } 48 * return prod; 49 * } 50 * 51 * var memoized = memoize( factorial ); 52 * 53 * var v = memoized( 5 ); 54 * // returns 120 55 * 56 * v = memoized( 5 ); 57 * // returns 120 58 */ 59 function memoize( fcn, hashFunction ) { 60 var toKey; 61 var cache; 62 if ( !isFunction( fcn ) ) { 63 throw new TypeError( 'invalid argument. First argument must be a function. Value: `'+fcn+'`.' ); 64 } 65 if ( arguments.length < 2 ) { 66 toKey = identity; 67 } else { 68 toKey = hashFunction; 69 if ( !isFunction( toKey ) ) { 70 throw new TypeError( 'invalid argument. Hash function argument must be a function. Value: `' + toKey + '`.' ); 71 } 72 } 73 cache = {}; 74 setReadOnly( memoized, 'cache', cache ); 75 return memoized; 76 77 /** 78 * Memoized function. 79 * 80 * @private 81 * @param {...*} args - function arguments 82 * @returns {*} memoized function result 83 */ 84 function memoized() { 85 var args; 86 var out; 87 var key; 88 var i; 89 args = new Array( arguments.length ); 90 for ( i = 0; i < arguments.length; i++ ) { 91 args[ i ] = arguments[ i ]; 92 } 93 key = toKey( args ).toString(); 94 if ( hasOwnProp( cache, key ) ) { 95 return cache[ key ]; 96 } 97 out = fcn.apply( null, args ); 98 cache[ key ] = out; 99 return out; 100 } 101 } 102 103 104 // EXPORTS // 105 106 module.exports = memoize;