Saya mempelajari THREE.js dan melihat pola di mana fungsi didefinisikan seperti ini:
var foo = ( function () {
var bar = new Bar();
return function ( ) {
//actual logic using bar from above.
//return result;
};
}());
(Contoh lihat metode raycast di sini ).
The biasa variasi metode tersebut akan terlihat seperti ini:
var foo = function () {
var bar = new Bar();
//actual logic.
//return result;
};
Membandingkan versi pertama dengan variasi normal , versi pertama tampaknya berbeda dalam hal:
- Ini memberikan hasil dari fungsi yang mengeksekusi sendiri.
- Ini mendefinisikan variabel lokal dalam fungsi ini.
- Ini mengembalikan fungsi sebenarnya yang berisi logika yang menggunakan variabel lokal.
Jadi perbedaan utamanya adalah pada variasi pertama bilah hanya ditetapkan satu kali, saat inisialisasi, sedangkan variasi kedua membuat variabel sementara ini setiap kali dipanggil.
Tebakan terbaik saya tentang mengapa ini digunakan adalah membatasi jumlah contoh untuk bar (hanya akan ada satu) dan dengan demikian menghemat overhead manajemen memori.
Pertanyaan saya:
- Apakah asumsi ini benar?
- Apakah ada nama untuk pola ini?
- Mengapa ini digunakan?
javascript
closures
iife
Patrick Klug
sumber
sumber
Jawaban:
Asumsi Anda hampir benar. Mari kita ulas dulu.
Ini disebut ekspresi fungsi yang dipanggil segera atau IIFE
Ini adalah cara memiliki bidang objek pribadi di JavaScript karena tidak menyediakan
private
kata kunci atau fungsionalitas sebaliknya.Sekali lagi, poin utamanya adalah variabel lokal ini bersifat privat .
AFAIK Anda dapat memanggil Pola Modul pola ini . Mengutip:
Membandingkan kedua contoh tersebut, tebakan terbaik saya tentang mengapa yang pertama digunakan adalah:
Tetapi jika Anda hanya membutuhkan objek vanilla setiap saat, maka pola ini mungkin tidak akan menambah nilai apa pun.
sumber
Ini membatasi biaya inisialisasi objek dan juga memastikan bahwa semua pemanggilan fungsi menggunakan objek yang sama . Ini memungkinkan, misalnya, status disimpan di objek untuk digunakan dalam pemanggilan di masa mendatang.
Meskipun mungkin membatasi penggunaan memori, biasanya GC akan mengumpulkan objek yang tidak digunakan, jadi pola ini sepertinya tidak akan banyak membantu.
Pola ini adalah bentuk penutupan tertentu .
sumber
Saya tidak yakin apakah pola ini memiliki nama yang lebih benar, tetapi ini tampak seperti modul bagi saya, dan alasan penggunaannya adalah untuk merangkum dan mempertahankan status.
Penutupan (diidentifikasi oleh fungsi di dalam fungsi) memastikan bahwa fungsi dalam memiliki akses ke variabel di dalam fungsi luar.
Dalam contoh yang Anda berikan, fungsi bagian dalam dikembalikan (dan ditetapkan ke
foo
) dengan menjalankan fungsi luar yang berartitmpObject
terus hidup di dalam closure dan beberapa panggilan ke fungsi bagian dalamfoo()
akan beroperasi pada contoh yang samatmpObject
.sumber
Perbedaan utama antara kode Anda dan kode Three.js adalah bahwa dalam kode Three.js variabel
tmpObject
hanya diinisialisasi sekali, dan kemudian dibagikan oleh setiap pemanggilan fungsi yang dikembalikan.Ini akan berguna untuk menjaga beberapa status antar panggilan, mirip dengan bagaimana
static
variabel digunakan dalam bahasa mirip C.tmpObject
adalah variabel privat yang hanya dapat dilihat oleh fungsi bagian dalam.Ini mengubah penggunaan memori, tetapi tidak dirancang untuk menghemat memori.
sumber
Saya ingin berkontribusi pada utas yang menarik ini dengan memperluas konsep pola modul pengungkapan, yang memastikan bahwa semua metode dan variabel dijaga kerahasiaannya hingga mereka diekspos secara eksplisit.
Dalam kasus terakhir, metode penambahan akan disebut sebagai Calculator.add ();
sumber
Dalam contoh yang diberikan, cuplikan pertama akan menggunakan contoh tmpObject yang sama untuk setiap panggilan ke fungsi foo (), sedangkan seperti pada cuplikan kedua, tmpObject akan menjadi contoh baru setiap saat.
Salah satu alasan cuplikan pertama mungkin telah digunakan, adalah karena variabel tmpObject dapat dibagikan di antara panggilan ke foo (), tanpa nilainya bocor ke dalam cakupan di mana foo () dideklarasikan.
Versi fungsi yang tidak segera dijalankan dari cuplikan pertama sebenarnya akan terlihat seperti ini:
Namun perlu diperhatikan bahwa versi ini memiliki tmpObject dalam lingkup yang sama dengan foo (), sehingga dapat dimanipulasi nanti.
Cara yang lebih baik untuk mencapai fungsionalitas yang sama adalah dengan menggunakan modul terpisah:
Modul 'foo.js':
Modul 2:
Perbandingan antara kinerja IEF dan fungsi pembuat foo bernama: http://jsperf.com/ief-vs-named-function
sumber