115 votes

Pourquoi puis-je accéder aux membres privés de TypeScript alors que je ne devrais pas pouvoir le faire ?

J'étudie l'implémentation des membres privés en TypeScript, et je trouve cela un peu confus. Intellisense ne permet pas d'accéder aux membres privés, mais en JavaScript pur, tout est là. Cela me fait penser que TS n'implémente pas correctement les membres privés. Une idée ?

class Test{
  private member: any = "private member";
}
alert(new Test().member);

107voto

Guffa Points 308133

Tout comme pour la vérification de type, la confidentialité des membres n'est appliquée qu'au sein du compilateur.

Une propriété privée est mise en œuvre comme une propriété ordinaire, et le code extérieur à la classe n'est pas autorisé à y accéder.

Pour rendre quelque chose de vraiment privé à l'intérieur de la classe, il ne peut pas s'agir d'un membre de la classe, mais d'une variable locale créée dans la portée d'une fonction à l'intérieur du code qui crée l'objet. Cela signifie que vous ne pouvez pas y accéder comme à un membre de la classe, c'est-à-dire en utilisant la fonction this mot-clé.

39voto

Martin Points 582

JavaScript prend en charge les variables privées.

function MyClass() {
    var myPrivateVar = 3;

    this.doSomething = function() {
        return myPrivateVar++;        
    }
}

En TypeScript, cela s'exprimerait de la manière suivante :

class MyClass {

    doSomething: () => number;

    constructor() {
        var myPrivateVar = 3;

        this.doSomething = function () {
            return myPrivateVar++;
        }
    }
}

EDITAR

Cette approche ne doit être utilisée que SPARINGLY là où c'est absolument nécessaire. Par exemple, si vous avez besoin de mettre temporairement un mot de passe en cache.

L'utilisation de ce modèle (sans rapport avec Javascript ou Typescript) a un coût en termes de performances et ne doit être utilisée qu'en cas de nécessité absolue.

22voto

Depuis la sortie de TypeScript 3.8, vous pourrez déclarer des champs privés qui ne peuvent pas être accédés ou même détectés en dehors de la classe qui les contient. .

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.

Les champs privés commencent par # caractère

Veuillez noter que ces champs privés seront différents des champs marqués d'une étoile. private mot-clé

Réf. https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/

19voto

Sean Points 888

Cela fait partie de la conception de la langue apparemment... https://typescript.codeplex.com/discussions/397651

11voto

Ryan Thomas Points 85

Une fois que le soutien aux WeakMap est plus largement disponible, il existe une technique intéressante, détaillée dans l'exemple n°3. aquí .

Il autorise les données privées ET évite les coûts de performance de l'exemple de Jason Evans en permettant aux données d'être accessibles à partir de méthodes prototypes au lieu de méthodes d'instance uniquement.

La page MDN WeakMap mentionne que les navigateurs pris en charge sont Chrome 36, Firefox 6.0, IE 11, Opera 23 et 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)();
    }
  }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X