Saya mempertahankan beberapa kode warisan dan saya perhatikan bahwa pola berikut untuk mendefinisikan objek digunakan:
var MyObject = {};
(function (root) {
root.myFunction = function (foo) {
//do something
};
})(MyObject);
Apakah ada tujuan dari ini? Apakah itu setara dengan hanya melakukan hal berikut?
var MyObject = {
myFunction : function (foo) {
//do something
};
};
Saya tidak akan memulai misi suci untuk merefaktor seluruh basis kode sesuai dengan keinginan saya, tetapi saya benar-benar ingin memahami alasan di balik cara memutar untuk menentukan objek.
Terima kasih!
javascript
javascript-objects
Sebastián Vansteenkiste
sumber
sumber
myFunction
bisa menggunakan beberapa variabel yang didefinisikan di luar dirinya sendiri yang tidak akan dapat diakses dari luar. Lihat jawaban sayaJawaban:
Ini disebut pola modul http://toddmotto.com/mastering-the-module-pattern/
Alasan utamanya adalah Anda membuat metode dan variabel yang benar-benar pribadi. Dalam kasus Anda, ini tidak berarti karena tidak menyembunyikan detail implementasi apa pun.
Berikut adalah contoh di mana masuk akal untuk menggunakan pola modul.
var MyNameSpace = {}; (function(ns){ // The value variable is hidden from the outside world var value = 0; // So is this function function adder(num) { return num + 1; } ns.getNext = function () { return value = adder(value); } })(MyNameSpace); var id = MyNameSpace.getNext(); // 1 var otherId = MyNameSpace.getNext(); // 2 var otherId = MyNameSpace.getNext(); // 3
Sedangkan jika Anda hanya menggunakan benda lurus,
adder
danvalue
akan menjadi publikvar MyNameSpace = { value: 0, adder: function(num) { return num + 1; }, getNext: function() { return this.value = this.adder(this.value); } }
Dan Anda bisa memecahkannya dengan melakukan hal-hal seperti
MyNameSpace.getNext(); // 1 MyNameSpace.value = 0; MyNameSpace.getNext(); // 1 again delete MyNameSpace.adder; MyNameSpace.getNext(); // error undefined is not a function
Tetapi dengan versi modul
MyNameSpace.getNext(); // 1 // Is not affecting the internal value, it's creating a new property MyNameSpace.value = 0; MyNameSpace.getNext(); // 2, yessss // Is not deleting anything delete MyNameSpace.adder; MyNameSpace.getNext(); // no problemo, outputs 3
sumber
ns.getNext: function () {
tidak akan bisa dikompilasi.delete MyNameSpace.getNext
.:)
Tujuannya adalah untuk membatasi aksesibilitas fungsi dalam closure untuk membantu mencegah skrip lain mengeksekusi kode di dalamnya. Dengan membungkusnya di sekitar closure, Anda mendefinisikan ulang cakupan eksekusi untuk semua kode di dalam closure dan secara efektif membuat ruang lingkup privat. Lihat artikel ini untuk info lebih lanjut:
http://lupomontero.com/using-javascript-closures-to-create-private-scopes/
Dari artikel:
Kode:
var MyObject = {}; (function (root) { function myPrivateFunction() { return "I can only be called from within the closure"; } root.myFunction = function (foo) { //do something }; myPrivateFunction(); // returns "I can only be called from within the closure" })(MyObject); myPrivateFunction(); // throws error - undefined is not a function
sumber
myFunction
tidak dalam cakupan global di versi kedua. Tujuan sebenarnya adalah untuk menyediakan ruang lingkup di mana fungsi pembantu internal dapat didefinisikan.myFunction
berada dalam cakupan global karena didefinisikan dalam objek globalmyObject
. Pada versi kedua, kode lain dalam aplikasi dapat dijalankanmyFunction
. Dalam versi pertama, hanya kode dalam penutupan yang memiliki akses kemyFunction
myFunction
hanya dapat dijalankan sebagaiMyObject.myFunction()
, sama seperti versi pertama.keuntungan:
memelihara variabel dalam ruang lingkup pribadi.
Anda dapat memperluas fungsionalitas objek yang ada.
kinerja meningkat.
Saya pikir tiga poin sederhana di atas cukup untuk mengikuti aturan tersebut. Dan untuk membuatnya tetap sederhana tidak lain adalah menulis fungsi batin.
sumber
Dalam kasus tertentu yang Anda tunjukkan, tidak ada perbedaan yang berarti, dalam hal fungsionalitas atau visibilitas.
Sepertinya pembuat kode asli mengadopsi pendekatan ini sebagai semacam templat yang memungkinkannya untuk menentukan variabel privat yang dapat digunakan dalam definisi hal-hal seperti
myFunction
:var MyObject = {}; (function(root) { var seconds_per_day = 24 * 60 * 60; // <-- private variable root.myFunction = function(foo) { return seconds_per_day; }; })(MyObject);
Ini menghindari penghitungan
seconds_per_day
setiap kali fungsi dipanggil, sekaligus menjaganya agar tidak mencemari ruang lingkup global.Namun, pada dasarnya tidak ada yang berbeda dari itu dan hanya mengatakan
var MyObject = function() { var seconds_per_day = 24 * 60 * 60; return { myFunction: function(foo) { return seconds_per_day; } }; }();
Pembuat kode asli mungkin lebih suka untuk dapat menambahkan fungsi ke objek menggunakan sintaks deklaratif
root.myFunction = function
, daripada sintaks objek / propertimyFunction: function
. Tetapi perbedaan itu terutama adalah masalah preferensi.Namun, struktur yang diambil oleh pembuat kode asli memiliki keuntungan bahwa properti / metode dapat dengan mudah ditambahkan di tempat lain dalam kode:
var MyObject = {}; (function(root) { var seconds_per_day = 24 * 60 * 60; root.myFunction = function(foo) { return seconds_per_day; }; })(MyObject); (function(root) { var another_private_variable = Math.pi; root.myFunction2 = function(bar) { }; })(MyObject);
Intinya, tidak perlu mengadopsi pendekatan ini jika Anda tidak perlu, tetapi juga tidak perlu mengubahnya, karena ini bekerja dengan baik dan sebenarnya memiliki beberapa keuntungan.
sumber
Pola pertama dapat digunakan sebagai modul yang mengambil objek dan mengembalikan objek tersebut dengan beberapa modifikasi. Dengan kata lain, Anda dapat mendefinisikan modul seperti berikut.
var module = function (root) { root.myFunction = function (foo) { //do something }; }
Dan gunakan seperti:
var obj = {}; module(obj);
Jadi keuntungan bisa menjadi kegunaan kembali modul ini untuk digunakan nanti.
Pada pola pertama, Anda dapat menentukan ruang lingkup pribadi untuk menyimpan barang pribadi Anda seperti properti dan metode pribadi. Misalnya, pertimbangkan cuplikan ini:
(function (root) { // A private property var factor = 3; root.multiply = function (foo) { return foo * factor; }; })(MyObject);
Pola ini dapat digunakan untuk menambahkan metode atau properti ke semua jenis objek seperti array, literal objek, fungsi.
function sum(a, b) { return a + b; } (function (root) { // A private property var factor = 3; root.multiply = function (foo) { return foo * factor; }; })(sum); console.log(sum(1, 2)); // 3 console.log(sum.multiply(4)); // 12
Menurut saya, keuntungan utama bisa jadi yang kedua (menciptakan ruang lingkup pribadi)
sumber
Pola ini menyediakan cakupan di mana Anda dapat menentukan fungsi pembantu yang tidak terlihat dalam cakupan global:
(function (root) { function doFoo() { ... }; root.myFunction = function (foo) { //do something doFoo(); //do something else }; })(MyObject);
doFoo
bersifat lokal untuk fungsi anonim, tidak dapat dirujuk dari luar.sumber