Untuk membuat kelas JavaScript dengan metode publik, saya akan melakukan sesuatu seperti:
function Restaurant() {}
Restaurant.prototype.buy_food = function(){
// something here
}
Restaurant.prototype.use_restroom = function(){
// something here
}
Dengan cara itu pengguna kelas saya dapat:
var restaurant = new Restaurant();
restaurant.buy_food();
restaurant.use_restroom();
Bagaimana cara membuat metode pribadi yang dapat dipanggil oleh buy_food
dan use_restroom
metode tetapi tidak secara eksternal oleh pengguna kelas?
Dengan kata lain, saya ingin implementasi metode saya dapat dilakukan:
Restaurant.prototype.use_restroom = function() {
this.private_stuff();
}
Tetapi ini seharusnya tidak berhasil:
var r = new Restaurant();
r.private_stuff();
Bagaimana cara saya mendefinisikan private_stuff
sebagai metode pribadi sehingga keduanya benar?
Saya telah membaca Lup menulis Doug Crockford beberapa kali tetapi tampaknya tidak seperti metode "pribadi" dapat dipanggil dengan metode publik dan metode "istimewa" dapat disebut secara eksternal.
sumber
Menggunakan fungsi dan panggilan pemanggilan diri
JavaScript menggunakan prototipe dan tidak memiliki kelas (atau metode dalam hal ini) seperti bahasa yang Berorientasi Objek. Pengembang JavaScript perlu berpikir dalam JavaScript.
Kutipan Wikipedia:
Solusi menggunakan fungsi pemanggilan sendiri dan fungsi panggilan untuk memanggil "metode" pribadi:
Fungsi panggilan memungkinkan kita untuk memanggil fungsi pribadi dengan konteks yang sesuai (
this
).Lebih sederhana dengan Node.js
Jika Anda menggunakan node.js , Anda tidak perlu IIFE karena Anda dapat memanfaatkan sistem pemuatan modul :
Muat file:
(Eksperimental) ES7 dengan Bind Operator
Operator mengikat
::
adalah proposal ECMAScript dan diimplementasikan dalam Babel ( tahap 0 ).Muat file:
sumber
.call
bagian itu.f()
di javascript (tidak saat ini)..call
) dan memori kecil (tidak ada fungsi pada contoh)? Apakah itu ada?Anda dapat mensimulasikan metode pribadi seperti ini:
Informasi lebih lanjut tentang teknik ini di sini: http://webreflection.blogspot.com/2008/04/natural-javascript-private-methods.html
sumber
Dalam situasi ini ketika Anda memiliki API publik, dan Anda ingin metode / properti pribadi dan publik, saya selalu menggunakan Pola Modul. Pola ini menjadi populer di perpustakaan YUI, dan detailnya dapat ditemukan di sini:
http://yuiblog.com/blog/2007/06/12/module-pattern/
Ini sangat mudah, dan mudah dipahami oleh pengembang lain. Sebagai contoh sederhana:
sumber
aPrivateMethod = function() { MYLIB.aPublicProperty}
?Ini adalah kelas yang saya buat untuk memahami apa yang disarankan Douglas Crockford di situsnya Anggota Pribadi dalam JavaScript
sumber
that
digunakan alih-alihthis
untuk menghindari masalah pelingkupan, ketika fungsi terikat ke objek yang berbeda. Di sini, Anda menyimpanthis
dalamthat
dan tidak pernah menggunakannya lagi yang sama dengan tidak melakukannya sama sekali. Anda harus berubahthis
denganthat
semuaConstructor
fungsi dalam (bukan deklarasi metode). Jikaemployee
iniapply
ed ataucall
ed dalam beberapa cara metode ini mungkin melemparkan karenathis
akan benar terikat.Saya menyulap ini: EDIT: Sebenarnya, seseorang telah menautkan ke solusi yang identik. Duh!
sumber
var getAwayVehicle = new Car(100);
mana100
kecepatan dan Anda ingin mengingatkan kecepatan. Terima kasih!var Car = function(speed) { this.speed = speed; }
dan `kembali {constructor: Car, ...`Saya pikir pertanyaan seperti itu muncul lagi dan lagi karena kurangnya pemahaman tentang penutupan. Сlosures adalah hal terpenting dalam JS. Setiap programmer JS harus merasakan esensi dari itu.
1. Pertama-tama kita perlu membuat ruang lingkup yang terpisah (penutupan).
2. Di bidang ini, kita dapat melakukan apa pun yang kita inginkan. Dan tidak ada yang akan tahu tentang itu.
3. Agar dunia tahu tentang kelas restoran kami, kami harus mengembalikannya dari penutupan.
4. Pada akhirnya, kami memiliki:
5. Juga, pendekatan ini memiliki potensi untuk pewarisan dan templating
Saya harap ini membantu seseorang lebih memahami masalah ini
sumber
Secara pribadi, saya lebih suka pola berikut untuk membuat kelas di JavaScript:
Seperti yang Anda lihat, ini memungkinkan Anda untuk mendefinisikan properti kelas dan properti instance, yang masing-masing dapat bersifat publik dan pribadi.
Demo
Lihat juga Fiddle ini .
sumber
Semua penutupan ini akan dikenakan biaya. Pastikan Anda menguji implikasi kecepatan terutama di IE. Anda akan merasa lebih baik dengan konvensi penamaan. Masih ada banyak pengguna web perusahaan di luar sana yang terpaksa menggunakan IE6 ...
sumber
Jangan terlalu bertele-tele. Ini Javascript. Gunakan Konvensi Penamaan .
Setelah bertahun-tahun bekerja di kelas ES6, saya baru-baru ini mulai bekerja pada proyek ES5 (menggunakan requireJS yang sudah sangat verbose). Saya telah berulang-ulang semua strategi yang disebutkan di sini dan semuanya pada dasarnya bermuara pada penggunaan konvensi penamaan :
private
. Pengembang lain yang memasukkan Javascript akan mengetahui hal ini di muka. Oleh karena itu, konvensi penamaan sederhana lebih dari cukup. Konvensi penamaan awalan sederhana dengan garis bawah memecahkan masalah properti pribadi dan metode pribadi.my-tooltip.js
sumber
define
, danconstructor
dan struktur itu sendiri. Sementara saya setuju sebagian besar pada jawaban, saya sudah mulai bekerja dengan JS dengan banyak pengaruh OOP dan bahkan melompat terlalu dini ke TS karena saya memiliki pengalaman sebelumnya ke C #. Saya pikir saya harus menghapus hal-hal ini dan harus memahami paradigma prototyping / prosedural. (Terpilih, btw)Anda dapat melakukannya sekarang dengan metode pribadi ES10 . Anda hanya perlu menambahkan
#
sebelum nama metode.sumber
Mengambil salah satu solusi yang mengikuti Crockford pribadi atau priviledged pola. Sebagai contoh:
Dalam setiap kasus di mana penyerang tidak memiliki hak "mengeksekusi" pada konteks JS ia tidak memiliki cara untuk mengakses bidang atau metode "publik" atau "pribadi". Seandainya penyerang memiliki akses tersebut, ia dapat menjalankan one-liner ini:
Perhatikan bahwa kode di atas adalah generik untuk semua privasi tipe konstruktor. Ini akan gagal dengan beberapa solusi di sini tetapi harus jelas bahwa hampir semua solusi berbasis penutupan dapat dipecah seperti ini dengan
replace()
parameter yang berbeda .Setelah ini dieksekusi objek apa pun yang dibuat dengan
new Foo()
akan memilikieval
metode yang dapat dipanggil untuk mengembalikan atau mengubah nilai atau metode yang didefinisikan dalam penutupan konstruktor, misalnya:Satu-satunya masalah yang saya dapat lihat dengan ini bahwa itu tidak akan berfungsi untuk kasus-kasus di mana hanya ada satu contoh dan itu dibuat saat dimuat. Tetapi kemudian tidak ada alasan untuk benar-benar mendefinisikan prototipe dan dalam hal ini penyerang dapat dengan mudah menciptakan kembali objek alih-alih konstruktor selama ia memiliki cara untuk melewatkan parameter yang sama (misalnya mereka konstan atau dihitung dari nilai yang tersedia).
Menurut pendapat saya, ini cukup banyak membuat solusi Crockford tidak berguna.Karena "privasi" dengan mudah merusak kelemahan dari solusinya (mengurangi keterbacaan & pemeliharaan, penurunan kinerja, peningkatan memori) menjadikan metode berbasis prototipe "tidak privasi" menjadi pilihan yang lebih baik.
Saya biasanya menggunakan garis bawah terkemuka untuk menandai
__private
dan_protected
metode dan bidang (gaya Perl), tetapi gagasan memiliki privasi dalam JavaScript hanya menunjukkan bagaimana itu adalah bahasa yang disalahpahami.Karena itu saya tidak setuju dengan Crockford kecuali untuk kalimat pertamanya.
Jadi, bagaimana Anda mendapatkan privasi nyata di JS? Masukkan semua yang diperlukan untuk menjadi pribadi di sisi server dan gunakan JS untuk melakukan panggilan AJAX.
sumber
(function () {allMyStuff}());
sehingga tidak mengungkapkan global.f.eval('nameOfVariable')
ketika Anda tidak tahu apa'nameOfVariable'
itu ...Pendewaan Pola Modul: Pola Modul Pengungkapan
Ekstensi kecil yang rapi untuk pola yang sangat kuat.
sumber
Jika Anda ingin berbagai fungsi publik dan pribadi dengan kemampuan fungsi publik untuk mengakses fungsi pribadi, tata letak kode untuk objek seperti ini:
sumber
new MyObject
, prototipeMyObject
diganti dengan nilai yang sama..prototype
dalam konstruktor.Mirip dengan georgebrock tetapi sedikit kurang verbose (IMHO) Ada masalah dengan melakukannya dengan cara ini? (Saya belum melihatnya di mana pun)
sunting: Saya menyadari ini agak tidak berguna karena setiap lembaga independen memiliki salinan sendiri dari metode publik, sehingga merusak penggunaan prototipe.
sumber
Inilah yang saya nikmati sejauh ini mengenai metode / anggota pribadi / publik dan instantiasi dalam javascript:
di sini adalah artikelnya: http://www.sefol.com/?p=1090
dan inilah contohnya:
JSFiddle: http://jsfiddle.net/northkildonan/kopj3dt3/1/
sumber
Pola modul benar dalam banyak kasus. Tetapi jika Anda memiliki ribuan instance, kelas menghemat memori. Jika menyimpan memori menjadi perhatian dan objek Anda berisi sejumlah kecil data pribadi, tetapi memiliki banyak fungsi publik, maka Anda ingin semua fungsi publik untuk tinggal di .protype untuk menghemat memori.
Inilah yang saya pikirkan:
Objek tersebut
priv
berisi properti pribadi. Ini dapat diakses melalui fungsi publikgetPriv()
, tetapi fungsi ini kembalifalse
kecuali Anda melewatinyasecret
, dan ini hanya diketahui di dalam penutupan utama.sumber
Bagaimana dengan ini?
Pencarian variabel pribadi tidak dimungkinkan di luar ruang lingkup fungsi langsung. Tidak ada duplikasi fungsi, menghemat memori.
The downside adalah bahwa pencarian variabel pribadi kikuk
privateVars[this.id].cooked
adalah konyol untuk mengetik. Ada juga variabel "id" tambahan.sumber
Restaurant
sebagaiundefined
karena Anda tidak kembali apa-apa dari fungsi anonim.Restaurant
telah dikumpulkan, nilai-nilainya tetap di dalamprivateVars
. AWeakMap
mungkin merupakan pengganti yang baik untukArray
kasus ini.Bungkus semua kode dalam Fungsi Anonim: Kemudian, semua fungsi akan menjadi pribadi, HANYA fungsi yang dilampirkan ke
window
objek:Gunakan ini :
BIOLA
sumber
Saya lebih suka menyimpan data pribadi dalam suatu yang terkait
WeakMap
. Ini memungkinkan Anda untuk menjaga metode publik Anda pada prototipe di mana mereka berada. Ini tampaknya menjadi cara paling efisien untuk menangani masalah ini untuk sejumlah besar objek.sumber
Fungsi pribadi tidak dapat mengakses variabel publik menggunakan pola modul
sumber
Karena semua orang memposting di sini kodenya sendiri, saya akan melakukannya juga ...
Saya suka Crockford karena dia memperkenalkan pola berorientasi objek nyata dalam Javascript. Tapi dia juga datang dengan kesalahpahaman baru, yang "itu".
Jadi mengapa dia menggunakan "that = this"? Ini tidak ada hubungannya dengan fungsi pribadi sama sekali. Itu ada hubungannya dengan fungsi batin!
Karena menurut Crockford ini adalah kode kereta:
Jadi dia menyarankan untuk melakukan ini:
Jadi seperti yang saya katakan, saya cukup yakin bahwa Crockford salah penjelasan tentang itu dan ini (tapi kodenya jelas benar). Atau apakah dia hanya membodohi dunia Javascript, untuk mengetahui siapa yang menyalin kode-nya? Saya tidak tahu ... Saya bukan pecandu peramban; D
EDIT
Ah, hanya itu masalahnya: Apa artinya 'var that = this;' artinya dalam JavaScript?
Jadi Crockie benar-benar salah dengan penjelasannya .... tetapi benar dengan kodenya, jadi dia masih pria yang baik. :))
sumber
Secara umum saya menambahkan Obyek pribadi _ sementara ke objek. Anda harus membuka privasi secara eksplisit di "Power-constructor" untuk metode ini. Jika Anda memanggil metode dari prototipe, Anda akan dapat menimpa metode prototipe
Jadikan metode publik dapat diakses di "Power-constructor": (ctx adalah konteks objek)
Sekarang saya punya openPrivacy ini:
sumber
Inilah yang saya kerjakan:
Membutuhkan satu kelas kode gula yang dapat Anda temukan di sini . Juga mendukung hal-hal yang dilindungi, pewarisan, virtual, statis ...
sumber
https://github.com/nooning/JSClass
sumber
Saya telah membuat alat baru untuk memungkinkan Anda memiliki metode pribadi sejati pada prototipe https://github.com/TremayneChrist/ProtectJS
Contoh:
sumber
_private
metode ini?Anda harus menutup fungsi konstruktor yang sebenarnya, di mana Anda dapat menentukan metode pribadi Anda. Untuk mengubah data instance melalui metode pribadi ini, Anda harus memberi mereka "ini" dengan mereka, baik sebagai argumen fungsi atau dengan memanggil fungsi ini dengan .apply (ini):
sumber
new Restaurant
akan memilikirestaurant
konstruktor sendiri , dan "prototipe" benar-benar disalahgunakan.Saya tahu ini agak terlambat tetapi bagaimana dengan ini?
sumber
Sudah banyak jawaban untuk pertanyaan ini, tetapi tidak ada yang sesuai dengan kebutuhan saya. Jadi saya datang dengan solusi saya sendiri, saya harap ini berguna bagi seseorang:
Seperti yang Anda lihat, sistem ini berfungsi saat menggunakan jenis kelas ini dalam javascript. Sejauh yang saya tahu tidak ada metode yang dikomentari di atas.
sumber
Lihat jawaban ini untuk solusi 'kelas' yang bersih & sederhana dengan antarmuka pribadi dan publik serta dukungan untuk komposisi
sumber