Casos de uso: #
-private fields
Prefácio:
Tempo de compilação e privacidade de tempo de execução
#
campos -Privadas fornecer tempo de compilação e privacidade de tempo de execução, o que não é "hackable". É um mecanismo para impedir o acesso a um membro de fora do corpo da classe de maneira direta .
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.
Herança de classe segura
#
Os campos privados recebem um escopo exclusivo. As hierarquias de classe podem ser implementadas sem substituições acidentais de propriedades particulares com nomes iguais.
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"
Felizmente, o compilador TS emite um erro quando as private
propriedades correm o risco de serem substituídas (consulte este exemplo ). Porém, devido à natureza de um recurso de tempo de compilação, tudo ainda é possível no tempo de execução, dado que os erros de compilação são ignorados e / ou é emitido o código JS utilizado.
Bibliotecas externas
Os autores da biblioteca podem refatorar #
identificadores privados sem causar uma alteração de interrupção para os clientes. Os usuários da biblioteca do outro lado estão protegidos contra o acesso a campos internos.
A API JS omite os #
campos -private
As funções e métodos JS internos ignoram os #
campos -private. Isso pode resultar em uma seleção de propriedade mais previsível em tempo de execução. Exemplos: Object.keys
, Object.entries
, JSON.stringify
, for..in
loop e outros ( exemplo de código ; ver também de Matt Bierner resposta ):
class Foo {
#bar = 42;
baz = "huhu";
}
Object.keys(new Foo()); // [ "baz" ]
Casos de uso: private
keyword
Prefácio:
Acesso à API e ao estado da classe interna (privacidade apenas em tempo de compilação)
private
membros de uma classe são propriedades convencionais em tempo de execução. Podemos usar essa flexibilidade para acessar a API ou o estado interno da classe de fora. Para satisfazer as verificações do compilador, mecanismos como asserções de tipo, acesso dinâmico à propriedade ou @ts-ignore
podem ser usados entre outros.
Exemplo com asserção de tipo ( as
/ <>
) e any
atribuição de variável digitada:
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
O TS ainda permite o acesso dinâmico à propriedade de um private
membro com uma saída de escape :
class C {
private foo = 10;
}
const res = new C()["foo"]; // 10, res has type number
Onde o acesso privado pode fazer sentido? (1) testes de unidade, (2) situações de depuração / registro em log ou (3) outros cenários de casos avançados com classes internas do projeto (lista aberta).
O acesso a variáveis internas é um pouco contraditório - caso contrário, você não as teria criado private
em primeiro lugar. Para dar um exemplo, os testes de unidade devem ser caixas pretas / cinza com campos particulares ocultos como detalhes da implementação. Na prática, porém, pode haver abordagens válidas de caso para caso.
Disponível em todos os ambientes ES
private
Modificadores de TS podem ser usados com todos os destinos de ES. #
Os campos privados estão disponíveis apenas para target
ES2015
/ ES6
ou superiores. No ES6 +, WeakMap
é usado internamente como implementação de nível inferior (veja aqui ). #
Atualmente, os campos nativos particulares requerem target
esnext
.
Consistência e compatibilidade
As equipes podem usar diretrizes de codificação e regras de linter para impor o uso private
como o único modificador de acesso. Essa restrição pode ajudar na consistência e evitar confusão com a #
notação de campo -private de uma maneira compatível com versões anteriores.
Se necessário, as propriedades dos parâmetros (abreviação de atribuição do construtor) são um limitador de exibição. Eles podem ser usados apenas com a private
palavra - chave e ainda não há planos para implementá-los em #
campos privados.
Outras razões
private
pode fornecer melhor desempenho em tempo de execução em alguns casos de nível inferior (veja aqui ).
- Até o momento, não há métodos rígidos de classe privada disponíveis no TS.
- Algumas pessoas gostam mais da
private
notação de palavras - chave 😊.
Nota sobre ambos
Ambas as abordagens criam algum tipo de tipo nominal ou de marca no momento da compilação.
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
Além disso, ambos permitem acesso entre instâncias: uma instância da classe A
pode acessar membros particulares de outras A
instâncias:
class A {
private a = 0;
method(arg: A) {
console.log(arg.a); // works
}
}
Fontes