JavaScript usa herança prototípica: cada objeto herda propriedades e métodos de seu objeto protótipo.
A classe tradicional como o modelo para criar objetos, usado em linguagens como Java ou Swift, não existe em JavaScript. A herança prototípica lida apenas com objetos.
a herança prototípica pode emular a herança de classe clássica. Para trazer as classes tradicionais para JavaScript, o padrão ES2015 introduz o id
sintaxe: um açúcar sintático sobre a herança prototípica.,
esta publicação familiariza-o com classes de JavaScript: como definir uma classe, inicializar a instância, definir campos e métodos, compreender os campos privados e públicos, compreender os campos e métodos estáticos.
1. Definição: classe de palavra-chave
A palavra-chave especial class
define uma classe em JavaScript:
class User { // The body of class}
O código acima define uma classe User
. The curly braces { }
delimit the class body. Note que esta sintaxe é chamada de declaração de classe.,
Você não é obrigado a indicar o nome da classe. Ao usar uma expressão de classe, poderá atribuir a classe a uma variável:
const UserClass = class { // The body of class};
pode facilmente exportar uma classe como parte de um módulo ES2015. Eis a sintaxe para uma exportação padrão:
export default class User { // The body of class}
E um chamado de exportação:
export class User { // The body of class}
A classe torna-se útil quando você cria uma instância da classe. Uma instância é um objeto que contém dados e comportamento descritos pela classe.,
new
operador instancia a classe em JavaScript: instance = new Class()
.
Por exemplo, você pode instanciar o User
classe usando o new
operador:
const myUser = new User();
new User()
cria uma instância de User
classe. 2. Inicialização: construtor ()
constructor(param1, param2, ...)
é um método especial no corpo de uma classe que inicia a instância., Esse é o lugar onde você define os valores iniciais para os campos, ou faz qualquer tipo de configuração de objeto.
No exemplo a seguir o construtor define o valor inicial do campo name
:
class User { constructor(name) { this.name = name; }}
User
‘s construtor tem um parâmetro name
o que é usado para definir o valor inicial do campo this.name
.
no interior do construtor this
o valor é igual à instância recentemente criada.,
Os argumentos utilizados para instanciar a classe tornam-se os parâmetros do construtor:
class User { constructor(name) { name; // => 'Jon Snow' this.name = name; }}const user = new User('Jon Snow');
name
parâmetro dentro do construtor tem o valor 'Jon Snow'
.
Se você não definir um construtor para a classe, um padrão é criado. O construtor padrão é uma função vazia, que não modifica a instância.
ao mesmo tempo, uma classe JavaScript pode ter até um construtor.
3. Os campos
são variáveis que contêm informação., Campos pode ser ligado a 2 entidades:
- os Campos em a instância da classe
- os Campos na classe em si (aka estático)
Os campos também possuem 2 níveis de acessibilidade:
- Público: o campo é acessível em qualquer lugar
- Privado: o campo é acessível apenas dentro do corpo da classe
3.1 instância Pública de campos
Vamos olhar novamente para o antigo trecho de código:
class User { constructor(name) { this.name = name; }}
A expressão this.name = name
cria uma instância do campo name
e atribui a ele um valor inicial.,
mais Tarde, você pode acessar o name
campo utilizando um assessor de propriedade:
const user = new User('Jon Snow');user.name; // => 'Jon Snow'
name
é um campo público, porque você pode acessá-lo fora de User
corpo da classe.
Quando os campos são criados implicitamente dentro do construtor, como no cenário anterior, pode ser difícil compreender a lista de campos. Tens de decifrá-los do Código do construtor.
uma melhor abordagem é declarar explicitamente os campos de classe., Não importa o que o construtor faz, a instância sempre tem o mesmo conjunto de campos.
a proposta de campos de classe permite definir os campos dentro do corpo da classe. Além disso, você pode indicar o valor inicial de imediato:
class SomeClass { field1; field2 = 'Initial value'; // ...}
Vamos modificar o User
classe e declarar um campo público name
:
class User { name; constructor(name) { this.name = name; }}const user = new User('Jon Snow');user.name; // => 'Jon Snow'
name;
dentro do corpo da classe declara um campo público name
.,
os campos públicos declarados dessa forma são expressivos: uma rápida olhada nas declarações de Campos é suficiente para entender a estrutura de dados da classe.
além disso, o campo de classe pode ser inicializado imediatamente na declaração.
class User { name = 'Unknown'; constructor() { // No initialization }}const user = new User();user.name; // => 'Unknown'
name = 'Unknown'
dentro do corpo da classe declara um campo name
e o inicializa com o valor de 'Unknown'
.
não há restrição no acesso ou atualização dos campos públicos., Você pode ler e atribuir valores a campos públicos dentro do construtor, métodos e fora da classe.
3.2 campos de instância privada
encapsulação é um conceito importante que lhe permite esconder os detalhes internos de uma classe. Alguém que usa uma classe encapsulada depende apenas da interface pública que a classe fornece, e não se conecta com os detalhes de implementação da classe. Classes
organizadas com encapsulação em mente são mais fáceis de atualizar quando os detalhes da implementação mudam.,
uma boa maneira de esconder dados internos de um objeto é usar os campos privados. Estes são os campos que podem ser lidos e alterados apenas dentro da classe A que pertencem. O mundo exterior da classe não pode mudar diretamente os campos privados.
os campos privados são acessíveis apenas dentro do corpo da classe.
Prefixo o nome do campo com o símbolo especial #
para torná-lo privado, e.g. #myField
., O prefixo #
deve ser mantido sempre que trabalhar com o campo: declare-o, Leia-o ou modifique-o.
vamos certificar-nos de que o campo #name
pode ser definido uma vez na inicialização da instância:
#name
é um campo privado. Você pode acessar e modificar #name
dentro do corpo do User
. The method getName()
(more about methods in next section) can access the private field #name
.,
Mas se você tentar acessar o campo private #name
fora User
corpo da classe, um erro de sintaxe é lançada: SyntaxError: Private field '#name' must be declared in an enclosing class
.
3.3 campos estáticos públicos
Pode também definir campos na própria classe: os campos estáticos. Estes são úteis para definir constantes de classe ou armazenar informações específicas para a classe.
Para criar campos estáticos em uma classe JavaScript, use a palavra-chave especial static
seguido do nome do campo: static myStaticField
.,
Let’s add a new field type
that indicates the user type: admin or regular. Os campos estáticos TYPE_ADMIN
e TYPE_REGULAR
são práticas constantes para diferenciar os tipos de utilizador:
static TYPE_ADMIN
e static TYPE_REGULAR
definir variáveis estáticas dentro de User
classe. Para acessar os campos estáticos, você tem que usar a classe seguida pelo nome do campo: User.TYPE_ADMIN
e User.TYPE_REGULAR
.
3.,4 campos estáticos privados
às vezes mesmo os campos estáticos são um detalhe de implementação que você gostaria de esconder. A este respeito, você pode tornar os campos estáticos privados.
Para fazer o campo estático privado, prefixo o nome do campo com #
símbolo especial: static #myPrivateStaticField
.
digamos que você gostaria de limitar o número de instâncias da classe User
., Para ocultar os detalhes sobre as instâncias limites, você pode criar o privado campos estáticos:
O campo estático User.#MAX_INSTANCES
define o número máximo de permissão de instâncias, enquanto User.#instances
campo estático conta o número real de casos.
estes campos estáticos privados são acessíveis apenas dentro da classe User
. Nada do mundo externo pode interferir com o mecanismo de limites: esse é o benefício da encapsulação. 4. Métodos
os campos contêm dados., Mas a capacidade de modificar dados é realizada por funções especiais que fazem parte da classe: os métodos.
As classes JavaScript suportam métodos estáticos e instância.
4.1 Instance methods
Instance methods can access and modify instance data. Métodos de instância podem chamar outros métodos de instância, bem como qualquer método estático.,
Por exemplo, vamos definir um método de getName()
que retorna o nome User
categoria:
Em um método de classe, bem como no construtor, this
valor igual a instância da classe. Use this
para acessar dados de instância: this.field
, ou mesmo chamar outros métodos: this.method()
.,
Vamos adicionar um novo método de nameContains(str)
que tem um parâmetro e chama outro método:
nameContains(str) { ... }
é um método de User
classe que aceita um parâmetro str
. Mais do que isso, ele executa outro método da instância this.getName()
para obter o nome do Usuário. um método também pode ser privado. Para tornar o método privado prefixo seu nome com #
.
Let’s make getName()
method private:
#getName()
is a private method., Inside the method nameContains(str)
you call a private method such way: this.#getName()
.
sendo privado, #getName()
não pode ser chamado fora deUser
corpo da classe.
4.2 Getters and setters
o getter e o setter imitam o campo regular, mas com mais controlo sobre como o campo é acedido e alterado.
o getter é executado em uma tentativa de obter o valor do campo, enquanto setter em uma tentativa de definir um valor.,
certifique-se de que o name
propriedade User
não pode ser vazio, vamos resumir o campo private #nameValue
em um getter e setter:
get name() {...}
getter é executado quando você acessar o valor do campo: user.name
.
4.3 métodos estáticos
os métodos estáticos são funções ligadas directamente à classe. Eles mantêm a lógica relacionada à classe, ao invés da instância da classe.,
para criar um método estático use a palavra-chave especial static
seguido por uma sintaxe de método regular:static myStaticMethod() { ... }
.
Ao trabalhar com métodos estáticos, existem 2 regras simples para lembrar:
- Um método estático pode acessar os campos estáticos
- Um método estático não pode acessar campos de instância.
Por exemplo, vamos criar um método estático que detecte se um usuário com um nome específico já foi tomado.,
isNameTaken()
é um método estático que usa o campo privado estáticoUser.#takenNames
para verificar os nomes usados.
5. Inheritance: extends
the classes in JavaScript support single inheritance using the extends
keyword.
a expressão class Child extends Parent { }
Child
classe herda Parent
o construtor, campos e métodos.
Por exemplo, vamos criar uma nova classe filha ContentWriter
que estende a classe pai User
.,
ContentWriter
herda o User
o construtor, o método getName()
e o campo name
. As well, the ContentWriter
class declares a new field posts
.
Note que os membros particulares de uma classe pai não são herdados pela classe criança.
5.1 construtor-mãe: super() no construtor ()
Se quiser ligar para o construtor-pai numa classe de crianças, terá de usar a função super()
função especial disponível no construtor de crianças.,
Por exemplo, vamos fazer com que o ContentWriter
chamada de construtor principal construtor de User
, bem como inicializar os postos de campo:
super(name)
dentro de uma classe filha ContentWriter
executa o construtor da classe pai User
.
Note que no interior da criança construtor você deve executar super()
antes de usar this
palavra-chave. Chamando super()
garante que o construtor-mãe inicializa a instância.,
class Child extends Parent { constructor(value1, value2) { // Does not work! this.prop2 = value2; super(value1); }}
5.2 instância Principal: super nos métodos
Se você deseja acessar o principal método dentro de uma criança método, você pode usar o atalho especial super
.
getName()
da criança de classe ContentWriter
acessa o método super.getName()
diretamente da classe pai User
.
Esta característica é chamada de método superior.
Note que você pode usar super
com métodos estáticos também, para acessar os métodos estáticos do Pai.
6., Object type checking: instanceof
object instanceof Class
is the operator that determines if object
is an instance of Class
.
Let’s see instanceof
operator in action:
user
is an instance of User
class, user instanceof User
evaluates to true
.
The empty object {}
is not an instance of User
, correspondingly obj instanceof User
is false
.,
instanceof
é polimórfico: o operador detecta uma criança como uma instância da classe pai.
writer
é uma instância da classe filha ContentWriter
. O operador avalia a true
.
Ao mesmo tempo ContentWriter
é uma criança de classe de User
. So writer instanceof User
evaluates to true
as well. e se quiser determinar a classe exacta da instância?, Você pode usar a propriedadeconstructor
e comparar diretamente com a classe:
writer.constructor === ContentWriter; // => truewriter.constructor === User; // => false
7. Classes e protótipos
devo dizer que a sintaxe de classe em JavaScript faz um grande trabalho para abstrair da herança prototípica. To describe theclass
syntax I haven’t even used the term prototype.
mas as classes são construídas em cima da herança prototípica. Cada classe é uma função, e cria uma instância quando invocada como um construtor.
os dois excertos de código seguintes são equivalentes.,
a versão da classe:
a versão usando protótipo:
A sintaxe da classe é muito mais fácil de trabalhar se você estiver familiarizado com o mecanismo de herança clássico de linguagens Java ou Swift.
de qualquer forma, mesmo que você use a sintaxe de classe em JavaScript, eu recomendo que você tenha uma boa compreensão da herança prototípica.
8. Características da classe disponibilidade
as características da classe apresentadas neste post estão espalhadas pelo ES2015 e propostas na fase 3.,
No final de 2019, os recursos de classe são divididas entre:
- Pública e privada, campos de instância são parte de campos Classe da proposta
- Privada métodos de instância e os acessores são parte da Classe de métodos privados proposta
- Público e privado campos estáticos e privadas métodos estáticos são parte da Classe estática apresenta proposta
- O resto é parte do ES2015 padrão.
9. Conclusion
classes JavaScript inicializam instâncias com Construtores, definem campos e métodos., Você pode anexar campos e métodos mesmo na própria classe usando a palavra-chave static
.
herança é alcançada usando extends
palavra-chave: você pode facilmente criar uma classe de filhos a partir de um pai. super
palavra-chave é usada para acessar a classe-mãe a partir de uma classe-criança.
para tirar partido da encapsulação, torne os campos e métodos privados para esconder os detalhes internos das suas classes. Os nomes dos Campos e métodos privados devem começar com #
.,
As classes em JavaScript tornam-se cada vez mais convenientes de usar.
O que você acha de usar #
para prefixar propriedades privadas?