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)();
    }
  }
}

Povezani članci