Jika dengan "tidak akan dieksekusi" yang Anda maksud "tidak akan melakukan apa-apa saat dipanggil lebih dari sekali", Anda dapat membuat penutupan:
var something = (function() {
var executed = false;
return function() {
if (!executed) {
executed = true;
// do something
}
};
})();
something(); // "do something" happens
something(); // nothing happens
Sebagai jawaban atas komentar @Vladloffe (sekarang dihapus): Dengan variabel global, kode lain dapat menyetel ulang nilai dari tanda "dieksekusi" (apa pun nama yang Anda pilih). Dengan penutupan, kode lain tidak memiliki cara untuk melakukan itu, baik secara tidak sengaja atau sengaja.
Seperti jawaban lain yang ditunjukkan di sini, beberapa pustaka (seperti Underscore dan Ramda ) memiliki fungsi utilitas kecil (biasanya bernama once()
[*] ) yang menerima fungsi sebagai argumen dan mengembalikan fungsi lain yang memanggil fungsi yang disediakan tepat sekali, terlepas dari bagaimana caranya berkali-kali fungsi yang dikembalikan dipanggil. Fungsi yang dikembalikan juga menyimpan nilai yang pertama kali dikembalikan oleh fungsi yang disediakan dan mengembalikannya pada panggilan berikutnya.
Namun, jika Anda tidak menggunakan pustaka pihak ketiga seperti itu, tetapi masih menginginkan fungsi utilitas seperti itu (daripada solusi nonce yang saya tawarkan di atas), cukup mudah untuk diterapkan. Versi terbaik yang pernah saya lihat adalah yang ini diposting oleh David Walsh :
function once(fn, context) {
var result;
return function() {
if (fn) {
result = fn.apply(context || this, arguments);
fn = null;
}
return result;
};
}
Saya akan cenderung untuk berubah fn = null;
menjadi fn = context = null;
. Tidak ada alasan bagi penutupan untuk mempertahankan referensi ke context
sekali fn
telah dipanggil.
[*] Namun, ketahuilah, bahwa pustaka lain, seperti ekstensi Drupal ke jQuery ini , mungkin memiliki fungsi bernama once()
yang melakukan sesuatu yang sangat berbeda.