Saya telah melihat beberapa jawaban yang serupa, tetapi saya ingin menyebutkan bahwa posting ini paling menggambarkannya, jadi saya ingin membagikannya dengan Anda.
Inilah beberapa kode yang diambil darinya, yang telah saya modifikasi untuk mendapatkan contoh lengkap yang semoga bermanfaat bagi komunitas karena dapat digunakan sebagai templat desain untuk kelas.
Itu juga menjawab pertanyaan Anda:
function Podcast() {
// private variables
var _somePrivateVariable = 123;
// object properties (read/write)
this.title = 'Astronomy Cast';
this.description = 'A fact-based journey through the galaxy.';
this.link = 'http://www.astronomycast.com';
// for read access to _somePrivateVariable via immutableProp
this.immutableProp = function() {
return _somePrivateVariable;
}
// object function
this.toString = function() {
return 'Title: ' + this.title;
}
};
// static property
Podcast.FILE_EXTENSION = 'mp3';
// static function
Podcast.download = function(podcast) {
console.log('Downloading ' + podcast + ' ...');
};
Dengan contoh itu, Anda dapat mengakses properti / fungsi statis sebagai berikut:
// access static properties/functions
console.log(Podcast.FILE_EXTENSION); // 'mp3'
Podcast.download('Astronomy cast'); // 'Downloading Astronomy cast ...'
Dan objek properti / fungsi cukup sebagai:
// access object properties/functions
var podcast = new Podcast();
podcast.title = 'The Simpsons';
console.log(podcast.toString()); // Title: The Simpsons
console.log(podcast.immutableProp()); // 123
Perhatikan bahwa di podcast.immutableProp (), kami memiliki penutup : Referensi ke _somePrivateVariable disimpan di dalam fungsi.
Anda bahkan dapat mendefinisikan getter dan setter . Lihatlah potongan kode ini (di mana d
prototipe objek yang ingin Anda deklarasikan properti, y
adalah variabel pribadi yang tidak terlihat di luar konstruktor):
// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
get: function() {return this.getFullYear() },
set: function(y) { this.setFullYear(y) }
});
Ini mendefinisikan properti d.year
via get
dan set
fungsinya - jika Anda tidak menentukan set
, maka properti tersebut hanya baca dan tidak dapat dimodifikasi (perlu diketahui bahwa Anda tidak akan mendapatkan kesalahan jika Anda mencoba mengaturnya, tetapi tidak berpengaruh). Setiap properti memiliki atribut writable
, configurable
(diizinkan untuk mengubah setelah deklarasi) dan enumerable
(memungkinkan untuk menggunakannya sebagai enumerator), yang sesuai standar false
. Anda dapat mengaturnya melalui defineProperty
parameter ke-3, mis enumerable: true
.
Yang juga valid adalah sintaks ini:
// getters and setters - alternative syntax
var obj = { a: 7,
get b() {return this.a + 1;},
set c(x) {this.a = x / 2}
};
yang mendefinisikan properti yang dapat dibaca / ditulis a
, properti hanya-baca b
dan properti hanya-tulis c
, di mana properti a
dapat diakses.
Pemakaian:
console.log(obj.a); console.log(obj.b); // output: 7, 8
obj.c=40;
console.log(obj.a); console.log(obj.b); // output: 20, 21
Catatan:
Untuk menghindari perilaku tak terduga jika Anda lupa new
kata kunci, saya sarankan Anda menambahkan fungsi berikut Podcast
:
// instantiation helper
function Podcast() {
if(false === (this instanceof Podcast)) {
return new Podcast();
}
// [... same as above ...]
};
Sekarang kedua instantiasi berikut akan berfungsi seperti yang diharapkan:
var podcast = new Podcast(); // normal usage, still allowed
var podcast = Podcast(); // you can omit the new keyword because of the helper
Pernyataan 'baru' membuat objek baru dan menyalin semua properti dan metode, yaitu
var a=new Podcast();
var b=new Podcast();
a.title="a"; b.title="An "+b.title;
console.log(a.title); // "a"
console.log(b.title); // "An Astronomy Cast"
Perhatikan juga, bahwa dalam beberapa situasi akan berguna untuk menggunakan return
pernyataan dalam fungsi konstruktor Podcast
untuk mengembalikan fungsi kustom objek yang dilindungi kelas secara internal tetapi bergantung pada yang perlu diekspos. Ini dijelaskan lebih lanjut dalam bab 2 (Objek) dari seri artikel.
Anda bisa mengatakan itu a
dan b
mewarisi dari Podcast
. Sekarang, bagaimana jika Anda ingin menambahkan metode ke Podcast yang berlaku untuk semuanya setelah a
dan b
telah di-instanciated? Dalam hal ini, gunakan yang .prototype
berikut ini:
Podcast.prototype.titleAndLink = function() {
return this.title + " [" + this.link + "]";
};
Sekarang telepon a
dan b
lagi:
console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"
Anda dapat menemukan detail lebih lanjut tentang prototipe di sini . Jika Anda ingin melakukan lebih banyak warisan, saya sarankan melihat ke dalam ini .
Seri artikel yang saya sebutkan di atas sangat disarankan untuk dibaca, termasuk juga topik-topik berikut:
- Fungsi
- Benda
- Prototipe
- Menerapkan Fungsi Baru pada Konstruktor
- Mengangkat
- Penyisipan titik koma otomatis
- Properti dan Metode Statis
Perhatikan bahwa penyisipan titik koma otomatis "fitur" dari JavaScript (sebagaimana disebutkan dalam 6.) seringkali bertanggung jawab untuk menyebabkan masalah aneh pada kode Anda. Oleh karena itu, saya lebih suka menganggapnya sebagai bug daripada sebagai fitur.
Jika Anda ingin membaca lebih lanjut, berikut ini adalah artikel MSDN yang cukup menarik tentang topik-topik ini, beberapa di antaranya dijelaskan di sana memberikan lebih banyak detail.
Yang juga menarik untuk dibaca (juga mencakup topik-topik yang disebutkan di atas) adalah artikel-artikel dari MDN JavaScript Guide :
Jika Anda ingin tahu cara meniru out
parameter c # (seperti dalam DateTime.TryParse(str, out result)
) dalam JavaScript, Anda dapat menemukan kode sampel di sini.
Anda yang bekerja dengan IE (yang tidak memiliki konsol untuk JavaScript kecuali Anda membuka alat pengembang menggunakan F12dan membuka tab konsol) mungkin menemukan potongan berikut ini bermanfaat. Ini memungkinkan Anda untuk menggunakan console.log(msg);
sebagaimana digunakan dalam contoh di atas. Cukup masukkan sebelum Podcast
fungsi.
Untuk kenyamanan Anda, inilah kode di atas dalam satu cuplikan kode tunggal lengkap:
let console = { log: function(msg) {
let canvas = document.getElementById("log"), br = canvas.innerHTML==="" ? "" : "<br/>";
canvas.innerHTML += (br + (msg || "").toString());
}};
console.log('For details, see the explaining text');
function Podcast() {
// with this, you can instantiate without new (see description in text)
if (false === (this instanceof Podcast)) {
return new Podcast();
}
// private variables
var _somePrivateVariable = 123;
// object properties
this.title = 'Astronomy Cast';
this.description = 'A fact-based journey through the galaxy.';
this.link = 'http://www.astronomycast.com';
this.immutableProp = function() {
return _somePrivateVariable;
}
// object function
this.toString = function() {
return 'Title: ' + this.title;
}
};
// static property
Podcast.FILE_EXTENSION = 'mp3';
// static function
Podcast.download = function(podcast) {
console.log('Downloading ' + podcast + ' ...');
};
// access static properties/functions
Podcast.FILE_EXTENSION; // 'mp3'
Podcast.download('Astronomy cast'); // 'Downloading Astronomy cast ...'
// access object properties/functions
var podcast = new Podcast();
podcast.title = 'The Simpsons';
console.log(podcast.toString()); // Title: The Simpsons
console.log(podcast.immutableProp()); // 123
// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
get: function() {
return this.getFullYear()
},
set: function(y) {
this.setFullYear(y)
}
});
// getters and setters - alternative syntax
var obj = {
a: 7,
get b() {
return this.a + 1;
},
set c(x) {
this.a = x / 2
}
};
// usage:
console.log(obj.a); console.log(obj.b); // output: 7, 8
obj.c=40;
console.log(obj.a); console.log(obj.b); // output: 20, 21
var a=new Podcast();
var b=new Podcast();
a.title="a"; b.title="An "+b.title;
console.log(a.title); // "a"
console.log(b.title); // "An Astronomy Cast"
Podcast.prototype.titleAndLink = function() {
return this.title + " [" + this.link + "]";
};
console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"
<div id="log"></div>
Catatan:
Beberapa tips, petunjuk, dan rekomendasi yang bagus tentang pemrograman JavaScript secara umum dapat Anda temukan di sini (praktik terbaik JavaScript) dan di sana ('var' versus 'let') . Juga disarankan artikel ini tentang typecasts implisit (pemaksaan) .
Cara mudah untuk menggunakan kelas dan mengompilasinya ke dalam JavaScript adalah TypeScript. Berikut adalah taman bermain di mana Anda dapat menemukan beberapa contoh yang menunjukkan kepada Anda cara kerjanya. Bahkan jika Anda tidak menggunakan TypeScript saat ini, Anda dapat melihatnya karena Anda dapat membandingkan TypeScript dengan hasil JavaScript pada tampilan berdampingan. Sebagian besar contoh sederhana, tetapi ada juga contoh Raytracer yang dapat Anda coba secara instan. Saya sarankan terutama melihat contoh "Menggunakan Kelas", "Menggunakan Warisan" dan "Menggunakan Generik" dengan memilihnya di kotak kombo - ini adalah templat yang bagus yang dapat langsung Anda gunakan dalam JavaScript. Naskah digunakan dengan Angular.
Untuk mencapai enkapsulasi variabel lokal, fungsi dll dalam JavaScript, saya sarankan untuk menggunakan pola seperti berikut (JQuery menggunakan teknik yang sama):
<html>
<head></head>
<body><script>
'use strict';
// module pattern (self invoked function)
const myModule = (function(context) {
// to allow replacement of the function, use 'var' otherwise keep 'const'
// put variables and function with local module scope here:
var print = function(str) {
if (str !== undefined) context.document.write(str);
context.document.write("<br/><br/>");
return;
}
// ... more variables ...
// main method
var _main = function(title) {
if (title !== undefined) print(title);
print("<b>last modified: </b>" + context.document.lastModified + "<br/>");
// ... more code ...
}
// public methods
return {
Main: _main
// ... more public methods, properties ...
};
})(this);
// use module
myModule.Main("<b>Module demo</b>");
</script></body>
</html>
Tentu saja, Anda dapat - dan harus - memasukkan kode skrip ke dalam *.js
file terpisah ; ini hanya ditulis sebaris untuk menjaga contoh singkat.
Fungsi self-invocing (juga dikenal sebagai IIFE = Ekspresi Fungsi Segera Diminta) dijelaskan lebih rinci di sini .