Berikut adalah daripada pelaksanaan John Hann ini menarik perhatian saya Ia menggunakan kaedah yang bijak untuk menyimpan hasil panggilan kaedah.
Analisis kod:
// memoize: Kaedah umum untuk caching menggunakan memoization
// func: kaedah untuk dicache
// konteks: konteks pelaksanaan kaedah
// Nota: Kaedah mesti boleh diakses secara luaran dan parameter mestilah boleh bersiri aksara
fungsi memoize (func, konteks) {
Function memoizeArg (argPos) { //Parameter menunjukkan kedudukan parameter dalam kaedah asal
var cache = {}; //Kunci cache ini ialah parameter dan nilainya ialah hasil pelaksanaan
kembalikan fungsi () { //Kembalikan penutupan fungsi
If (argPos == 0) { //Parameter pertama, jika parameter tidak wujud dalam kekunci cache, laksanakan fungsi asal dan simpan hasil pelaksanaan
Jika (!(argumen[argPos] dalam cache)) {
cache[arguments[argPos]] = func.apply(context, arguments);
kembalikan cache[arguments[argPos]];
Lain {// bukan parameter pertama Jika parameter tidak wujud dalam kunci cache, ia sedang melaksanakan kaedah Memoizearg secara rekursif Kedudukan parameter dalam kaedah-1 asal
Jika (!(argumen[argPos] dalam cache)) {
cache[arguments[argPos]] = memoizeArg(argPos - 1);
kembali cache[arguments[argPos]].apply(this, arguments
).
}
}
var arity = func.arity ||. func.length; //Panjang parameter func, atribut panjang digunakan dalam JavaScript dan atribut arity digunakan untuk yang lain
Kembalikan memoizeArg(arity - 1); //Recurse daripada parameter terakhir
}
Gunakan:
Salin kod
Kod adalah seperti berikut:
var mem = memoize(func, this);
makluman(mem.call(ini,1,1,2));
makluman(mem.call(ini,2,1,2));
alert(mem.call(this,3,1,3));
alert(mem.call(this,2,2,4));
Nampak mudah, tetapi ia mungkin tidak mudah difahami pada pandangan pertama Namun, jika anda sudah biasa dengan penggunaan penutupan, ia akan mudah difahami. Selepas beberapa panggilan ke mem.call di atas, pokok terbentuk, setiap nod adalah penutupan, setiap penutupan mempunyai cache dan kunci setiap cache ialah cawangan pokok:
(Nota: "hasil" dalam gambar di atas juga merupakan penutupan, tetapi argPos ialah 0)
Tetapi terdapat banyak cara, contohnya, limbboy berkata:
Salin kod
Kod adalah seperti berikut:
fungsi Memoize(fn){
var cache = {};
Kembalikan fungsi(){
kunci var = [];
untuk( var i=0, l = arguments.length; i < l; i )
key.push(arguments[i]);
Jika( !(kunci dalam cache) )
cache[key] = fn.apply(this, arguments);
kembalikan cache [kunci];
};
}
Pelaksanaan adalah lebih mudah, tetapi tolak parameter ke dalam tatasusunan, dan kemudian gunakan tatasusunan sebagai kunci, dan kunci itu hanya menyokong jenis rentetan, jadi anda perlu memberi perhatian kepada perkara ini apabila menggunakannya (contohnya, objek hanya boleh dilihat selepas rentetan "[objek objek]"), fungsinya lebih lemah daripada yang di atas.
Tidak sukar untuk memperbaiki perkara ini Cuma buat objek berasingan untuk parameter dan objek cache asal dan objek parameter berasingan ini dikaitkan dengan ID:
var cache = {}, args = {};
Kembalikan fungsi(){
for( var i=0, key = args.length; i < key; i ) {
If( equal( args[i], arguments ) )
kembalikan cache[i];
}
args[key] = argumen;
cache[key] = fn.apply(this, arguments
).
kembalikan cache [kunci];
};
}
Terdapat kaedah lain, yang boleh ditulis sebagai kaedah berfungsi ringkas.