Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 48 additions & 48 deletions 1-js/07-object-properties/02-property-accessors/article.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@

# Property getters and setters
# Getters e setters de propriedades

There are two kinds of object properties.
Existem dois tipos de propriedades de objeto.

The first kind is *data properties*. We already know how to work with them. All properties that we've been using until now were data properties.
O primeiro tipo são as *propriedades de dados*. Já sabemos como trabalhar com elas. Todas as propriedades que usamos até agora eram propriedades de dados.

The second type of property is something new. It's an *accessor property*. They are essentially functions that execute on getting and setting a value, but look like regular properties to an external code.
O segundo tipo de propriedade é algo novo. É uma *propriedade de acesso*. Elas são, essencialmente, funções que executam ao obter e definir um valor, mas parecem propriedades normais para um código externo.

## Getters and setters
## Getters e setters

Accessor properties are represented by "getter" and "setter" methods. In an object literal they are denoted by `get` and `set`:
Propriedades de acesso são representadas por métodos "getter" e "setter". Num objeto literal, eles são indicados por `get` e `set`:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Object literal" é um literal de objeto (a sintaxe {...}); "objeto literal" lê como "um objeto que é literal". Sugestão:

Suggested change
Propriedades de acesso são representadas por métodos "getter" e "setter". Num objeto literal, eles são indicados por `get` e `set`:
Propriedades de acesso são representadas por métodos "getter" e "setter". Em um literal de objeto, eles são indicados por `get` e `set`:


```js
let obj = {
*!*get propName()*/!* {
// getter, the code executed on getting obj.propName
// getter, o código executado ao obter obj.propName
},

*!*set propName(value)*/!* {
// setter, the code executed on setting obj.propName = value
// setter, o código executado ao definir obj.propName = value
}
};
```

The getter works when `obj.propName` is read, the setter -- when it is assigned.
O getter funciona quando `obj.propName` é lido, o setter -- quando é atribuído.

For instance, we have a `user` object with `name` and `surname`:
Por exemplo, temos um objeto `user` com `name` e `surname`:

```js
let user = {
Expand All @@ -34,7 +34,7 @@ let user = {
};
```

Now we want to add a `fullName` property, that should be `"John Smith"`. Of course, we don't want to copy-paste existing information, so we can implement it as an accessor:
Agora queremos adicionar uma propriedade `fullName`, que deve ser `"John Smith"`. Claro, não queremos copiar e colar informações já existentes, então podemos implementá-la como um acessor:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminologia inconsistente: a seção introduz o termo propriedade de acesso (linha 8) e usa-o nas linhas 56, 101 e 103, mas aqui e nas linhas 112, 137 e 188 aparece "acessor"/"acessores". Sugiro escolher um termo e usá-lo no artigo inteiro, para o leitor não achar que são conceitos diferentes.


```js run
let user = {
Expand All @@ -53,9 +53,9 @@ alert(user.fullName); // John Smith
*/!*
```

From the outside, an accessor property looks like a regular one. That's the idea of accessor properties. We don't *call* `user.fullName` as a function, we *read* it normally: the getter runs behind the scenes.
De fora, uma propriedade de acesso parece uma propriedade normal. Essa é a ideia das propriedades de acesso. Nós não *chamamos* `user.fullName` como uma função, nós a *lemos* normalmente: o getter roda nos bastidores.

As of now, `fullName` has only a getter. If we attempt to assign `user.fullName=`, there will be an error:
Por enquanto, `fullName` só tem um getter. Se tentarmos atribuir `user.fullName=`, vai haver um erro:

```js run
let user = {
Expand All @@ -65,11 +65,11 @@ let user = {
};

*!*
user.fullName = "Test"; // Error (property has only a getter)
user.fullName = "Test"; // Erro (a propriedade só tem um getter)
*/!*
```

Let's fix it by adding a setter for `user.fullName`:
Vamos corrigir isso adicionando um setter para `user.fullName`:

```js run
let user = {
Expand All @@ -87,29 +87,29 @@ let user = {
*/!*
};

// set fullName is executed with the given value.
// set fullName é executado com o valor dado.
user.fullName = "Alice Cooper";

alert(user.name); // Alice
alert(user.surname); // Cooper
```

As the result, we have a "virtual" property `fullName`. It is readable and writable.
Como resultado, temos uma propriedade "virtual" `fullName`. Ela é legível e gravável.

## Accessor descriptors
## Descritores de acesso

Descriptors for accessor properties are different from those for data properties.
Os descritores de propriedades de acesso são diferentes dos de propriedades de dados.

For accessor properties, there is no `value` or `writable`, but instead there are `get` and `set` functions.
Para propriedades de acesso, não existe `value` ou `writable`, mas, em vez disso, existem as funções `get` e `set`.

That is, an accessor descriptor may have:
Ou seja, um descritor de acesso pode ter:

- **`get`** -- a function without arguments, that works when a property is read,
- **`set`** -- a function with one argument, that is called when the property is set,
- **`enumerable`** -- same as for data properties,
- **`configurable`** -- same as for data properties.
- **`get`** -- uma função sem argumentos, que funciona quando uma propriedade é lida,
- **`set`** -- uma função com um argumento, que é chamada quando a propriedade é definida,
- **`enumerable`** -- igual às propriedades de dados,
- **`configurable`** -- igual às propriedades de dados.

For instance, to create an accessor `fullName` with `defineProperty`, we can pass a descriptor with `get` and `set`:
Por exemplo, para criar um acessor `fullName` com `defineProperty`, podemos passar um descritor com `get` e `set`:

```js run
let user = {
Expand All @@ -134,13 +134,13 @@ alert(user.fullName); // John Smith
for(let key in user) alert(key); // name, surname
```

Please note that a property can be either an accessor (has `get/set` methods) or a data property (has a `value`), not both.
Observe que uma propriedade pode ser um acessor (tem métodos `get/set`) ou uma propriedade de dados (tem um `value`), mas não as duas coisas.

If we try to supply both `get` and `value` in the same descriptor, there will be an error:
Se tentarmos fornecer `get` e `value` no mesmo descritor, vai haver um erro:

```js run
*!*
// Error: Invalid property descriptor.
// Erro: Invalid property descriptor.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comentário mistura português e inglês. No artigo anterior (property-descriptors, linha 119) o padrão foi manter a mensagem original e traduzi-la entre parênteses. Sugestão para manter consistência:

Suggested change
// Erro: Invalid property descriptor.
// Erro: Invalid property descriptor (descritor de propriedade inválido).

*/!*
Object.defineProperty({}, 'prop', {
get() {
Expand All @@ -151,11 +151,11 @@ Object.defineProperty({}, 'prop', {
});
```

## Smarter getters/setters
## Getters/setters mais espertos

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: "espertos" soa coloquial para um título; "mais inteligentes" é a forma mais comum em material técnico.

Suggested change
## Getters/setters mais espertos
## Getters/setters mais inteligentes


Getters/setters can be used as wrappers over "real" property values to gain more control over operations with them.
Getters/setters podem ser usados como invólucros sobre valores "reais" de propriedades, pra ganhar mais controle sobre as operações com eles.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registro informal: "pra" destoa do resto do artigo, que usa "para" em todos os outros lugares.

Suggested change
Getters/setters podem ser usados como invólucros sobre valores "reais" de propriedades, pra ganhar mais controle sobre as operações com eles.
Getters/setters podem ser usados como invólucros sobre valores "reais" de propriedades, para ganhar mais controle sobre as operações com eles.


For instance, if we want to forbid too short names for `user`, we can have a setter `name` and keep the value in a separate property `_name`:
Por exemplo, se quisermos proibir nomes muito curtos para `user`, podemos ter um setter `name` e manter o valor numa propriedade separada, `_name`:

```js run
let user = {
Expand All @@ -165,7 +165,7 @@ let user = {

set name(value) {
if (value.length < 4) {
alert("Name is too short, need at least 4 characters");
alert("O nome é muito curto, precisa ter pelo menos 4 caracteres");
return;
}
this._name = value;
Expand All @@ -175,19 +175,19 @@ let user = {
user.name = "Pete";
alert(user.name); // Pete

user.name = ""; // Name is too short...
user.name = ""; // O nome é muito curto...
```

So, the name is stored in `_name` property, and the access is done via getter and setter.
Então, o nome é armazenado na propriedade `_name`, e o acesso é feito via getter e setter.

Technically, external code is able to access the name directly by using `user._name`. But there is a widely known convention that properties starting with an underscore `"_"` are internal and should not be touched from outside the object.
Tecnicamente, código externo consegue acessar o nome diretamente usando `user._name`. Mas existe uma convenção amplamente conhecida de que propriedades começando com um sublinhado `"_"` são internas e não devem ser tocadas de fora do objeto.


## Using for compatibility
## Usando para compatibilidade

One of the great uses of accessors is that they allow to take control over a "regular" data property at any moment by replacing it with a getter and a setter and tweak its behavior.
Um dos grandes usos dos acessores é que eles permitem assumir o controle sobre uma propriedade de dados "normal" a qualquer momento, substituindo-a por um getter e um setter e ajustando seu comportamento.

Imagine we started implementing user objects using data properties `name` and `age`:
Imagine que começamos a implementar objetos de usuário usando as propriedades de dados `name` e `age`:

```js
function User(name, age) {
Expand All @@ -200,7 +200,7 @@ let john = new User("John", 25);
alert( john.age ); // 25
```

...But sooner or later, things may change. Instead of `age` we may decide to store `birthday`, because it's more precise and convenient:
...Mas, mais cedo ou mais tarde, as coisas podem mudar. Em vez de `age`, podemos decidir armazenar `birthday`, porque é mais preciso e conveniente:

```js
function User(name, birthday) {
Expand All @@ -211,21 +211,21 @@ function User(name, birthday) {
let john = new User("John", new Date(1992, 6, 1));
```

Now what to do with the old code that still uses `age` property?
Agora, o que fazer com o código antigo que ainda usa a propriedade `age`?

We can try to find all such places and fix them, but that takes time and can be hard to do if that code is used by many other people. And besides, `age` is a nice thing to have in `user`, right?
Podemos tentar encontrar todos esses lugares e corrigi-los, mas isso leva tempo e pode ser difícil se esse código for usado por muitas outras pessoas. E, além disso, `age` é algo bom de se ter em `user`, não é?

Let's keep it.
Vamos mantê-lo.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

O pronome se refere à propriedade age (feminino), como na frase anterior "a propriedade age".

Suggested change
Vamos mantê-lo.
Vamos mantê-la.


Adding a getter for `age` solves the problem:
Adicionar um getter para `age` resolve o problema:

```js run no-beautify
function User(name, birthday) {
this.name = name;
this.birthday = birthday;

*!*
// age is calculated from the current date and birthday
// age é calculado a partir da data atual e do birthday
Object.defineProperty(this, "age", {
get() {
let todayYear = new Date().getFullYear();
Expand All @@ -237,8 +237,8 @@ function User(name, birthday) {

let john = new User("John", new Date(1992, 6, 1));

alert( john.birthday ); // birthday is available
alert( john.age ); // ...as well as the age
alert( john.birthday ); // birthday está disponível
alert( john.age ); // ...assim como age
```

Now the old code works too and we've got a nice additional property.
Agora o código antigo também funciona e ganhamos uma boa propriedade adicional.