Geschiedenis van de vraag
In TypeScript werden privé velden aanvankelijk geïntroduceerd met de modifier private, en sinds ECMAScript 2021 ondersteunt JavaScript echte privé velden met behulp van het symbool #. Het belangrijkste doel is het encapsuleren van gegevens, zodat de interne details van de klasse worden beschermd tegen externe toegang.
Probleem
De private modifier in TypeScript zorgt alleen voor privacy tijdens de compileertijd, maar in de gecompileerde JavaScript blijven deze velden toegankelijk via directe toegang tot de objecteigenschappen. Dit kan leiden tot onbedoelde wijzigingen van de objectstatus. ES Private Fields (#) zijn volledig niet toegankelijk buiten de klasse, zelfs niet op runtime niveau in JS, wat echte gegevensbescherming garandeert.
Oplossing
TypeScript ondersteunt beide benaderingen. Bij het kiezen tussen hen moet u rekening houden met de gewenste mate van bescherming en compatibiliteitsbeperkingen met JS-versies.
Voorbeeldcode:
class Voorbeeld { private verborgen: number; #echtVerbogen: string; constructor() { this.verborgen = 42; this.#echtVerbogen = 'geheim'; } getVerborgen() { return this.verborgen; } getEchtVerbogen() { return this.#echtVerbogen; } } const x = new Voorbeeld(); // x.verborgen — fout in TS, maar werkt via x['verborgen'] in JS // x.#echtVerbogen — syntaxisfout zelfs in JS
Belangrijke kenmerken:
private garandeert privacy alleen tijdens de compileertijd van TypeScript#field biedt echte privacy op het niveau van de uitvoering van JavaScript# vereist ondersteuning voor moderne JS (ES2021+)Kan men toegang krijgen tot een privé veld van een TypeScript klasse via directe toegang in JS?
Ja, dat kan, omdat de privacy alleen tijdens de compileertijd wordt gerealiseerd. In de originele JS zal het veld een gewone eigenschap van het object zijn. Bijvoorbeeld:
class A { private x = 1; } const a = new A(); console.log((a as any)["x"]); // 1
Kan men privé velden met # gebruiken in interfaces of deze beschrijven met type?
Nee, #private velden zijn slechts een deel van de implementatie van de klasse en kunnen niet worden beschreven in interfaces of types, of buiten de klasse zelf worden gebruikt. Interfaces beschrijven alleen openbare leden.
Kan men privé velden die met # zijn verklaard, overerven?
Nee, dergelijke velden zijn helemaal niet toegankelijk voor afgeleide klassen. Alleen de eigen klasse heeft toegang tot hen:
class Ouders { #foo = 123; } class Kind extends Ouders { // this.#foo = 444; // Fout }
private voor het beschermen van cruciale gegevens — leidt tot kwetsbaarheid bij directe toegangIn een project voor het opslaan van wachtwoorden in de User klasse werd het veld private password gebruikt. Een van de ontwikkelaars kreeg per ongeluk toegang via user['password'] voor debugging, en het veld bleek te zijn gewijzigd door een extern module.
Voordelen:
Nadelen:
Een ontwikkelaar gebruikt het ES-private veld #password. Nu worden pogingen om toegang te krijgen tot het veld via indexing of in afgeleiden klassen niet toegestaan, gegevensbeveiliging is gewaarborgd, zelfs bij het gebruik van externe bibliotheken en tools.
Voordelen:
Nadelen: