Casos de uso: #
-campos privados
Prefacio:
Tiempo de compilación y privacidad en tiempo de ejecución
#
Privadas campos proporcionan el tiempo de compilación y privacidad en tiempo de ejecución, lo que no es "piratear". Es un mecanismo para evitar el acceso a un miembro desde fuera del cuerpo de la clase de manera directa .
class A {
#a: number;
constructor(a: number) {
this.#a = a;
}
}
let foo: A = new A(42);
foo.#a; // error, not allowed outside class bodies
(foo as any).#bar; // still nope.
Herencia de clase segura
#
-los campos privados obtienen un alcance único. Las jerarquías de clase se pueden implementar sin sobrescribir accidentalmente propiedades privadas con nombres iguales.
class A {
#a = "a";
fnA() { return this.#a; }
}
class B extends A {
#a = "b";
fnB() { return this.#a; }
}
const b = new B();
b.fnA(); // returns "a" ; unique property #a in A is still retained
b.fnB(); // returns "b"
Afortunadamente, el compilador de TS emite un error cuando las private
propiedades están en peligro de sobrescribirse (consulte este ejemplo ). Pero debido a la naturaleza de una función de tiempo de compilación, todo es posible en tiempo de ejecución, dado que los errores de compilación son ignorados y / o se utiliza el código JS emitido.
Bibliotecas externas
Los autores de la biblioteca pueden refactorizar #
identificadores privados sin causar un cambio importante para los clientes. Los usuarios de la biblioteca en el otro lado están protegidos de acceder a los campos internos.
La API de JS omite #
campos privados
Las funciones y métodos JS incorporados ignoran los #
campos privados. Esto puede dar como resultado una selección de propiedades más predecible en tiempo de ejecución. Ejemplos: Object.keys
, Object.entries
, JSON.stringify
, for..in
bucle y otros ( ejemplo de código ; véase también de Matt Bierner respuesta ):
class Foo {
#bar = 42;
baz = "huhu";
}
Object.keys(new Foo()); // [ "baz" ]
Casos de uso: private
palabra clave
Prefacio:
Acceso a la clase interna API y estado (privacidad solo en tiempo de compilación)
private
Los miembros de una clase son propiedades convencionales en tiempo de ejecución. Podemos utilizar esta flexibilidad para acceder a la API interna de la clase o al estado desde el exterior. Para satisfacer las comprobaciones del compilador, mecanismos como aserciones de tipo, acceso a propiedades dinámicas o@ts-ignore
se pueden usar entre otros.
Ejemplo con aserción de tipo ( as
/ <>
) y any
asignación de variable con tipo :
class A {
constructor(private a: number) { }
}
const a = new A(10);
a.a; // TS compile error
(a as any).a; // works
const casted: any = a; casted.a // works
TS incluso permite el acceso a propiedades dinámicas de un private
miembro con una escotilla de escape :
class C {
private foo = 10;
}
const res = new C()["foo"]; // 10, res has type number
¿Dónde puede tener sentido el acceso privado? (1) pruebas unitarias, (2) situaciones de depuración / registro u (3) otros escenarios de casos avanzados con clases internas del proyecto (lista abierta).
El acceso a las variables internas es un poco contradictorio; de lo contrario, no las habría hecho private
en primer lugar. Para dar un ejemplo, se supone que las pruebas unitarias son cuadros negros / grises con campos privados ocultos como detalles de implementación. Sin embargo, en la práctica, puede haber enfoques válidos de un caso a otro.
Disponible en todos los entornos ES
Los private
modificadores TS se pueden usar con todos los objetivos ES. #
-los campos privados solo están disponibles para target
ES2015
/ ES6
o superior. En ES6 +, WeakMap
se usa internamente como implementación de nivel inferior (ver aquí ). Los #
campos nativos- privados actualmente requierentarget
esnext
.
Consistencia y compatibilidad
Los equipos pueden usar pautas de codificación y reglas de interfaz para imponer el uso private
como el único modificador de acceso. Esta restricción puede ayudar con la coherencia y evitar confusiones con la #
notación de campo privado de una manera compatible con versiones anteriores.
Si es necesario, las propiedades de los parámetros (abreviatura de asignación de constructor) son un show stopper. Solo se pueden usar con private
palabras clave y todavía no hay planes para implementarlas para#
campos privados.
Otras razones
private
podría proporcionar un mejor rendimiento en tiempo de ejecución en algunos casos de reducción de nivel (ver aquí ).
- No hay métodos de clase privada disponibles en TS hasta ahora.
- Algunas personas
private
prefieren la notación de palabras clave 😊.
Nota sobre ambos
Ambos enfoques crean algún tipo de tipo nominal o de marca en tiempo de compilación.
class A1 { private a = 0; }
class A2 { private a = 42; }
const a: A1 = new A2();
// error: "separate declarations of a private property 'a'"
// same with hard private fields
Además, ambos permiten el acceso entre instancias: una instancia de clase A
puede acceder a miembros privados de otras A
instancias:
class A {
private a = 0;
method(arg: A) {
console.log(arg.a); // works
}
}
Fuentes