在javascript中缓存闭包

在javascript中缓存闭包,javascript,browser,node.js,closures,Javascript,Browser,Node.js,Closures,阅读问题的答案后: 我想知道在这种情况下是否可能缓存内部函数(doSomethingTool): function newUser(user){ function doSomethingCool(){ console.log(user); } } 您无法真正缓存闭包。如果您这样做了,那么它仍然会关闭最初定义的函数的变量 例如,您可能会考虑这样做,乍一看可能看起来不错: var newUser = (function() {

阅读问题的答案后:

我想知道在这种情况下是否可能缓存内部函数(doSomethingTool):

function newUser(user){
         function doSomethingCool(){
                 console.log(user);
         } 
}
您无法真正缓存闭包。如果您这样做了,那么它仍然会关闭最初定义的函数的变量

例如,您可能会考虑这样做,乍一看可能看起来不错:

var newUser = (function() {
    var doSomethingCool;

    function newUser(user){
         doSomethingCool = doSomethingCool || function(){console.log(user);};
         doSomethingCool();
    }

    return newUser;
}());
第一次调用
newUser
,将创建
doSomethingTool
函数。这是输出:

> newUser('foo')
  foo
> newUser('bar')
  foo
当我们第二次调用函数时,闭包被重用。这是输出:

> newUser('foo')
  foo
> newUser('bar')
  foo
为什么??因为闭包只关闭函数调用中定义的变量

如果确实要“缓存”函数,则必须将其参数化:

var newUser = (function() {
    var doSomethingCool;

    function newUser(user){
         doSomethingCool = doSomethingCool || function(user){console.log(user);};
         doSomethingCool(user);
    }

    return newUser;
}());
但我不认为这是一个结束。从技术上讲,它是一个闭包,但您不使用此属性

实际上,这样写要容易得多:

var newUser = (function() {
    var doSomethingCool = function(user){...};

    function newUser(user){
         doSomethingCool(user);
    }

    return newUser;
}());

使用闭包的目的是保留创建闭包的上下文。如果“缓存”闭包,则对
user
的引用将始终是相同的,这与目的背道而驰。您可能想要的是:

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();
使用该代码,在用户原型上只创建了一个
doSomethingTool
函数,但其行为会根据调用方式发生变化


如果您只是想创建一个只在
newUser
中使用的实用函数,但不利用闭包的属性,那么最好移动该函数并接受用户作为参数。也就是说,我非常怀疑把它留在那里会以任何明显的方式影响性能。

这里是一个使用基本闭包和函数的简单缓存。它的驱逐策略是基于概率的,但是你可以很容易地修改它,使之基于时间。与其他一些解决方案不同,此解决方案不需要调用new和对传入函数的委托。它还使用对象作为缓存

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"))

执行n:

0.6886668809537186
called with param christian
0.5845787434396792
called with param bongiorno
0.2618603367580965

我不想更改NewUsers的签名/定义只是为了澄清我想缓存'DoSomethingTool'我不想更改newUser函数定义,newUser的内部impl可以是任何…@browsingLoops:我认为函数的定义就是它的实现。