diff --git a/README.md b/decorator/README.md similarity index 100% rename from README.md rename to decorator/README.md diff --git a/src/index.js b/decorator/src/index-01.js similarity index 87% rename from src/index.js rename to decorator/src/index-01.js index ee9b637..426dfcc 100644 --- a/src/index.js +++ b/decorator/src/index-01.js @@ -1,6 +1,6 @@ function slow(x) { - // there can be a heavy CPU-intensive job here console.info(`Called with ${x}`); + for (let i = 1; i < 1000000000; i++) {}; // CPU-intensive "job" return x; } @@ -27,4 +27,4 @@ console.info( slow(1) ); // slow(1) is cached and the result returned console.info( "Again: " + slow(1) ); // slow(1) result returned from cache console.info( slow(2) ); // slow(2) is cached and the result returned -console.info( "Again: " + slow(2) ); \ No newline at end of file +console.info( "Again: " + slow(2) ); diff --git a/decorator/src/index-02.js b/decorator/src/index-02.js new file mode 100644 index 0000000..dd2fbe3 --- /dev/null +++ b/decorator/src/index-02.js @@ -0,0 +1,31 @@ +let worker = { + someMethod() { + return 1; + }, + + slow(x) { + console.info("Called with " + x); + for (let i = 1; i < 1000000000; i++) {}; // CPU-intensive "job" + return x * this.someMethod(); // (*) + } +}; + +function cachingDecorator(func) { + let cache = new Map(); + return function(x) { + if (cache.has(x)) { + console.info("Cache hit!"); + return cache.get(x); + } + console.info("Cache miss!"); + // let result = func(x); // What's `this`? + let result = func.call(this, x); // `this` is passed correctly now + cache.set(x, result); + return result; + }; +} + +worker.slow = cachingDecorator(worker.slow); // now make it caching + +console.info( worker.slow(2) ); // works +console.info( "Again: " + worker.slow(2) ); // works, doesn't call the original (cached) diff --git a/decorator/src/index-03.js b/decorator/src/index-03.js new file mode 100644 index 0000000..69c5c3e --- /dev/null +++ b/decorator/src/index-03.js @@ -0,0 +1,34 @@ +let worker = { + slow(min, max) { + console.info(`Called with ${min},${max}`); + for (let i = 0; i < 1000000000; i++) {}; + return min + max; + } +}; + +function cachingDecorator(func, hash) { + let cache = new Map(); + return function() { + let key = hash(arguments); // (*) + if (cache.has(key)) { + console.info("Cache hit!"); + return cache.get(key); + } + + let result = func.call(this, ...arguments); // (**) + + cache.set(key, result); + console.info("Cache miss!"); + return result; + }; +} + +function hash(args) { + return args[0] + ',' + args[1]; +} + +worker.slow = cachingDecorator(worker.slow, hash); + +console.info( worker.slow(3, 5) ); // works +console.info( worker.slow(8, 7, 9) ); // works, ignoring extra argument +console.info( "Again " + worker.slow(3, 5) ); // same (cached)