簡體   English   中英

在 javascript 中緩存一個閉包

[英]Caching a closure in javascript

閱讀問題的答案后: JavaScript 內部函數和性能

我想知道在這種情況下是否可以緩存內部函數(doSomethingCool):

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 ,會創建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;
}());

使用閉包的目的是保留創建它的上下文。 如果您“緩存”您的閉包,則對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但不利用閉包屬性的實用程序函數,則最好移動該函數並接受用戶作為參數。 也就是說,我非常懷疑把它留在那里會以任何明顯的方式影響你的表現。

這是一個使用基本閉包和函數的簡單緩存。 它的驅逐策略是一種基於概率的策略,但您可以輕松地將其修改為基於時間的策略。 與其他一些解決方案不同,這個解決方案不需要你調用 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM