开发者

Caching a closure in javascript

开发者 https://www.devze.com 2023-03-15 03:41 出处:网络
After reading the answer for the question: JavaScript inner-functions and Performance I wonder if it somehow possible t开发者_如何学Pythono cache the inner function(doSomethingCool) in this case:

After reading the answer for the question: JavaScript inner-functions and Performance

I wonder if it somehow possible t开发者_如何学Pythono cache the inner function(doSomethingCool) in this case:

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


You cannot really cache a closure. If you do, then it still closes over the variables of the function it was first defined.

For example, you might consider doing this, which might look ok at a first glance:

var newUser = (function() {
    var doSomethingCool;

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

    return newUser;
}());

The first time we call newUser, the doSomethingCool function will be created. This is the output:

> newUser('foo')
  foo

When we call the function a second time, the closure is reused. This is the output:

> newUser('bar')
  foo

Why? Because the closure only closes of the variables of the function invocation it was defined in.

If you really want to "cache" the function, you have to parameterize it:

var newUser = (function() {
    var doSomethingCool;

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

    return newUser;
}());

But I would not call this a closure. Technically it is a closure, but you don't make use of this property.

And actually, it is much easier then to write it like this:

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

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

    return newUser;
}());


The point of using a closure is to preserve the context in which it was created. If you "cache" your closure the reference to user will always be the same, defeating the purpose. What you probably want is something like:

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

With that code, only one doSomethingCool function is created on the prototype of User, but it's behavior changes based on how it is called.

If you are just looking to make a utility function that's only used within newUser but doesn't take advantage of the properties of closures, you'd probably be better off moving the function and accepting the user as an argument. That said, I highly doubt leaving it there will impact your performance in any noticeable way.


Here is a dead simple cache using a basic closure and function. It's eviction strategy is one based on probability but you could easily modify it to be time based. Unlike some of the other solutions, this one doesn't require you to call new and delegates to the function passed in. It also uses an object for it's cache

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

execution 1:

called with param christian
0.7340898868131249
0.7340898868131249
called with param bongiorno
0.3708897404988516

execution n:

0.6886668809537186
called with param christian
0.5845787434396792
called with param bongiorno
0.2618603367580965
0

精彩评论

暂无评论...
验证码 换一张
取 消