Berikut ini adalah dari implementasi John Hann, dan kode ini menarik perhatian saya, yang di -cache hasil panggilan metode dengan metode yang cerdas.
Parsing kode:
Salinan kode adalah sebagai berikut:
// Memoize: Metode umum untuk menggunakan memoisasi untuk cache
// func: metode untuk di -cache
// Konteks: Konteks Eksekusi Metode
// CATATAN: Metode harus dapat diakses secara eksternal, dan parameternya adalah serial-serial
Function Memoize (func, Context) {
fungsi memoizeARG (argpos) {// parameter menunjukkan posisi parameter dalam metode asli
var cache = {}; // Kunci cache ini adalah parameter, dan nilainya adalah hasil eksekusi
return function () {// mengembalikan penutupan fungsi
if (argpos == 0) {// parameter pertama, jika parameter tidak ada di tombol cacheed, fungsi asli akan dieksekusi dan hasil eksekusi akan disimpan
if (! (Argumen [argpos] di cache)) {
cache [argumen [argpos]] = func.Apply (konteks, argumen);
}
mengembalikan cache [argumen [argpos]];
}
lain {// bukan parameter pertama. Jika parameter tidak ada di kunci yang di -cache, metode MemoizeARG akan dieksekusi secara rekursif. Posisi parameter dalam metode asli -1
if (! (Argumen [argpos] di cache)) {
cache [argumen [argpos]] = memoizeARG (argpos - 1);
}
mengembalikan cache [argumen [argpos]]. Terapkan (ini, argumen);
}
}
}
var arity = func.arity || func.length; // Panjang parameter fungsi digunakan, dan atribut Arity digunakan dalam JavaScript.
return memoizearg (arity - 1); // Rekursi dimulai dari parameter terakhir
}
menggunakan:
Salinan kode adalah sebagai berikut:
var mem = memoize (func, this);
peringatan (mem.call (ini, 1,1,2));
peringatan (mem.call (ini, 2,1,2));
peringatan (mem.call (ini, 3,1,3));
peringatan (mem.call (ini, 2,2,4));
Tampaknya sederhana, tetapi tampaknya tidak mudah dimengerti ketika Anda melihatnya, tetapi jika Anda terbiasa dengan penggunaan penutupan, itu akan mudah dimengerti. Setelah panggilan di atas ke mem.call, sebuah pohon terbentuk. Setiap node adalah penutupan, setiap penutupan memiliki cache, dan setiap kunci cache adalah cabang pohon:
(Catatan: "Hasil" pada gambar di atas juga merupakan penutupan, tetapi argpos hanya 0)
Tetapi ada banyak cara, seperti yang dikatakan Limboy:
Salinan kode adalah sebagai berikut:
function memoize (fn) {
var cache = {};
return function () {
var key = [];
untuk (var i = 0, l = argumen.length; i <l; i ++)
key.push (argumen [i]);
if (! (Kunci dalam cache))
cache [key] = fn.Apply (ini, argumen);
mengembalikan cache [kunci];
};
}
Implementasinya lebih mudah, tetapi dorong parameter ke dalam array dan kemudian perlakukan array sebagai kunci, dan kunci hanya mendukung tipe string. Oleh karena itu, Anda perlu memperhatikan hal ini saat menggunakannya (misalnya, setelah objek tostring, Anda hanya dapat melihat "[objek objek]"), dan fungsinya lebih lemah dari yang di atas.
Tidak sulit untuk memperbaiki ini. Cukup atur objek lain dengan parameter, dan objek cache asli dan objek parameter lainnya dikaitkan dengan ID:
Salinan kode adalah sebagai berikut:
function memoize (fn) {
var cache = {}, args = {};
return function () {
untuk (var i = 0, key = args.length; i <key; i ++) {
if (equal (args [i], argumen))
mengembalikan cache [i];
}
args [key] = argumen;
cache [key] = fn.Apply (ini, argumen);
mengembalikan cache [kunci];
};
}
Ada beberapa metode lain yang dapat ditulis sebagai metode fungsional yang ringkas.