@ Loganfsmyth'in cevabını genişletmek için:
JavaScript'teki tek gerçek veri yine de kapsam dahilindeki değişkenlerdir. Herkese açık mülklerle aynı şekilde dahili olarak erişilen mülkler anlamında özel mülkleriniz olamaz, ancak özel verileri depolamak için kapsamlandırılmış değişkenleri kullanabilirsiniz.
Kapsamlı değişkenler
Buradaki yaklaşım, özel verileri saklamak için özel olan yapıcı işlevinin kapsamını kullanmaktır. Bu özel verilere erişme yöntemlerinin, yapıcı içinde de oluşturulması gerekir, yani bunları her örnekle yeniden oluşturuyorsunuz. Bu bir performans ve hafıza cezasıdır, ancak bazıları cezanın kabul edilebilir olduğuna inanmaktadır. Özel verilere her zamanki gibi prototipe eklenerek erişilmesi gerekmeyen yöntemler için ceza önlenebilir.
Misal:
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
Kapsamlı Zayıf Harita
WeakMap, önceki yaklaşımın performansını ve bellek cezasını önlemek için kullanılabilir. WeakMaps, verileri yalnızca bu WeakMap kullanılarak erişilebilecek şekilde Nesneler (burada, örnekler) ile ilişkilendirir. Bu nedenle, özel bir WeakMap oluşturmak için kapsamlandırılmış değişkenler yöntemini kullanırız, ardından bu WeakMap'i ile ilişkili özel verileri almak için kullanırız.this
. Bu, kapsamdaki değişkenler yönteminden daha hızlıdır, çünkü tüm örnekleriniz tek bir WeakMap'i paylaşabilir, bu nedenle yalnızca kendi WeakMap'lerine erişmelerini sağlamak için yöntemleri yeniden oluşturmanız gerekmez.
Misal:
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
Bu örnek, birden çok özel özellik için bir WeakMap kullanmak için bir Nesne kullanır; ayrıca birden fazla WeakMaps kullanabilir veage.set(this, 20)
veya küçük bir sarmalayıcı yazıp başka bir şekilde kullanabilirsiniz privateProps.set(this, 'age', 0)
.
Bu yaklaşımın gizliliği teorik olarak küresel WeakMap
nesneye . Bununla birlikte, tüm JavaScript karışık küreseller tarafından kırılabilir. Kodumuz zaten bunun olmadığı varsayımına dayanmaktadır.
(Bu yöntem de yapılabilir Map
, ancak WeakMap
daha iyidir, çünkü Map
çok dikkatli olmadığınız sürece bellek sızıntıları yaratacaktır ve bu amaç için ikisi farklı değildir.)
Yarı Cevap: Kapsamlı Semboller
Sembol, bir özellik adı olarak işlev görebilen bir tür ilkel değerdir. Özel bir Sembol oluşturmak için kapsamlı değişken yöntemini kullanabilir, ardından özel verileri adresinde depolayabilirsiniz this[mySymbol]
.
Bu yöntemin gizliliği kullanılarak ihlal edilebilir Object.getOwnPropertySymbols
, ancak yapılması biraz gariptir.
Misal:
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)`.
Yarı Cevap: Alt Çizgiler
Eski varsayılan, yalnızca alt çizgi önekine sahip bir ortak mülk kullanın. Herhangi bir şekilde özel bir mülk olmamasına rağmen, bu sözleşme, okuyucuların mülkiyeti özel olarak ele alması gerektiğini bildiren iyi bir iş çıkardığı kadar yaygındır ve bu da genellikle işi yapar. Bu gecikme karşılığında, okunması daha kolay, yazması daha kolay ve daha hızlı bir yaklaşım elde ediyoruz.
Misal:
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.
Sonuç
ES2017'den itibaren, özel mülkler yapmanın mükemmel bir yolu yoktur. Çeşitli yaklaşımların artıları ve eksileri vardır. Kapsamlı değişkenler gerçekten özeldir; Kapsamlı WeakMaps kapsam kapsamındaki değişkenlerden çok özel ve daha pratiktir; Kapsamlı Semboller oldukça özel ve oldukça pratiktir; alt çizgiler genellikle yeterince özel ve çok pratiktir.