Caching a closure in javascript
阅读以下问题的答案后:JavaScript内部函数和性能
我想知道在这种情况下是否可以缓存内部函数(doSomethingCool):
1 2 3 4 5 | function newUser(user){ function doSomethingCool(){ console.log(user); } } |
您无法真正缓存闭包。如果这样做,它仍然会关闭最初定义的函数的变量。
例如,您可能会考虑这样做,乍一看似乎没问题:
1 2 3 4 5 6 7 8 9 10 | var newUser = (function() { var doSomethingCool; function newUser(user){ doSomethingCool = doSomethingCool || function(){console.log(user);}; doSomethingCool(); } return newUser; }()); |
我们第一次调用
1 2 | > newUser('foo') foo |
当我们第二次调用该函数时,闭包将被重用。这是输出:
1 2 | > newUser('bar') foo |
为什么?因为闭包仅关闭函数调用的变量,所以它是在其中定义的。
如果您真的想"缓存"该功能,则必须对其进行参数化:
1 2 3 4 5 6 7 8 9 10 | var newUser = (function() { var doSomethingCool; function newUser(user){ doSomethingCool = doSomethingCool || function(user){console.log(user);}; doSomethingCool(user); } return newUser; }()); |
但是我不会称其为闭包。从技术上讲,它是一个闭包,但是您不使用此属性。
实际上,这样写起来要容易得多:
1 2 3 4 5 6 7 8 9 | var newUser = (function() { var doSomethingCool = function(user){...}; function newUser(user){ doSomethingCool(user); } return newUser; }()); |
使用闭包的目的是保留创建闭包的上下文。如果"缓存"闭包,则对
1 2 3 4 5 6 7 8 9 10 11 12 13 | function User(name) { this.name = name; } User.prototype.doSomethingCool = function() { console.log(this.name); } var userA = new User('a'); var userB = new User('b'); userA.doSomethingCool(); userB.doSomethingCool(); |
使用该代码,仅在User原型上创建了一个
如果您只是想创建仅在
这是一个使用基本闭包和函数的简单缓存。它的驱逐策略是一种基于概率的策略,但是您可以轻松地将其修改为基于时间的策略。与其他一些解决方案不同,该解决方案不需要您调用new并委托传入的函数。它还使用一个对象作为其cache
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | const cache = (f, prob) =>{ const c = {} return (args) => (Math.random() < prob && c.hasOwnProperty(args) && c[args]) || (c[args] = f(args)) }; const doThing = (param1) = cache((param1) => { console.log(`called with param ${param1}`) return Math.random() },.1) console.log(doThing("christian")) console.log(doThing("christian")) console.log(doThing("bongiorno")) |
执行1:
1 2 3 4 5 | called with param christian 0.7340898868131249 0.7340898868131249 called with param bongiorno 0.3708897404988516 |
执行n:
1 2 3 4 5 | 0.6886668809537186 called with param christian 0.5845787434396792 called with param bongiorno 0.2618603367580965 |