javascript - Zašto mogu pristupiti privatnim članovima TypeScripta kada ne bih smio?
Proučavam implementaciju privatnih članova u TypeScriptu i smatram to malo zbunjujućim. Intellisense ne dopušta pristup privatnom članu, ali u čistom JavaScriptu sve je dostupno. To me navodi na pomisao da TypeScript ne implementira privatne članove ispravno. Imate li kakvih mišljenja?
class Test{
private member: any = "private member";
}
alert(new Test().member);
Odgovor #1
Baš kao i kod provjere tipa, privatnost članova se provodi samo unutar kompajlera.
Privatno vlasništvo implementirano je kao uobičajena svojina, i kod izvan klase ne smije joj pristupati.
Da bi nešto bilo zaista privatno unutar klase, ne može biti član klase, to bi bila lokalna varijabla stvorena unutar opsega funkcije u kodu koji stvara objekt. To bi značilo da joj ne možete pristupiti kao članu klase, tj. koristeći ključnu riječ this.
Odgovor #2
JavaScript podržava privatne varijable.
function MyClass() {
var myPrivateVar = 3;
this.doSomething = function() {
return myPrivateVar++;
}
}
U TypeScriptu bi se to izrazilo ovako:
class MyClass {
doSomething: () => number;
constructor() {
var myPrivateVar = 3;
this.doSomething = function () {
return myPrivateVar++;
}
}
}
UREDI
Ovaj pristup treba koristiti ŠTEDLJIVO samo tamo gdje je apsolutno potreban. Na primjer, ako trebate privremeno pohraniti lozinku.
Korištenje ovog obrasca ima troškove u pogledu performansi (bez obzira na Javascript ili Typescript) i trebalo bi ga koristiti samo kada je apsolutno potrebno.
Odgovor #3
Budući da će TypeScript 3.8 biti objavljen, moći ćete deklarirati privatno polje koje se ne može pristupiti niti otkriti izvan klase koja ga sadrži.
class Person {
#name: string
constructor(name: string) {
this.#name = name;
}
greet() {
console.log(`Hello, my name is ${this.#name}!`);
}
}
let jeremy = new Person("Jeremy Bearimy");
jeremy.#name
// ~~~~~
// Property '#name' is not accessible outside class 'Person'
// because it has a private identifier.
Privatna polja počinju znakom #
Imajte na umu da će ova privatna polja biti nešto drugačije od polja označenih ključnom riječi private
Ref. https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/
Odgovor #4
Kada podrška za WeakMap bude šire dostupna, postoji zanimljiva tehnika detaljno objašnjena u primjeru #3 ovdje.
Omogućuje privatne podatke I izbjegava troškove performansi iz primjera Jasona Evansa dopuštajući da podaci budu dostupni iz metoda prototipa umjesto samo iz metoda instance.
Povezana MDN stranica o WeakMap prikazuje podršku preglednika na Chrome 36, Firefox 6.0, IE 11, Opera 23 i Safari 7.1.
let _counter = new WeakMap();
let _action = new WeakMap();
class Countdown {
constructor(counter, action) {
_counter.set(this, counter);
_action.set(this, action);
}
decrement() {
let counter = _counter.get(this);
if (counter < 1) return;
counter--;
_counter.set(this, counter);
if (counter === 0) {
_action.get(this)();
}
}
}
