Untuk memperluas jawaban @ loganfsmyth:
Satu-satunya data yang benar-benar pribadi dalam JavaScript masih variabel cakupan. Anda tidak dapat memiliki properti pribadi dalam arti properti yang diakses secara internal dengan cara yang sama seperti properti publik, tetapi Anda dapat menggunakan variabel scoped untuk menyimpan data pribadi.
Variabel cakupan
Pendekatan di sini adalah dengan menggunakan ruang lingkup fungsi konstruktor, yang bersifat pribadi, untuk menyimpan data pribadi. Agar metode memiliki akses ke data pribadi ini, mereka juga harus dibuat di dalam konstruktor, artinya Anda membuat ulang dengan setiap contoh. Ini adalah penalti kinerja dan memori, tetapi beberapa percaya penalti itu dapat diterima. Hukuman dapat dihindari untuk metode yang tidak memerlukan akses ke data pribadi dengan menambahkannya ke prototipe seperti biasa.
Contoh:
function Person(name) {
let age = 20; // this is private
this.name = name; // this is public
this.greet = function () {
// here we can access both name and age
console.log(`name: ${this.name}, age: ${age}`);
};
}
let joe = new Person('Joe');
joe.greet();
// here we can access name but not age
WeakMap Bercakupan
WeakMap dapat digunakan untuk menghindari kinerja pendekatan dan memori memori sebelumnya. WeakMaps mengaitkan data dengan Objects (di sini, instance) sedemikian rupa sehingga hanya dapat diakses menggunakan WeakMap itu. Jadi, kami menggunakan metode variabel lingkup untuk membuat WeakMap pribadi, lalu gunakan WeakMap itu untuk mengambil data pribadi yang terkait dengannya this
. Ini lebih cepat daripada metode variabel cakupan karena semua instance Anda dapat membagikan WeakMap tunggal, jadi Anda tidak perlu membuat ulang metode hanya untuk membuatnya mengakses WeakMaps mereka sendiri.
Contoh:
let Person = (function () {
let privateProps = new WeakMap();
class Person {
constructor(name) {
this.name = name; // this is public
privateProps.set(this, {age: 20}); // this is private
}
greet() {
// Here we can access both name and age
console.log(`name: ${this.name}, age: ${privateProps.get(this).age}`);
}
}
return Person;
})();
let joe = new Person('Joe');
joe.greet();
// here we can access joe's name but not age
Contoh ini menggunakan Objek untuk menggunakan satu WeakMap untuk beberapa properti pribadi; Anda juga dapat menggunakan beberapa WeakMaps dan menggunakannya age.set(this, 20)
, atau menulis pembungkus kecil dan menggunakannya dengan cara lain, seperti privateProps.set(this, 'age', 0)
.
Privasi dari pendekatan ini secara teoritis dapat dilanggar dengan merusak WeakMap
objek global . Karena itu, semua JavaScript dapat dipatahkan oleh global yang hancur. Kode kami sudah dibangun dengan asumsi bahwa ini tidak terjadi.
(Metode ini juga bisa dilakukan Map
, tetapi WeakMap
lebih baik karena Map
akan membuat kebocoran memori kecuali Anda sangat berhati-hati, dan untuk tujuan ini keduanya tidak berbeda.)
Setengah Jawab: Simbol yang Dicakup
Simbol adalah jenis nilai primitif yang dapat berfungsi sebagai nama properti. Anda dapat menggunakan metode variabel cakupan untuk membuat Simbol pribadi, lalu menyimpan data pribadi di this[mySymbol]
.
Privasi metode ini dapat dilanggar menggunakan Object.getOwnPropertySymbols
, tetapi agak canggung untuk dilakukan.
Contoh:
let Person = (function () {
let ageKey = Symbol();
class Person {
constructor(name) {
this.name = name; // this is public
this[ageKey] = 20; // this is intended to be private
}
greet() {
// Here we can access both name and age
console.log(`name: ${this.name}, age: ${this[ageKey]}`);
}
}
return Person;
})();
let joe = new Person('Joe');
joe.greet();
// Here we can access joe's name and, with a little effort, age. ageKey is
// not in scope, but we can obtain it by listing all Symbol properties on
// joe with `Object.getOwnPropertySymbols(joe)`.
Half-Answer: Menggarisbawahi
Default yang lama, cukup gunakan properti publik dengan awalan garis bawah. Meskipun bukan merupakan properti pribadi dengan cara apa pun, konvensi ini cukup lazim sehingga ia melakukan pekerjaan yang baik dengan mengomunikasikan bahwa pembaca harus memperlakukan properti itu sebagai milik pribadi, yang sering kali menyelesaikan pekerjaannya. Sebagai gantinya selang ini, kami mendapatkan pendekatan yang lebih mudah dibaca, lebih mudah untuk mengetik, dan lebih cepat.
Contoh:
class Person {
constructor(name) {
this.name = name; // this is public
this._age = 20; // this is intended to be private
}
greet() {
// Here we can access both name and age
console.log(`name: ${this.name}, age: ${this._age}`);
}
}
let joe = new Person('Joe');
joe.greet();
// Here we can access both joe's name and age. But we know we aren't
// supposed to access his age, which just might stop us.
Kesimpulan
Pada ES2017, masih belum ada cara sempurna untuk melakukan properti pribadi. Berbagai pendekatan memiliki pro dan kontra. Variabel yang dicakup benar-benar pribadi; WeakMaps scoped sangat pribadi dan lebih praktis daripada variabel scoped; Simbol yang dicakup cukup pribadi dan praktis; garis bawah sering kali cukup pribadi dan sangat praktis.