在javascript中缓存闭包

时间:2011-06-25 09:14:20

标签: javascript browser node.js closures

在阅读问题的答案后:JavaScript inner-functions and Performance

我想知道在这种情况下是否可以以某种方式缓存内部函数(doSomethingCool):

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

3 个答案:

答案 0 :(得分:4)

你无法真正缓存闭包。如果这样做,那么它仍然会关闭它首次定义的函数的变量。

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

var newUser = (function() {
    var doSomethingCool;

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

    return newUser;
}());

我们第一次调用newUser时,将创建doSomethingCool函数。这是输出:

> 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;
}());

答案 1 :(得分:1)

使用闭包的目的是保留创建它的上下文。如果你“缓存”你的闭包,对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();

使用该代码,在User的原型上只创建了一个doSomethingCool函数,但它的行为会根据它的调用方式而改变。

如果您只是想创建一个仅在newUser内使用但没有利用闭包属性的实用程序函数,那么移动函数并接受用户可能会更好论点。也就是说,我非常怀疑它会以任何明显的方式影响你的表现。

答案 2 :(得分:0)

这是一个使用基本闭包和函数的简单缓存。它的驱逐策略是一种基于概率的策略,但是您可以轻松地将其修改为基于时间的策略。与其他解决方案不同,该解决方案不需要您调用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"))

执行1:

called with param christian
0.7340898868131249
0.7340898868131249
called with param bongiorno
0.3708897404988516

执行n:

0.6886668809537186
called with param christian
0.5845787434396792
called with param bongiorno
0.2618603367580965