diff --git a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md index 6d25a462a..232ad793c 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md @@ -1,4 +1,4 @@ -1. `true`, taken from `rabbit`. -2. `null`, taken from `animal`. -3. `undefined`, there's no such property any more. +1. `true`, obtido de `rabbit`. +2. `null`, obtido de `animal`. +3. `undefined`, essa propriedade não existe mais. diff --git a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md index f38fb6f97..67c8f5a62 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Working with prototype +# Trabalhando com protótipos -Here's the code that creates a pair of objects, then modifies them. +Aqui está o código que cria um par de objetos, e depois os modifica. -Which values are shown in the process? +Que valores são mostrados no processo? ```js let animal = { @@ -28,4 +28,4 @@ delete animal.jumps; alert( rabbit.jumps ); // ? (3) ``` -There should be 3 answers. +Deve haver 3 respostas. diff --git a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md index a16796f9c..25c3c175b 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md @@ -1,5 +1,5 @@ -1. Let's add `__proto__`: +1. Vamos adicionar `__proto__`: ```js run let head = { @@ -27,6 +27,6 @@ alert( table.money ); // undefined ``` -2. In modern engines, performance-wise, there's no difference whether we take a property from an object or its prototype. They remember where the property was found and reuse it in the next request. +2. Em interpretadores de JavaScript modernos, em termos de performance (*performance-wise*), não há diferença entre obtermos uma propriedade de um objeto ou do seu protótipo. Eles se lembram onde a propriedade foi encontrada e reutilizam isso na próxima requisição. - For instance, for `pockets.glasses` they remember where they found `glasses` (in `head`), and next time will search right there. They are also smart enough to update internal caches if something changes, so that optimization is safe. + Por exemplo, para `pockets.glasses` eles se lembram onde encontraram `glasses` (em `head`), e na próxima vez vão procurar lá. Eles também são inteligentes o suficiente para atualizar caches internos se algo mudar, então essa otimização é segura. diff --git a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md index bc2db47fe..b95b4c576 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Searching algorithm +# Algoritmo de busca -The task has two parts. +A tarefa tem duas partes. -Given the following objects: +Dados os objetos a seguir: ```js let head = { @@ -27,5 +27,5 @@ let pockets = { }; ``` -1. Use `__proto__` to assign prototypes in a way that any property lookup will follow the path: `pockets` -> `bed` -> `table` -> `head`. For instance, `pockets.pen` should be `3` (found in `table`), and `bed.glasses` should be `1` (found in `head`). -2. Answer the question: is it faster to get `glasses` as `pockets.glasses` or `head.glasses`? Benchmark if needed. +1. Use `__proto__` para atribuir propriedades de forma que qualquer busca de propriedades siga o caminho: `pockets` -> `bed` -> `table` -> `head`. Por exemplo, `pockets.pen` deve ter o valor `3` (encontrado em `table`), e `bed.glasses` deve ter o valor `1` (encontrado em `head`). +2. Responda à seguinte questão: é mais rápido obter `glasses` como `pockets.glasses` ou como `head.glasses`? Compare (*benchmark*), se necessário. diff --git a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md index 4d6ea2653..8d0ce35f7 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md @@ -1,7 +1,7 @@ -**The answer: `rabbit`.** +**A resposta: `rabbit`.** -That's because `this` is an object before the dot, so `rabbit.eat()` modifies `rabbit`. +Isso porque `this` é o objeto antes do ponto, então `rabbit.eat()` modifica `rabbit`. -Property lookup and execution are two different things. +Procurar e executar propriedades são duas coisas diferentes. -The method `rabbit.eat` is first found in the prototype, then executed with `this=rabbit`. +O método `rabbit.eat` primeiro é encontrado no protótipo, depois é exectado com `this=rabbit`. diff --git a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md index ed8482c07..5a4d0eb6f 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Where does it write? +# Onde vai escrever? -We have `rabbit` inheriting from `animal`. +Nós temos `rabbit` herdando de `animal`. -If we call `rabbit.eat()`, which object receives the `full` property: `animal` or `rabbit`? +Se nós chamarmos `rabbit.eat()`, que objeto recebe a propriedade `full`: `animal` ou `rabbit`? ```js let animal = { diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md index c141b2ecd..820cc2b1b 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md @@ -1,18 +1,18 @@ -Let's look carefully at what's going on in the call `speedy.eat("apple")`. +Vamos ver cuidadosamente o que está acontecendo na chamada `speedy.eat("apple")`. -1. The method `speedy.eat` is found in the prototype (`=hamster`), then executed with `this=speedy` (the object before the dot). +1. O método `speedy.eat` é encontrado no protótipo (`=hamster`), e executado usando `this=speedy` (o objeto antes do ponto). -2. Then `this.stomach.push()` needs to find `stomach` property and call `push` on it. It looks for `stomach` in `this` (`=speedy`), but nothing found. +2. Então o método `this.stomach.push()` precisa de encontrar uma propriedade `stomach` e chamar o `push` nela. Ele procura por um `stomach` no `this` (`=speedy`), mas não encontra. -3. Then it follows the prototype chain and finds `stomach` in `hamster`. +3. Aí ele segue a cadeia de protótipos e encontra `stomach` no `hamster`. -4. Then it calls `push` on it, adding the food into *the stomach of the prototype*. +4. Por fim, ele chama o `push`, adicionando a comida (*food*) dentro do *`stomach` do protótipo*. -So all hamsters share a single stomach! +Então, todos os hamsters compartilham o mesmo estômago! -Both for `lazy.stomach.push(...)` and `speedy.stomach.push()`, the property `stomach` is found in the prototype (as it's not in the object itself), then the new data is pushed into it. +Para ambos `lazy.stomach.push(...)` e `speedy.stomach.push()`, a propriedade `stomach` é encontrada no protótipo (porque não está no próprio objeto), e assim os novos dados são colocados nela. -Please note that such thing doesn't happen in case of a simple assignment `this.stomach=`: +Note que isso não acontece no caso de uma simples atribuição `this.stomach=`: ```js run let hamster = { @@ -20,7 +20,7 @@ let hamster = { eat(food) { *!* - // assign to this.stomach instead of this.stomach.push + // atribui o valor para this.stomach ao invés de usar this.stomach.push this.stomach = [food]; */!* } @@ -34,17 +34,17 @@ let lazy = { __proto__: hamster }; -// Speedy one found the food -speedy.eat("apple"); -alert( speedy.stomach ); // apple +// O Speedy acha a comida +speedy.eat("maçã"); +alert( speedy.stomach ); // maçã -// Lazy one's stomach is empty -alert( lazy.stomach ); // +// O estômago do Lazy continua vazio +alert( lazy.stomach ); // ``` -Now all works fine, because `this.stomach=` does not perform a lookup of `stomach`. The value is written directly into `this` object. +Agora tudo funciona bem, porque `this.stomach=` não procura por um `stomach`. O valor é escrito diretamente no `this` do objeto. -Also we can totally avoid the problem by making sure that each hamster has their own stomach: +Além disso, nós podemos evitar completamente o problema fazendo com que cada hamster tenha seu próprio estômago: ```js run let hamster = { @@ -69,12 +69,12 @@ let lazy = { */!* }; -// Speedy one found the food -speedy.eat("apple"); -alert( speedy.stomach ); // apple +// O Speedy acha a comida +speedy.eat("maçã"); +alert( speedy.stomach ); // maçã -// Lazy one's stomach is empty -alert( lazy.stomach ); // +// O estômago do Lazy continua vazio +alert( lazy.stomach ); // ``` -As a common solution, all properties that describe the state of a particular object, like `stomach` above, should be written into that object. That prevents such problems. +É uma solução comum, fazer com que todas as propriedades que descrevem um estado particular do objeto, como o `stomach` acima, sejam escritas dentro do próprio objeto. Isso previne esses problemas. diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md index 50171123d..9a3738fc6 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md +++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Why are both hamsters full? +# Por que os dois hamsters estão cheios? -We have two hamsters: `speedy` and `lazy` inheriting from the general `hamster` object. +Nós temos dois hamsters: `speedy` e `lazy`, que herdam do objeto genérico `hamster`. -When we feed one of them, the other one is also full. Why? How can we fix it? +Quando nós alimentamos um deles, o outro também fica cheio. Por quê? Como podemos corrigir isso? ```js run let hamster = { @@ -25,11 +25,11 @@ let lazy = { __proto__: hamster }; -// This one found the food -speedy.eat("apple"); -alert( speedy.stomach ); // apple +// Este aqui encontrou a comida +speedy.eat("maçã"); +alert( speedy.stomach ); // maçã -// This one also has it, why? fix please. -alert( lazy.stomach ); // apple +// Esse aqui também comeu, por quê? Corrija, por favor. +alert( lazy.stomach ); // maçã ``` diff --git a/1-js/08-prototypes/01-prototype-inheritance/article.md b/1-js/08-prototypes/01-prototype-inheritance/article.md index ef6c7ffeb..d60e186d2 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/article.md +++ b/1-js/08-prototypes/01-prototype-inheritance/article.md @@ -1,22 +1,22 @@ -# Prototypal inheritance +# Herança Prototipada -In programming, we often want to take something and extend it. +Na programação, nós sempre queremos extender algum comportamento. -For instance, we have a `user` object with its properties and methods, and want to make `admin` and `guest` as slightly modified variants of it. We'd like to reuse what we have in `user`, not copy/reimplement its methods, just build a new object on top of it. +Por exemplo, nós temos um objeto `user` com suas propriedades e métodos, e queremos criar duas variantes `admin` e `guest` ligeiramente diferentes. Nós gostaríamos de reutilizar o que já temos no `user`, sem copiar/reimplementar seus métodos, apenas construir um novo objeto baseado nele. -*Prototypal inheritance* is a language feature that helps in that. +Herança Prototipada (*Prototypal inheritance*) é uma funcionalidade da linguagem que nos ajuda com isso. ## [[Prototype]] -In JavaScript, objects have a special hidden property `[[Prototype]]` (as named in the specification), that is either `null` or references another object. That object is called "a prototype": +No Javascript, os objetos possuem uma propriedade escondida especial `[[Prototype]]` (como é chamada na especificação), cujo valor é `null` ou referencia outro objeto. Esse objeto é chamado de "protótipo": ![prototype](object-prototype-empty.svg) -When we read a property from `object`, and it's missing, JavaScript automatically takes it from the prototype. In programming, this is called "prototypal inheritance". And soon we'll study many examples of such inheritance, as well as cooler language features built upon it. +Quando lemos uma propriedade de um `object`, e ela não está presente, o Javascript automaticamente obtém seu valor do protótipo. Na programação, isso é chamado de "herança prototipada". Em breve nós vamos ver vários exemplos dessa herança, bem como funcionalidades legais construidas em cima disso. -The property `[[Prototype]]` is internal and hidden, but there are many ways to set it. +A propriedade `[[Prototype]]` é interna e escondida, mas existem várias formas de configurar um valor para ela. -One of them is to use the special name `__proto__`, like this: +Uma delas é usar o nome especial `__proto__`, dessa forma: ```js run let animal = { @@ -31,9 +31,9 @@ rabbit.__proto__ = animal; // sets rabbit.[[Prototype]] = animal */!* ``` -Now if we read a property from `rabbit`, and it's missing, JavaScript will automatically take it from `animal`. +Agora, se tentarmos ler uma propriedade de `rabbit` e ela não estiver presente, o Javascript vai automaticamente obtê-la de `animal`. -For instance: +Por exemplo: ```js let animal = { @@ -47,31 +47,31 @@ let rabbit = { rabbit.__proto__ = animal; // (*) */!* -// we can find both properties in rabbit now: +// nós podemos encontrar ambas propriedades no `rabbit` agora: *!* alert( rabbit.eats ); // true (**) */!* alert( rabbit.jumps ); // true ``` -Here the line `(*)` sets `animal` to be the prototype of `rabbit`. +Aqui, a linha `(*)` do exemplo configura `animal` como o protótipo de `rabbit`. -Then, when `alert` tries to read property `rabbit.eats` `(**)`, it's not in `rabbit`, so JavaScript follows the `[[Prototype]]` reference and finds it in `animal` (look from the bottom up): +Depois, quando o `alert` tenta ler a propriedade `rabbit.eats`, em `(**)`, ela não está no `rabbit`, então o Javascript segue a referência do `[[Prototype]]` e a encontra no `animal` (olhe de baixo pra cima): ![](proto-animal-rabbit.svg) -Here we can say that "`animal` is the prototype of `rabbit`" or "`rabbit` prototypically inherits from `animal`". +Aqui nós podemos dizer que "`animal` é o protótipo de `rabbit`", ou então que "`rabbit` herda o protótipo de `animal`". -So if `animal` has a lot of useful properties and methods, then they become automatically available in `rabbit`. Such properties are called "inherited". +Então se `animal` tem várias propriedades e métodos que são úteis, eles se tornam automaticamente disponíveis no `rabbit`. Essas propriedades são chamadas de "herdadas" ("inherited"). -If we have a method in `animal`, it can be called on `rabbit`: +Se nós temos um método em `animal`, ele pode ser chamado no `rabbit`: ```js run let animal = { eats: true, *!* walk() { - alert("Animal walk"); + alert("Animal caminha"); } */!* }; @@ -81,23 +81,23 @@ let rabbit = { __proto__: animal }; -// walk is taken from the prototype +// walk é obtido do protótipo *!* -rabbit.walk(); // Animal walk +rabbit.walk(); // Animal caminha */!* ``` -The method is automatically taken from the prototype, like this: +O método é automaticamente obtido do protótipo, assim: ![](proto-animal-rabbit-walk.svg) -The prototype chain can be longer: +A cadeia de protótipos pode ser maior: ```js run let animal = { eats: true, walk() { - alert("Animal walk"); + alert("Animal caminha"); } }; @@ -115,47 +115,47 @@ let longEar = { */!* }; -// walk is taken from the prototype chain -longEar.walk(); // Animal walk -alert(longEar.jumps); // true (from rabbit) +// walk é obtido da cadeia de protótipos +longEar.walk(); // Animal caminha +alert(longEar.jumps); // true (vindo de rabbit) ``` ![](proto-animal-rabbit-chain.svg) -Now if we read something from `longEar`, and it's missing, JavaScript will look for it in `rabbit`, and then in `animal`. +Agora, se nós quisermos ler algo de `longEar` e ele não possuir, o Javascript vai procurar no `rabbit`, e depois no `animal`. -There are only two limitations: +Só existem duas limitações: -1. The references can't go in circles. JavaScript will throw an error if we try to assign `__proto__` in a circle. -2. The value of `__proto__` can be either an object or `null`. Other types are ignored. +1. As referências não podem ser circulares. O Javascript vai disparar um erro caso a gente tente atribuir `__proto__` em um círculo de objetos. +2. O valor de `__proto__` só pode ser um objeto ou `null`, outros tipos são ignorados. -Also it may be obvious, but still: there can be only one `[[Prototype]]`. An object may not inherit from two others. +Além disso, só pode haver um `[[Prototype]]`. Um objeto não pode ser herdeiro de outros dois. -```smart header="`__proto__` is a historical getter/setter for `[[Prototype]]`" -It's a common mistake of novice developers not to know the difference between these two. +```smart header="`__proto__` é um getter/setter histórico para `[[Prototype]]`" +É um erro comum, desenvolvedores novatos não saberem a diferença entre esses dois. -Please note that `__proto__` is *not the same* as the internal `[[Prototype]]` property. It's a getter/setter for `[[Prototype]]`. Later we'll see situations where it matters, for now let's just keep it in mind, as we build our understanding of JavaScript language. +Mas note que `__proto__` *não é o mesmo* que a propriedade interna `[[Prototype]]`. Ele é um getter/setter para o `[[Prototype]]`. Mais tarde veremos situações nas quais isso importa, por ora vamos apenar manter isso em mente enquanto construimos nossa compreensão da linguagem Javascript. -The `__proto__` property is a bit outdated. It exists for historical reasons, modern JavaScript suggests that we should use `Object.getPrototypeOf/Object.setPrototypeOf` functions instead that get/set the prototype. We'll also cover these functions later. +A propriedade `__proto__` está um pouco ultrapassada, ela existe por motivos históricos. O Javascript moderno sugere que nós usemos as funções `Object.getPrototypeOf/Object.setPrototypeOf` no lugar, que também fazem get/set do protótipo. Nós também vamos cobrir essas funções mais tarde. -By the specification, `__proto__` must only be supported by browsers. In fact though, all environments including server-side support `__proto__`, so we're quite safe using it. +A especificação diz que o `__proto__` só pode ser suportado por browsers. Mas o fato é que todos os ambientes, incluindo o lado do servidor ("server-side") suportam o `__proto__`, então podemos usá-lo tranquilamente. -As the `__proto__` notation is a bit more intuitively obvious, we use it in the examples. +Como a notação `__proto__` é um pouco mais intuitiva, vamos usá-la nos exemplos. ``` -## Writing doesn't use prototype +## A Escrita não usa o protótipo -The prototype is only used for reading properties. +O protótipo é usado apenas para leitura de propriedades. -Write/delete operations work directly with the object. +As operações de escrita/deleção trabalham diretamente com o objeto. -In the example below, we assign its own `walk` method to `rabbit`: +No exemplo abaixo, nós criamos um método `walk` próprio para o `rabbit`: ```js run let animal = { eats: true, walk() { - /* this method won't be used by rabbit */ + /* esse método não será usado pelo rabbit */ } }; @@ -165,20 +165,20 @@ let rabbit = { *!* rabbit.walk = function() { - alert("Rabbit! Bounce-bounce!"); + alert("Coelho! Pula-pula!"); }; */!* -rabbit.walk(); // Rabbit! Bounce-bounce! +rabbit.walk(); // Coelho! Pula-pula! ``` -From now on, `rabbit.walk()` call finds the method immediately in the object and executes it, without using the prototype: +De agora em diante, chamar `rabbit.walk()` encontra o método imediatamente no objeto e o executa, sem usar o protótipo: ![](proto-animal-rabbit-walk-2.svg) -Accessor properties are an exception, as assignment is handled by a setter function. So writing to such a property is actually the same as calling a function. +Métodos de acesso são uma exceção, porque a atribuição é feita por uma função setter. Assim, guardar um valor numa dessas propriedades é o mesmo que chamar uma função. -For that reason `admin.fullName` works correctly in the code below: +Por essa razão, `admin.fullName` funciona corretamente no código abaixo: ```js run let user = { @@ -201,37 +201,37 @@ let admin = { alert(admin.fullName); // John Smith (*) -// setter triggers! +// setter é disparado! admin.fullName = "Alice Cooper"; // (**) -alert(admin.fullName); // Alice Cooper, state of admin modified -alert(user.fullName); // John Smith, state of user protected +alert(admin.fullName); // Alice Cooper, estado do admin modificado +alert(user.fullName); // John Smith, estado do user protegido ``` -Here in the line `(*)` the property `admin.fullName` has a getter in the prototype `user`, so it is called. And in the line `(**)` the property has a setter in the prototype, so it is called. +Na linha `(*)`, a propriedade `admin.fullName` tem um getter no protótipo `user`, então ele é chamado. E na linha `(**)` a propriedade tem um setter no protótipo, então ele é chamado. -## The value of "this" +## O valor do "this" -An interesting question may arise in the example above: what's the value of `this` inside `set fullName(value)`? Where are the properties `this.name` and `this.surname` written: into `user` or `admin`? +Uma pergunta interessante pode surgir no exemplo acima: qual o valor do `this` dentro de `set fullName(value)`? Onde as propriedades `this.name` e `this.surname` são escritas: dentro de `user` ou de `admin`? -The answer is simple: `this` is not affected by prototypes at all. +A resposta é simples: o `this` não é nem um pouco afetado pelos protótipos. -**No matter where the method is found: in an object or its prototype. In a method call, `this` is always the object before the dot.** +**Não importa onde o método é encontrado: dentro de um objeto ou do seu protótipo. Ao chamar um método, `this` é sempre o objeto antes do ponto.** -So, the setter call `admin.fullName=` uses `admin` as `this`, not `user`. +Então, a chamada do setter `admin.fullName=` usa o `admin` como `this`, não o `user`. -That is actually a super-important thing, because we may have a big object with many methods, and have objects that inherit from it. And when the inheriting objects run the inherited methods, they will modify only their own states, not the state of the big object. +Na verdade isso é super importante, porque pode ser que a gente tenha um objeto grande com vários métodos, sendo que outros objetos herdam ele. Quando os objetos herdeiros rodam os métodos herdados, eles vão modificar apenas seus próprios estados, não o estado do objeto grande. -For instance, here `animal` represents a "method storage", and `rabbit` makes use of it. +Por exemplo, aqui `animal` representa um "armazenador de métodos", e `rabbit` faz uso deles. -The call `rabbit.sleep()` sets `this.isSleeping` on the `rabbit` object: +A chamada de `rabbit.sleep()` configura `this.isSleeping` no objeto `rabbit`: ```js run -// animal has methods +// animal tem métodos let animal = { walk() { if (!this.isSleeping) { - alert(`I walk`); + alert(`Eu caminho`); } }, sleep() { @@ -240,30 +240,30 @@ let animal = { }; let rabbit = { - name: "White Rabbit", + name: "Coelho branco", __proto__: animal }; -// modifies rabbit.isSleeping +// modifica rabbit.isSleeping rabbit.sleep(); alert(rabbit.isSleeping); // true -alert(animal.isSleeping); // undefined (no such property in the prototype) +alert(animal.isSleeping); // undefined (não existe essa propriedade no protótipo) ``` -The resulting picture: +A imagem do resultado fica: ![](proto-animal-rabbit-walk-3.svg) -If we had other objects, like `bird`, `snake`, etc., inheriting from `animal`, they would also gain access to methods of `animal`. But `this` in each method call would be the corresponding object, evaluated at the call-time (before dot), not `animal`. So when we write data into `this`, it is stored into these objects. +Se nós tivéssemos outros objetos, como `bird`, `snake`, etc., herdando de `animal`, eles iriam ganhar acesso aos métodos de `animal`. Mas em cada chamada dos métodos, o `this` corresponderia ao próprio objeto (antes do ponto), calculado na hora da chamada, não ao `animal`. Dessa forma, quando escrevemos algum dado no `this`, ele vai ser armazenado dentro de cada objeto. -As a result, methods are shared, but the object state is not. +Como resultado, os métodos são compartilhados, mas o estado dos objetos não são. -## for..in loop +## Loop for..in -The `for..in` loop iterates over inherited properties too. +O loop `for..in` também itera sobre as propriedades herdadas. -For instance: +Por exemplo: ```js run let animal = { @@ -276,19 +276,19 @@ let rabbit = { }; *!* -// Object.keys only returns own keys +// Object.keys retorna apenas as próprias chaves alert(Object.keys(rabbit)); // jumps */!* *!* -// for..in loops over both own and inherited keys -for(let prop in rabbit) alert(prop); // jumps, then eats +// for..in itera sobre as próprias chaves e sobre as herdadas +for(let prop in rabbit) alert(prop); // jumps, e depois eats */!* ``` -If that's not what we want, and we'd like to exclude inherited properties, there's a built-in method [obj.hasOwnProperty(key)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty): it returns `true` if `obj` has its own (not inherited) property named `key`. +Se isso não é o que queremos, e nós gostaríamos de excluir as propriedades herdadas, existe o método interno [obj.hasOwnProperty(key)](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty): ele retorna `true` se o `obj` possui de fato uma propriedade chamada `key` (não herdada). -So we can filter out inherited properties (or do something else with them): +Então nós podemos filtrar apenas as propriedades herdadas (ou fazer outra coisa com elas): ```js run let animal = { @@ -304,35 +304,35 @@ for(let prop in rabbit) { let isOwn = rabbit.hasOwnProperty(prop); if (isOwn) { - alert(`Our: ${prop}`); // Our: jumps + alert(`Nosso: ${prop}`); // Nosso: jumps } else { - alert(`Inherited: ${prop}`); // Inherited: eats + alert(`Herdado: ${prop}`); // Herdado: eats } } ``` -Here we have the following inheritance chain: `rabbit` inherits from `animal`, that inherits from `Object.prototype` (because `animal` is a literal object `{...}`, so it's by default), and then `null` above it: +Aqui nós temos a seguinte cadeia de heranças: `rabbit` herda de `animal`, que herda de `Object.prototype` (por definição, pois `animal` é um objeto literal `{...}`), que tem apenas `null` acima: ![](rabbit-animal-object.svg) -Note, there's one funny thing. Where is the method `rabbit.hasOwnProperty` coming from? We did not define it. Looking at the chain we can see that the method is provided by `Object.prototype.hasOwnProperty`. In other words, it's inherited. +Note que existe uma coisa curiosa. De onde o método `rabbit.hasOwnProperty` está vindo? Nós não definimos ele. Mas olhando para a cadeia, nós podemos ver que esse método é passado pelo `Object.prototype.hasOwnProperty`. Em outras palavras, ele é herdado. -...But why does `hasOwnProperty` not appear in the `for..in` loop like `eats` and `jumps` do, if `for..in` lists inherited properties? +...Mas por que `hasOwnProperty` não aparece no loop `for..in`, da mesma forma que `eats` e `jumps`, já que o `for..in` lista propriedades herdadas? -The answer is simple: it's not enumerable. Just like all other properties of `Object.prototype`, it has `enumerable:false` flag. And `for..in` only lists enumerable properties. That's why it and the rest of the `Object.prototype` properties are not listed. +A resposta é simples: ele não é enumerável. Assim como todas as outras propriedades de `Object.prototype`, ele tem a flag `enumerable:false`. E `for..in` só lista aquelas que são enumeráveis. Aí está o porquê do resto das propriedades de `Object.prototype` não estarem listadas. -```smart header="Almost all other key/value-getting methods ignore inherited properties" -Almost all other key/value-getting methods, such as `Object.keys`, `Object.values` and so on ignore inherited properties. +```smart header="Quase todas as outras chaves/métodos *obtém-valor* ignoram propriedades herdadas." +Quase todas as outras chaves/métodos *obtém-valor*, como `Object.keys`, `Object.values`, entre outros, ignoram propriedades herdadas. -They only operate on the object itself. Properties from the prototype are *not* taken into account. +Eles operam apenas no próprio objeto. Propriedades vindas do protótipo *não* são levadas em conta. ``` -## Summary +## Resumo -- In JavaScript, all objects have a hidden `[[Prototype]]` property that's either another object or `null`. -- We can use `obj.__proto__` to access it (a historical getter/setter, there are other ways, to be covered soon). -- The object referenced by `[[Prototype]]` is called a "prototype". -- If we want to read a property of `obj` or call a method, and it doesn't exist, then JavaScript tries to find it in the prototype. -- Write/delete operations act directly on the object, they don't use the prototype (assuming it's a data property, not a setter). -- If we call `obj.method()`, and the `method` is taken from the prototype, `this` still references `obj`. So methods always work with the current object even if they are inherited. -- The `for..in` loop iterates over both its own and its inherited properties. All other key/value-getting methods only operate on the object itself. +- No Javascript, todos os objetos possuem uma propriedade `[[Prototype]]` escondida que ou é um objeto ou é `null`. +- Nós podemos usar `obj.__proto__` para acessá-lo (um histórico getter/setter, mas já existem alternativas, que veremos em breve). +- O objeto referenciado por `[[Prototype]]` é um chamado "protótipo" (*prototype*). +- Se nós queremos ler uma propriedade de `obj` ou chamar um método, e eles não existem, o Javascript tenta encontrá-los no protótipo. +- Operações de escrever/deletar agem diretamente no objeto, elas não usam o protótipo (assumindo que seja uma propriedade para dados, não um setter). +- Se chamarmos `obj.method()`, e o `method` é obtido do prototype, o `this` ainda referencia o `obj`. Portanto métodos sempre trabalham com o objeto atual, mesmo que eles sejam herdados. +- O loop `for..in` itera tanto sobre as propriedades do objeto quanto sobre as propriedades herdadas. Todas os outros métodos para obter chaves/valores operam apenas sobre o próprio objeto. diff --git a/1-js/08-prototypes/index.md b/1-js/08-prototypes/index.md index 8554a0e30..af72852ce 100644 --- a/1-js/08-prototypes/index.md +++ b/1-js/08-prototypes/index.md @@ -1 +1 @@ -# Prototypes, inheritance +# Protótipos, herança