diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/solution.js b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/solution.js
index d5a09efb3..3184e9957 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/solution.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/solution.js
@@ -1,7 +1,8 @@
function spy(func) {
function wrapper(...args) {
- // using ...args instead of arguments to store "real" array in wrapper.calls
+ // usar `...args` ao invés de `arguments`
+ // para armazenar o vetor "real" no `wrapper.calls`
wrapper.calls.push(args);
return func.apply(this, args);
}
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/source.js b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/source.js
index 38da0105f..dd970ede5 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/source.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/source.js
@@ -1,5 +1,4 @@
function spy(func) {
- // your code
+ // o teu código
}
-
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/test.js b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/test.js
index 5adfcb978..f277703bd 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/test.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/test.js
@@ -18,18 +18,17 @@ describe("spy", function() {
});
it("transparently wraps functions", function() {
-
+
let sum = sinon.spy((a, b) => a + b);
let wrappedSum = spy(sum);
assert.equal(wrappedSum(1, 2), 3);
- assert(sum.calledWith(1, 2));
+ assert(sum.calledWidth(1, 2));
});
-
it("transparently wraps methods", function() {
-
+
let calc = {
sum: sinon.spy((a, b) => a + b)
};
@@ -40,5 +39,4 @@ describe("spy", function() {
assert(calc.sum.calledWith(1, 2));
assert(calc.sum.calledOn(calc));
});
-
-});
+});
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/solution.md b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/solution.md
index 0c8a211b4..c42cfcac4 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/solution.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/solution.md
@@ -1 +1 @@
-The wrapper returned by `spy(f)` should store all arguments and then use `f.apply` to forward the call.
+O embrulhador retornado pela `spy(f)` deve armazenar todos os argumentos e então usar `f.apply` para encaminhar a chamada.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/task.md b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/task.md
index a3843107c..81dfca7e1 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/task.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/task.md
@@ -2,17 +2,17 @@ importance: 5
---
-# Spy decorator
+# Decorador de Espionagem
-Create a decorator `spy(func)` that should return a wrapper that saves all calls to function in its `calls` property.
+Cria um decorador `spy(func)` que retorna um embrulhador que guarda todas as chamadas à função na sua propriedade `calls`.
-Every call is saved as an array of arguments.
+Toda chamada é guardada num vetor de argumentos.
-For instance:
+Por exemplo:
```js
function work(a, b) {
- alert( a + b ); // work is an arbitrary function or method
+ alert( a + b ); // `work` é uma função ou método arbitrário
}
*!*
@@ -27,4 +27,4 @@ for (let args of work.calls) {
}
```
-P.S. That decorator is sometimes useful for unit-testing. Its advanced form is `sinon.spy` in [Sinon.JS](http://sinonjs.org/) library.
+Pós-escrito: Este decorador pode ser útil para testes unitários. Sua forma avançada é `sinon.spy` na biblioteca [Sinon.JS](http://sinonjs.org).
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/_js.view/test.js b/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/_js.view/test.js
index d9295da51..5d4ca2ab5 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/_js.view/test.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/_js.view/test.js
@@ -7,7 +7,7 @@ describe("delay", function() {
this.clock.restore();
});
- it("calls the function after the specified timeout", function() {
+ it("chama a função após o tempo de espera especificado", function() {
let start = Date.now();
function f(x) {
@@ -16,12 +16,12 @@ describe("delay", function() {
f = sinon.spy(f);
let f1000 = delay(f, 1000);
- f1000("test");
+ f1000("teste");
this.clock.tick(2000);
- assert(f.calledOnce, 'calledOnce check fails');
+ assert(f.calledOnce, 'a verificação de calledOnce falha');
});
- it("passes arguments and this", function() {
+ it("passa os argumentos e o contexto de this", function() {
let start = Date.now();
let user = {
sayHi: function(phrase, who) {
@@ -37,10 +37,10 @@ describe("delay", function() {
let spy = user.sayHi;
user.sayHi = delay(user.sayHi, 1500);
- user.sayHi("Hello", "John");
+ user.sayHi("Olá", "John");
this.clock.tick(2000);
- assert(spy.calledOnce, 'calledOnce check failed');
+ assert(spy.calledOnce, 'a verificação de calledOnce falhou');
});
-});
+});
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/solution.md b/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/solution.md
index 24bb4d448..914c88688 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/solution.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/solution.md
@@ -1,4 +1,4 @@
-The solution:
+A solução:
```js run demo
function delay(f, ms) {
@@ -11,22 +11,22 @@ function delay(f, ms) {
let f1000 = delay(alert, 1000);
-f1000("test"); // shows "test" after 1000ms
+f1000("teste"); // exibe "teste" após 1000ms
```
-Please note how an arrow function is used here. As we know, arrow functions do not have own `this` and `arguments`, so `f.apply(this, arguments)` takes `this` and `arguments` from the wrapper.
+Notemos como usamos uma função de seta neste exemplo de código. Como sabemos, as funções de seta não possuem `this` e `arguments` próprios, então `f.apply(this, arguments)` recebe o `this` e `arguments` da função envolvente.
-If we pass a regular function, `setTimeout` would call it without arguments and `this=window` (assuming we're in the browser).
+Se passarmos uma função normal, `setTimeout` a chamaria sem argumentos e `this=window` (assumindo que estamos no navegador).
-We still can pass the right `this` by using an intermediate variable, but that's a little bit more cumbersome:
+Nós podemos ainda passar o `this` correto utilizando uma variável intermediária, mas isso é um pouco mais complicado:
```js
function delay(f, ms) {
return function(...args) {
- let savedThis = this; // store this into an intermediate variable
+ let savedThis = this; // armazenar isto numa variável intermédia
setTimeout(function() {
- f.apply(savedThis, args); // use it here
+ f.apply(savedThis, args); // utilizá-lo aqui
}, ms);
};
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/task.md b/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/task.md
index c04c68d7e..ab6254518 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/task.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/task.md
@@ -2,25 +2,25 @@ importance: 5
---
-# Delaying decorator
+# Decorador de Atraso
-Create a decorator `delay(f, ms)` that delays each call of `f` by `ms` milliseconds.
+Crie um decorador `delay(f, ms)` que atrasa cada chamada de `f` por `ms` milissegundos.
-For instance:
+Por exemplo:
```js
function f(x) {
alert(x);
}
-// create wrappers
+// criar funções envolventes
let f1000 = delay(f, 1000);
let f1500 = delay(f, 1500);
-f1000("test"); // shows "test" after 1000ms
-f1500("test"); // shows "test" after 1500ms
+f1000("teste"); // exibe "teste" após 1000ms
+f1500("teste"); // exibe "teste" após 1500ms
```
-In other words, `delay(f, ms)` returns a "delayed by `ms`" variant of `f`.
+Por outras palavras, `delay(f, ms)` retorna uma variante "atrasada por `ms`" de `f`.
-In the code above, `f` is a function of a single argument, but your solution should pass all arguments and the context `this`.
+No código acima, `f` é uma função de um único argumento, mas a sua solução deve passar todos os argumentos e o contexto de `this`.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/test.js b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/test.js
index 750e649f8..e237008ac 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/test.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/test.js
@@ -7,33 +7,33 @@ describe('debounce', function () {
this.clock.restore();
});
- it('for one call - runs it after given ms', function () {
+ it('para uma chamada - execute-a após um determinado ms', function () {
const f = sinon.spy();
const debounced = debounce(f, 1000);
debounced('test');
- assert(f.notCalled, 'not called immediately');
+ assert(f.notCalled, 'não é chamada imediatamente');
this.clock.tick(1000);
- assert(f.calledOnceWith('test'), 'called after 1000ms');
+ assert(f.calledOnceWith('test'), 'chamada após 1000ms');
});
- it('for 3 calls - runs the last one after given ms', function () {
+ it('para 3 chamadas - executa a última após determinados ms', function () {
const f = sinon.spy();
const debounced = debounce(f, 1000);
debounced('a');
- setTimeout(() => debounced('b'), 200); // ignored (too early)
- setTimeout(() => debounced('c'), 500); // runs (1000 ms passed)
+ setTimeout(() => debounced('b'), 200); // ignorada (demasiado cedo)
+ setTimeout(() => debounced('c'), 500); // executar (1000ms passados)
this.clock.tick(1000);
- assert(f.notCalled, 'not called after 1000ms');
+ assert(f.notCalled, 'não é chamada após 1000ms');
this.clock.tick(500);
- assert(f.calledOnceWith('c'), 'called after 1500ms');
+ assert(f.calledOnceWith('c'), 'chamada após 1500ms');
});
- it('keeps the context of the call', function () {
+ it('mantém o contexto da chamada', function () {
let obj = {
f() {
assert.equal(this, obj);
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.svg b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.svg
index e624ce020..45be5ec38 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.svg
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.view/index.html b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.view/index.html
index e3b4d5842..13a063a06 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.view/index.html
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.view/index.html
@@ -1,18 +1,18 @@
-Function handler
is called on this input:
+A função handler
é chamada nesta entrada:
-Debounced function debounce(handler, 1000)
is called on this input:
+A função debounce(handler, 1000)
reduzida é chamada nesta entrada:
-
+
\ No newline at end of file
+
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/solution.md b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/solution.md
index 83e75f315..ea3640063 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/solution.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/solution.md
@@ -9,5 +9,4 @@ function debounce(func, ms) {
```
-A call to `debounce` returns a wrapper. When called, it schedules the original function call after given `ms` and cancels the previous such timeout.
-
+Uma chamada à `debounce` retorna um embrulhador. Quando chamado, este agenda a chamada da função original depois de dados `ms` e cancela o tempo de espera anterior.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/task.md b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/task.md
index 5b0fcc5f8..9c5244c7c 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/task.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/task.md
@@ -2,21 +2,21 @@ importance: 5
---
-# Debounce decorator
+# Decorador de Redução
-The result of `debounce(f, ms)` decorator is a wrapper that suspends calls to `f` until there's `ms` milliseconds of inactivity (no calls, "cooldown period"), then invokes `f` once with the latest arguments.
+O resultado do decorador `debounce(f, ms)` é um embrulhador que suspende as chamadas à `f` até existir `ms` milissegundos de inatividade (nenhuma chamada, "período de arrefecimento"), depois invoca `f` uma vez com os argumentos mais recentes.
-In other words, `debounce` is like a secretary that accepts "phone calls", and waits until there's `ms` milliseconds of being quiet. And only then it transfers the latest call information to "the boss" (calls the actual `f`).
+Por outras palavras, `debounce` é como uma secretária que aceita "chamadas telefónicas", e espera até existir `ms` milissegundos de silêncio. E apenas depois transfere a informação da chamada mais recente ao "chefe" (chama a verdadeira `f`).
-For instance, we had a function `f` and replaced it with `f = debounce(f, 1000)`.
+Por exemplo, tínhamos uma função `f` e a substituímos por `f = debounce(f, 1000)`.
-Then if the wrapped function is called at 0ms, 200ms and 500ms, and then there are no calls, then the actual `f` will be only called once, at 1500ms. That is: after the cooldown period of 1000ms from the last call.
+Então se a função embrulhada for chamada aos 0ms, 200ms, e 500ms, e depois não existirem chamadas, a `f` verdadeira apenas será chamada uma vez, aos 1500ms. Isto é: depois do período de arrefecimento de 1000ms da última chamada.

-...And it will get the arguments of the very last call, other calls are ignored.
+...E obterá os argumentos da última chamada, outras chamadas são ignoradas.
-Here's the code for it (uses the debounce decorator from the [Lodash library](https://lodash.com/docs/4.17.15#debounce)):
+Eis o código para isto (que usa o decorador de redução da [biblioteca Lodash](https://lodash.com/docs/4.17.15#debounce)):
```js
let f = _.debounce(alert, 1000);
@@ -24,28 +24,28 @@ let f = _.debounce(alert, 1000);
f("a");
setTimeout( () => f("b"), 200);
setTimeout( () => f("c"), 500);
-// debounced function waits 1000ms after the last call and then runs: alert("c")
+// a função de redução espera 1000ms após a última chamada e depois executa: alert("c")
```
-Now a practical example. Let's say, the user types something, and we'd like to send a request to the server when the input is finished.
+Agora um exemplo prático. Digamos, que o utilizador digita algo, e gostaríamos de enviar uma requisição a servidor quando a entrada for terminada.
-There's no point in sending the request for every character typed. Instead we'd like to wait, and then process the whole result.
+Não faz sentido enviar uma requisição por cada carácter digitado. Em vez disto, gostaríamos de esperar e depois processar todo o resultado.
-In a web-browser, we can setup an event handler -- a function that's called on every change of an input field. Normally, an event handler is called very often, for every typed key. But if we `debounce` it by 1000ms, then it will be only called once, after 1000ms after the last input.
+Num navegador da Web, podemos configurar um manipulador de evento -- uma função que é chamada sobre toda mudança dum campo de entrada. Normalmente, um manipulador de evento é chamado com muita frequência, para toda tecla digitada. Mas se usássemos `debounce` nesta por 1000ms, então apenas será chamada uma vez, após 1000ms depois da última entrada.
```online
-In this live example, the handler puts the result into a box below, try it:
+Neste exemplo ao vivo, o manipulador coloca o resultado numa caixa abaixo, experimenta:
[iframe border=1 src="debounce" height=200]
-See? The second input calls the debounced function, so its content is processed after 1000ms from the last input.
+Vês? A segunda entrada chama a função reduzida, então o seu conteúdo é processado após 1000ms depois da última entrada.
```
-So, `debounce` is a great way to process a sequence of events: be it a sequence of key presses, mouse movements or something else.
+Portanto, `debounce` é uma excelente maneira de processar uma sequência de eventos: seja uma sequência de pressões de tecla, movimentos de rato ou qualquer outra coisa.
-It waits the given time after the last call, and then runs its function, that can process the result.
+Esta espera o dado tempo depois da última chamada, e depois executa a sua função, que pode processar o resultado.
-The task is to implement `debounce` decorator.
+A tarefa é implementar o decorador `debounce`.
-Hint: that's just a few lines if you think about it :)
+Sugestão: são apenas algumas linhas, se pensarmos bem :)
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/solution.js b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/solution.js
index 8071be9d4..408f9716f 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/solution.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/solution.js
@@ -7,23 +7,28 @@ function throttle(func, ms) {
function wrapper() {
if (isThrottled) {
- // memo last arguments to call after the cooldown
+ // memorizar os últimos argumentos a
+ // chamar depois arrefecimento
savedArgs = arguments;
savedThis = this;
return;
}
- // otherwise go to cooldown state
+ // caso contrário, passa ao estado
+ // de arrefecimento
func.apply(this, arguments);
isThrottled = true;
- // plan to reset isThrottled after the delay
+ // planear reiniciar `isThrottled`
+ // depois do atraso
setTimeout(function() {
isThrottled = false;
if (savedArgs) {
- // if there were calls, savedThis/savedArgs have the last one
- // recursive call runs the function and sets cooldown again
+ // se houve chamadas, `savedThis` ou
+ // `savedArgs` tem a última
+ // a chamada recursiva executa a função
+ // e define novamente o arrefecimento
wrapper.apply(savedThis, savedArgs);
savedArgs = savedThis = null;
}
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/test.js b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/test.js
index e671438f6..04d83bf8a 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/test.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/test.js
@@ -11,33 +11,33 @@ describe("throttle(f, 1000)", function() {
f1000 = throttle(f, 1000);
});
- it("the first call runs now", function() {
- f1000(1); // runs now
+ it("a primeira chamada executa agora", function() {
+ f1000(1); // executa agora
assert.equal(log, "1");
});
- it("then calls are ignored till 1000ms when the last call works", function() {
- f1000(2); // (throttling - less than 1000ms since the last run)
- f1000(3); // (throttling - less than 1000ms since the last run)
- // after 1000 ms f(3) call is scheduled
+ it("então as chamadas são ignoradas até 1000ms quando a última chamada funcionar", function() {
+ f1000(2); // (throttling - menos do que 1000ms desde a última execução)
+ f1000(3); // (throttling - menos do que 1000ms desde a última execução)
+ // depois de 1000ms a chamada f(3) é agendada
- assert.equal(log, "1"); // right now only the 1st call done
+ assert.equal(log, "1"); // agora somente a primeira chamada é feita
- this.clock.tick(1000); // after 1000ms...
- assert.equal(log, "13"); // log==13, the call to f1000(3) is made
+ this.clock.tick(1000); // depois de 1000ms...
+ assert.equal(log, "13"); // log==13, a chamada para f1000(3) é feita
});
- it("the third call waits 1000ms after the second call", function() {
+ it(" a terceira chamada espera 1000ms depois da segunda chamada", function() {
this.clock.tick(100);
- f1000(4); // (throttling - less than 1000ms since the last run)
+ f1000(4); // (regulação - menos do que 1000ms desde a última execução)
this.clock.tick(100);
- f1000(5); // (throttling - less than 1000ms since the last run)
+ f1000(5); // (regulação - menos do que 1000ms desde a última execução)
this.clock.tick(700);
- f1000(6); // (throttling - less than 1000ms since the last run)
+ f1000(6); // (regulação - menos do que 1000ms desde a última execução)
- this.clock.tick(100); // now 100 + 100 + 700 + 100 = 1000ms passed
+ this.clock.tick(100); // agora 100 + 100 + 700 + 100 = 1000ms se passaram
- assert.equal(log, "136"); // the last call was f(6)
+ assert.equal(log, "136"); // a última chamada foi f(6)
});
after(function() {
@@ -48,14 +48,14 @@ describe("throttle(f, 1000)", function() {
describe('throttle', () => {
- it('runs a forwarded call once', done => {
+ it('executa uma chamada encaminhada uma vez', done => {
let log = '';
const f = str => log += str;
const f10 = throttle(f, 10);
f10('once');
setTimeout(() => {
- assert.equal(log, 'once');
+ assert.equal(log, 'uma vez');
done();
}, 20);
});
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/solution.md b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/solution.md
index 6950664be..a3950761e 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/solution.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/solution.md
@@ -29,10 +29,10 @@ function throttle(func, ms) {
}
```
-A call to `throttle(func, ms)` returns `wrapper`.
+Uma chamada a `throttle(func, ms)` retorna `wrapper`.
-1. During the first call, the `wrapper` just runs `func` and sets the cooldown state (`isThrottled = true`).
-2. In this state all calls are memorized in `savedArgs/savedThis`. Please note that both the context and the arguments are equally important and should be memorized. We need them simultaneously to reproduce the call.
-3. After `ms` milliseconds pass, `setTimeout` triggers. The cooldown state is removed (`isThrottled = false`) and, if we had ignored calls, `wrapper` is executed with the last memorized arguments and context.
+1. Durante a primeira chamada, o `wrapper` apenas executa a `func` e define o estado de arrefecimento (`isThrottled = true`).
+2. Neste estado todas as chamadas são memorizadas em `savedArgs/savedThis`. É de notar que tanto o contexto como os argumentos são igualmente importantes e devem ser memorizados. Nós precisamos destes simultaneamente para reproduzir a chamada.
+3. Após `ms` milissegundos, `setTimeout` é acionada. O estado de arrefecimento é removido (`isThrottled = false`) e, se tivermos ignorado chamadas, o `wrapper` é executado com os últimos argumentos e contexto memorizados.
-The 3rd step runs not `func`, but `wrapper`, because we not only need to execute `func`, but once again enter the cooldown state and setup the timeout to reset it.
+O terceiro passo não executa a `func`, mas sim o `wrapper`, porque não só precisamos de executar a `func`, como também entrar novamente no estado de arrefecimento e configurar o tempo de espera para reiniciá-lo.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/task.md b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/task.md
index cbd473196..17ae38ad1 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/task.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/task.md
@@ -2,52 +2,53 @@ importance: 5
---
-# Throttle decorator
+# Decorador Regulador
-Create a "throttling" decorator `throttle(f, ms)` -- that returns a wrapper.
+Crie um decorador de "regulação" `throttle(f, ms)` -- que retorna uma função envolvente.
-When it's called multiple times, it passes the call to `f` at maximum once per `ms` milliseconds.
+Quando é chamado várias vezes, este passa a chamada a `f` no máximo uma vez por `ms` milissegundos.
-Compared to the debounce decorator, the behavior is completely different:
-- `debounce` runs the function once after the "cooldown" period. Good for processing the final result.
-- `throttle` runs it not more often than given `ms` time. Good for regular updates that shouldn't be very often.
+Em comparação com o decorador de redução, o comportamento é completamente diferente:
+- `debounce` executa a função uma vez após o período de "arrefecimento". Bom para processar o resultado final.
+- `throttle` executa a função não mais frequentemente do que o tempo dado `ms`. Bom para atualizações regulares que não devem ser muito frequentes.
-In other words, `throttle` is like a secretary that accepts phone calls, but bothers the boss (calls the actual `f`) not more often than once per `ms` milliseconds.
+Por outras palavras, `throttle` é como uma secretária que aceita chamadas telefónicas, mas que incomoda a chefe (chama a verdadeira `f`) não mais do que uma vez por `ms` milissegundos.
-Let's check the real-life application to better understand that requirement and to see where it comes from.
+Vejamos a aplicação na realidade para compreender melhor este requisito e ver de onde vem.
-**For instance, we want to track mouse movements.**
+**Por exemplo, queremos rastrear movimentos do rato**
-In a browser we can setup a function to run at every mouse movement and get the pointer location as it moves. During an active mouse usage, this function usually runs very frequently, can be something like 100 times per second (every 10 ms).
-**We'd like to update some information on the web-page when the pointer moves.**
+Num navegador, podemos configurar uma função para ser executada em cada movimento do rato e obter a localização do ponteiro à medida que este se move. Durante uma utilização ativa do rato, esta função é normalmente executada com muita frequência, podendo ser algo como 100 vezes por segundo (a cada 10 milissegundos).**Gostaríamos de atualizar algumas informações na página da Web quando o ponteiro se move.**
-...But updating function `update()` is too heavy to do it on every micro-movement. There is also no sense in updating more often than once per 100ms.
+...Mas a função de atualização `update()` é demasiado pesada para o fazer em cada micro-movimento. Também não faz sentido atualizar mais do que uma vez por 100ms.
-So we'll wrap it into the decorator: use `throttle(update, 100)` as the function to run on each mouse move instead of the original `update()`. The decorator will be called often, but forward the call to `update()` at maximum once per 100ms.
+Por isso, a envolveremos no decorador: usamos `throttle(update, 100)` como uma função a ser executada em cada movimento do rato, em vez da `update` original. O decorador será chamado frequentemente, mas encaminhará a chamada a `update` no máximo uma vez a cada 100ms.
-Visually, it will look like this:
+Visualmente, terá o seguinte aspeto:
-1. For the first mouse movement the decorated variant immediately passes the call to `update`. That's important, the user sees our reaction to their move immediately.
-2. Then as the mouse moves on, until `100ms` nothing happens. The decorated variant ignores calls.
-3. At the end of `100ms` -- one more `update` happens with the last coordinates.
-4. Then, finally, the mouse stops somewhere. The decorated variant waits until `100ms` expire and then runs `update` with last coordinates. So, quite important, the final mouse coordinates are processed.
+1. Para o primeiro movimento do rato a variante decorada passa a chamada para `update`. É importante que o usuário veja a nossa reação aos seus movimentos imediatamente.
+1. Para o primeiro movimento do rato, a variante decorada passa imediatamente a chamada a `update`. Isso é importante, o usuário vê a nossa reação ao seu movimento imediatamente.
+2. Depois, à medida que o rato se move, até `100ms` nada acontece. A variante decorada ignora as chamadas.
+3. No final de `100ms` -- mais uma `update` acontece com as últimas coordenadas.
+4. Então, finalmente, o rato para em algum lugar. A variante decorada espera até `100ms` expiraram e depois executa a `update` com as últimas coordenadas. Assim, o mais importante, as últimas coordenadas do rato são processadas.
-A code example:
+
+Um exemplo de código:
```js
function f(a) {
console.log(a);
}
-// f1000 passes calls to f at maximum once per 1000 ms
+// f1000 passa chamadas a `f` no máximo uma vez por 1000 ms
let f1000 = throttle(f, 1000);
-f1000(1); // shows 1
-f1000(2); // (throttling, 1000ms not out yet)
-f1000(3); // (throttling, 1000ms not out yet)
+f1000(1); // exibe 1
+f1000(2); // (regulação, 1000ms ainda não passaram)
+f1000(3); // (regulação, 1000ms ainda não passaram)
-// when 1000 ms time out...
-// ...outputs 3, intermediate value 2 was ignored
+// quando o tempo de 1000ms se esgota...
+// ...exibe 3, o valor intermédio 2 foi ignorado
```
-P.S. Arguments and the context `this` passed to `f1000` should be passed to the original `f`.
+P.S. Os argumentos e o contexto de `this` passados a `f1000` devem ser passados a `f` original.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/article.md b/1-js/06-advanced-functions/09-call-apply-decorators/article.md
index c5d785493..4aacc35b7 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/article.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/article.md
@@ -1,20 +1,20 @@
-# Decorators and forwarding, call/apply
+# Decoradores e reencaminhamento, chamar/aplicar
-JavaScript gives exceptional flexibility when dealing with functions. They can be passed around, used as objects, and now we'll see how to *forward* calls between them and *decorate* them.
+A JavaScript oferece uma flexibilidade excecional ao lidar com funções. Podem ser transmitidas, utilizadas como objetos, e agora veremos como *encaminhar* chamadas entre elas e *decorá-las*.
-## Transparent caching
+## Memorização transparente
-Let's say we have a function `slow(x)` which is CPU-heavy, but its results are stable. In other words, for the same `x` it always returns the same result.
+Digamos que temos uma função `slow(x)` que consume muito processamento, mas seus resultados são estáveis. Em outras palavras, para o mesmo `x` esta sempre retorna o mesmo resultado.
-If the function is called often, we may want to cache (remember) the results to avoid spending extra-time on recalculations.
+Se a função for chamada com frequência, podemos querer memorizar (lembrar) os resultados para evitar gastar tempo adicional em recálculos.
-But instead of adding that functionality into `slow()` we'll create a wrapper function, that adds caching. As we'll see, there are many benefits of doing so.
+Mas, em vez de adicionar essa funcionalidade em `slow()` criaremos uma função de embrulho, que adiciona a memorização. Como veremos, existem muitas vantagens em fazê-lo.
-Here's the code, and explanations follow:
+Eis o código, e as explicações que se seguem:
```js run
function slow(x) {
- // there can be a heavy CPU-intensive job here
+ // pode haver um processamento intensivo aqui
alert(`Called with ${x}`);
return x;
}
@@ -23,65 +23,67 @@ function cachingDecorator(func) {
let cache = new Map();
return function(x) {
- if (cache.has(x)) { // if there's such key in cache
- return cache.get(x); // read the result from it
+ if (cache.has(x)) { // se existir tal chave na memória
+ return cache.get(x); // ler o resultado do mesmo
}
- let result = func(x); // otherwise call func
+ let result = func(x); // caso contrário, chamar função
- cache.set(x, result); // and cache (remember) the result
+ cache.set(x, result); // e memorizar (lembrar) o resultado
+
return result;
};
}
slow = cachingDecorator(slow);
-alert( slow(1) ); // slow(1) is cached and the result returned
-alert( "Again: " + slow(1) ); // slow(1) result returned from cache
+alert( slow(1) ); // slow(1) é memorizado e o resultado retornado
+alert( "Again: " + slow(1) ); // resultado da slow(1) retornado da memória
-alert( slow(2) ); // slow(2) is cached and the result returned
-alert( "Again: " + slow(2) ); // slow(2) result returned from cache
+alert( slow(2) ); // slow(2) é memorizado e o resultado retornado
+alert( "Again: " + slow(2) ); // resultado da slow(2) retornado da memória
```
-In the code above `cachingDecorator` is a *decorator*: a special function that takes another function and alters its behavior.
+No código acima `cachingDecorator` é um *decorador*: uma função especial que pega em outra função e altera o seu comportamento.
-The idea is that we can call `cachingDecorator` for any function, and it will return the caching wrapper. That's great, because we can have many functions that could use such a feature, and all we need to do is to apply `cachingDecorator` to them.
+A ideia é que podemos chamar `cachingDecorator` para qualquer função, e esta retornará o embrulho de memorização. Isto é ótimo, porque podemos ter muitas funções que poderiam usar esse recurso, e tudo o que precisamos fazer é aplicar `cachingDecorator` a elas.
-By separating caching from the main function code we also keep the main code simpler.
+Ao separar a memorização do código da função principal, também mantemos o código principal mais simples.
-The result of `cachingDecorator(func)` is a "wrapper": `function(x)` that "wraps" the call of `func(x)` into caching logic:
+O resultado de `caching` é um "embrulho": `function(x)` que "embrulha" a chama da `func(x)` na lógica de memorização:

-From an outside code, the wrapped `slow` function still does the same. It just got a caching aspect added to its behavior.
+A partir dum código externo, a função `slow` embrulhada ainda faz o mesmo. Esta apenas tem um aspeto de memorização adicionado ao seu comportamento.
-To summarize, there are several benefits of using a separate `cachingDecorator` instead of altering the code of `slow` itself:
+Para resumir, existem vários benefícios em utilizar um `cachingDecorator` separado ao invés de alterar o código da `slow` em si:
-- The `cachingDecorator` is reusable. We can apply it to another function.
-- The caching logic is separate, it did not increase the complexity of `slow` itself (if there was any).
-- We can combine multiple decorators if needed (other decorators will follow).
+- O `cachingDecorator` é reutilizável. Podemos aplicá-lo a outra função.
+- A lógica de memorização é separada, não aumentou a complexidade da `slow` em si (se é que existia alguma).
+- Podemos combinar vários decoradores, se necessário (outros decoradores seguir-se-ão).
-## Using "func.call" for the context
+## Usando `func.call` para o contexto
-The caching decorator mentioned above is not suited to work with object methods.
+O decorador de memorização mencionado acima não é adequado para trabalhar com o métodos de objeto.
-For instance, in the code below `worker.slow()` stops working after the decoration:
+Por exemplo, no código abaixo `worker.slow()` para de funcionar após a decoração:
```js run
-// we'll make worker.slow caching
+// faremos a memorização do `worker.slow`
let worker = {
someMethod() {
return 1;
},
slow(x) {
- // scary CPU-heavy task here
+ // tarefa de processamento
+ // assustadoramente pesado.
alert("Called with " + x);
return x * this.someMethod(); // (*)
}
};
-// same code as before
+// o mesmo código que o anterior
function cachingDecorator(func) {
let cache = new Map();
return function(x) {
@@ -96,49 +98,50 @@ function cachingDecorator(func) {
};
}
-alert( worker.slow(1) ); // the original method works
+alert( worker.slow(1) ); // o método original funciona
-worker.slow = cachingDecorator(worker.slow); // now make it caching
+worker.slow = cachingDecorator(worker.slow); // agora, memorize-o
*!*
-alert( worker.slow(2) ); // Whoops! Error: Cannot read property 'someMethod' of undefined
+alert( worker.slow(2) ); // Ups! Erro: Não é possível ler a 'someMethod' de indefinido
*/!*
```
-The error occurs in the line `(*)` that tries to access `this.someMethod` and fails. Can you see why?
+O erro ocorre na linha `(*)` que tenta acessar a `this.someMethod` e falha. Podemos ver por quê?
-The reason is that the wrapper calls the original function as `func(x)` in the line `(**)`. And, when called like that, the function gets `this = undefined`.
+A razão é que o embrulhador chama a função original como `func(x)` na linha `(**)`. E, quando chamada desta maneira, a função recebe `this = undefined`.
-We would observe a similar symptom if we tried to run:
+Observaríamos um sintoma semelhante se tentássemos executar:
```js
let func = worker.slow;
func(2);
```
-So, the wrapper passes the call to the original method, but without the context `this`. Hence the error.
+Assim, o embrulhador passa a chamada para o método original, mas sem o contexto `this`. Daí o erro.
-Let's fix it.
+Vamos corrigi-lo.
-There's a special built-in function method [func.call(context, ...args)](mdn:js/Function/call) that allows to call a function explicitly setting `this`.
+Existe uma método especial de função embutido [`func.call(context, ...args)`](mdn:js/Function/call) que permite chamar uma função definindo explicitamente `this`.
-The syntax is:
+A sintaxe é:
```js
func.call(context, arg1, arg2, ...)
```
-It runs `func` providing the first argument as `this`, and the next as the arguments.
+Ele executa `func` fornecendo o primeiro argumento como `this`, e o próximo como os argumentos.
+
+Para simplificar, estas duas chamadas fazem quase o mesmo:
-To put it simply, these two calls do almost the same:
```js
func(1, 2, 3);
func.call(obj, 1, 2, 3)
```
-They both call `func` with arguments `1`, `2` and `3`. The only difference is that `func.call` also sets `this` to `obj`.
+Ambas chamam `func` com os argumentos `1`, `2`, e `3`. A única diferença é que `func.call` também define `this` como `obj`.
-As an example, in the code below we call `sayHi` in the context of different objects: `sayHi.call(user)` runs `sayHi` providing `this=user`, and the next line sets `this=admin`:
+Como exemplo, no código abaixo chamamos `sayHi` no contexto de diferentes objetos: `sayHi.call(user)` executa `sayHi` fornecendo `this=user`, e a próxima linha define `this=admin`:
```js run
function sayHi() {
@@ -148,13 +151,13 @@ function sayHi() {
let user = { name: "John" };
let admin = { name: "Admin" };
-// use call to pass different objects as "this"
+// usar `call` para passar
+// diferentes objetos como "this"
sayHi.call( user ); // John
sayHi.call( admin ); // Admin
```
-And here we use `call` to call `say` with the given context and phrase:
-
+E aqui usamos `call` para chamar `say` com o dado contexto e frase:
```js run
function say(phrase) {
@@ -163,11 +166,12 @@ function say(phrase) {
let user = { name: "John" };
-// user becomes this, and "Hello" becomes the first argument
+// `user` torna-se `this`, e "Hello"
+// torna-se o primeiro argumento
say.call( user, "Hello" ); // John: Hello
```
-In our case, we can use `call` in the wrapper to pass the context to the original function:
+No nosso caso, podemos usar `call` no embrulhador para passar o contexto para a função original:
```js run
let worker = {
@@ -188,57 +192,57 @@ function cachingDecorator(func) {
return cache.get(x);
}
*!*
- let result = func.call(this, x); // "this" is passed correctly now
+ let result = func.call(this, x); // "this" é agora passado corretamente
*/!*
cache.set(x, result);
return result;
};
}
-worker.slow = cachingDecorator(worker.slow); // now make it caching
+worker.slow = cachingDecorator(worker.slow); // agora, memoriza-o
-alert( worker.slow(2) ); // works
-alert( worker.slow(2) ); // works, doesn't call the original (cached)
+alert( worker.slow(2) ); // funciona
+alert( worker.slow(2) ); // funciona, não chama o original (memorizado)
```
-Now everything is fine.
+Agora está tudo bem.
-To make it all clear, let's see more deeply how `this` is passed along:
+Para tornar tudo mais claro, veremos mais profundamente como `this` é passado adiante:
-1. After the decoration `worker.slow` is now the wrapper `function (x) { ... }`.
-2. So when `worker.slow(2)` is executed, the wrapper gets `2` as an argument and `this=worker` (it's the object before dot).
-3. Inside the wrapper, assuming the result is not yet cached, `func.call(this, x)` passes the current `this` (`=worker`) and the current argument (`=2`) to the original method.
+1. Após a decoração, `worker.slow` agora é o embrulhador `function (x) { ... }`.
+2. Então quando `worker.slow(2)` é executado, o embrulhador recebe `2` como argumento e `this=worker` (é o objeto antes do ponto).
+3. Dentro do embrulhador, assumindo que o resultado ainda não está memorizado, `func.call(this, x)` passa o `this` atual (`=worker`) e o argumento atual (`=2`) para o método original.
-## Going multi-argument
+## Passando vários argumentos
-Now let's make `cachingDecorator` even more universal. Till now it was working only with single-argument functions.
+Agora vamos tornar o `cachingDecorator` ainda mais universal. Até agora este estava trabalhando apenas com funções de um único argumento.
-Now how to cache the multi-argument `worker.slow` method?
+Agora, como memorizar o método `worker.slow` com vários argumentos?
```js
let worker = {
slow(min, max) {
- return min + max; // scary CPU-hogger is assumed
+ return min + max; // assume-se que é assustadoramente devoradora de processamento
}
};
-// should remember same-argument calls
+// deve lembrar-se das chamadas com o mesmo argumento
worker.slow = cachingDecorator(worker.slow);
```
-Previously, for a single argument `x` we could just `cache.set(x, result)` to save the result and `cache.get(x)` to retrieve it. But now we need to remember the result for a *combination of arguments* `(min,max)`. The native `Map` takes single value only as the key.
+Anteriormente, para um único argumento, `x` poderíamos simplesmente `cache.set(x, result)` para guardar o resultado e `cache.get(x)` para recuperá-lo. Mas agora precisamos lembrar o resultado para uma *combinação de argumentos* `(min,max)`. O `Map` nativo recebe apenas um único valor como chave.
-There are many solutions possible:
+Existem muitas soluções possíveis:
-1. Implement a new (or use a third-party) map-like data structure that is more versatile and allows multi-keys.
-2. Use nested maps: `cache.set(min)` will be a `Map` that stores the pair `(max, result)`. So we can get `result` as `cache.get(min).get(max)`.
-3. Join two values into one. In our particular case we can just use a string `"min,max"` as the `Map` key. For flexibility, we can allow to provide a *hashing function* for the decorator, that knows how to make one value from many.
+1. Implementar uma nova estrutura de dados parecida com o mapa (ou usar uma estrutura de terceiros) que seja mais versátil e permita várias chaves.
+2. Usar mapas aninhados: `cache.set(min)` será um `Map` que armazena o par `(max, result)`. Assim, podemos obter o `result` como `cache.get(min).get(max)`.
+3. Juntar dois valores num só. No nosso caso particular, podemos usar uma sequência de caracteres `min,max` como chave do `Map`. Para maior flexibilidade, podemos permitir fornecer uma *função de baralhamento* para o decorador, que sabe como fazer um valor a partir de muitos.
-For many practical applications, the 3rd variant is good enough, so we'll stick to it.
+Para muitas aplicações práticas, a terceira variante é suficientemente boa, pelo que ficaremos por ela.
-Also we need to pass not just `x`, but all arguments in `func.call`. Let's recall that in a `function()` we can get a pseudo-array of its arguments as `arguments`, so `func.call(this, x)` should be replaced with `func.call(this, ...arguments)`.
+Também precisamos passar não apenas `x`, mas todos os argumentos na `func.call`. Lembremos que numa `func.call` podemos obter um pseudo-vetor dos seus argumentos como `arguments`, então `func.call(this, x)` deve ser substituído por `func.call(this, ...arguments)`.
-Here's a more powerful `cachingDecorator`:
+Eis um `cachingDecorator` mais poderoso:
```js run
let worker = {
@@ -273,50 +277,50 @@ function hash(args) {
worker.slow = cachingDecorator(worker.slow, hash);
-alert( worker.slow(3, 5) ); // works
-alert( "Again " + worker.slow(3, 5) ); // same (cached)
+alert( worker.slow(3, 5) ); // funciona
+alert( "Again " + worker.slow(3, 5) ); // o mesmo (memorizado)
```
-Now it works with any number of arguments (though the hash function would also need to be adjusted to allow any number of arguments. An interesting way to handle this will be covered below).
+Agora funciona com qualquer número de argumentos (embora a função de baralhar também precise de ser ajustada para permitir qualquer número de argumentos. Uma maneira interessante de lidar com isto será abordada mais adiante).
-There are two changes:
+Existem duas alterações:
-- In the line `(*)` it calls `hash` to create a single key from `arguments`. Here we use a simple "joining" function that turns arguments `(3, 5)` into the key `"3,5"`. More complex cases may require other hashing functions.
-- Then `(**)` uses `func.call(this, ...arguments)` to pass both the context and all arguments the wrapper got (not just the first one) to the original function.
+- Na linha `(*)` chama `hash` para criar uma única chave a partir de `arguments`. Neste caso usamos uma função simples de "junção" que transforma os argumentos `(3,5)` na chave `"3,5"`. Os casos mais complexos podem exigir outras funções de baralhamento.
+- Então `(**)` usa `func.call(this, ...arguments)` para passar tanto o contexto quanto todos os argumentos que o embrulhador recebeu (não apenas o primeiro) para a função original.
-## func.apply
+## `func.apply`
-Instead of `func.call(this, ...arguments)` we could use `func.apply(this, arguments)`.
+Em vez de `func.call(this, ...arguments)` poderíamos usar `func.apply(this, arguments)`.
-The syntax of built-in method [func.apply](mdn:js/Function/apply) is:
+A sintaxe do método embutido [`func.apply`](mdn:js/Function/apply) é:
```js
func.apply(context, args)
```
-It runs the `func` setting `this=context` and using an array-like object `args` as the list of arguments.
+Este executa a `func` definindo `this=context` e usando um objeto parecido com vetor `args` como lista de argumentos.
-The only syntax difference between `call` and `apply` is that `call` expects a list of arguments, while `apply` takes an array-like object with them.
+A única diferença entre `call` e `apply` é que `call` espera uma lista de argumentos, enquanto `apply` recebe um objeto parecido com vetor com eles.
-So these two calls are almost equivalent:
+Assim, estas duas chamadas são quase equivalentes:
```js
func.call(context, ...args);
func.apply(context, args);
```
-They perform the same call of `func` with given context and arguments.
+Estas realizam a mesma chama de `func` com dado contexto e argumentos.
-There's only a subtle difference regarding `args`:
+Existe apenas uma diferença subtil em relação a `args`:
-- The spread syntax `...` allows to pass *iterable* `args` as the list to `call`.
-- The `apply` accepts only *array-like* `args`.
+- A sintaxe de propagação `...` permite passar `args` *iteráveis* como lista a `call`.
+- O `apply` aceita apenas `args` *parecidos com vetor*.
-...And for objects that are both iterable and array-like, such as a real array, we can use any of them, but `apply` will probably be faster, because most JavaScript engines internally optimize it better.
+...E para objetos que são simultaneamente iteráveis e semelhantes a um vetor, tais como um vetor de verdade, podemos usar qualquer um destes, mas `apply` será provavelmente mais rápido, porque a maioria dos motores de JavaScript otimizam-o internamente melhor.
-Passing all arguments along with the context to another function is called *call forwarding*.
+A passagem de todos os argumentos juntamente com o contexto a outra função chama-se **encaminhamento de chamada**.
-That's the simplest form of it:
+Esta é a maneira mais simples de o fazer:
```js
let wrapper = function() {
@@ -324,11 +328,11 @@ let wrapper = function() {
};
```
-When an external code calls such `wrapper`, it is indistinguishable from the call of the original function `func`.
+Quando um código externo chama este `wrapper`, é indistinguível da chamada da função original `func`.
-## Borrowing a method [#method-borrowing]
+## Emprestando um método [#method-borrowing]
-Now let's make one more minor improvement in the hashing function:
+Agora vamos fazer mais uma pequena melhoria na função de baralhamento:
```js
function hash(args) {
@@ -336,9 +340,9 @@ function hash(args) {
}
```
-As of now, it works only on two arguments. It would be better if it could glue any number of `args`.
+De momento, funciona apenas com dois argumentos. Seria melhor se pudesse colar qualquer número de `args`.
-The natural solution would be to use [arr.join](mdn:js/Array/join) method:
+A solução natural seria usar o método [`arr.join`](mdn:js/Array/join):
```js
function hash(args) {
@@ -346,21 +350,21 @@ function hash(args) {
}
```
-...Unfortunately, that won't work. Because we are calling `hash(arguments)`, and `arguments` object is both iterable and array-like, but not a real array.
+...Infelizmente, isso não funcionará. Porque estamos chamando `hash(arguments)`, e o objeto `arguments` é tanto iterável quanto semelhante a um vetor, mas não um vetor de verdade.
-So calling `join` on it would fail, as we can see below:
+Por isso, chamar `join` sobre este falharia, como podemos ver abaixo:
```js run
function hash() {
*!*
- alert( arguments.join() ); // Error: arguments.join is not a function
+ alert( arguments.join() ); // Error: `arguments.join` não é uma função
*/!*
}
hash(1, 2);
```
-Still, there's an easy way to use array join:
+No entanto, existe uma maneira fácil de usar a junção de vetor:
```js run
function hash() {
@@ -372,48 +376,48 @@ function hash() {
hash(1, 2);
```
-The trick is called *method borrowing*.
+O truque chama-se *empréstimo de método*.
-We take (borrow) a join method from a regular array (`[].join`) and use `[].join.call` to run it in the context of `arguments`.
+Nós pegamos (emprestamos) um método de junção dum vetor normal (`[].join`) e usamos `[].join.call()` para executá-lo no contexto de `arguments`.
-Why does it work?
+Por que é que funciona?
-That's because the internal algorithm of the native method `arr.join(glue)` is very simple.
+Isto acontece porque o algoritmo interno do método nativo `arr.join(glue)` é muito simples.
-Taken from the specification almost "as-is":
+Retirado da especificação quase "tal e qual":
-1. Let `glue` be the first argument or, if no arguments, then a comma `","`.
-2. Let `result` be an empty string.
-3. Append `this[0]` to `result`.
-4. Append `glue` and `this[1]`.
-5. Append `glue` and `this[2]`.
-6. ...Do so until `this.length` items are glued.
-7. Return `result`.
+1. Deixar `glue` ser o primeiro argumento, ou se não existirem argumentos, então uma vírgula `","`.
+2. Deixar `result` ser uma sequência de caracteres vazia.
+3. Anexar `this[0]` ao `result`.
+4. Anexar `glue` e `this[1]`.
+5. Anexar `glue` e `this[2]`.
+6. ...Fazer isto até que itens de `this.length` estejam colados.
+7. Retornar `result`.
-So, technically it takes `this` and joins `this[0]`, `this[1]` ...etc together. It's intentionally written in a way that allows any array-like `this` (not a coincidence, many methods follow this practice). That's why it also works with `this=arguments`.
+Então, tecnicamente este recebe `this` e junta `this[0]`, `this[1]` ...etc. Foi intencionalmente escrito de maneira a permitir qualquer `this` parecido com vetor (não por coincidência, muitos métodos seguem essa prática). É por isto que este também funciona com `this=arguments`.
-## Decorators and function properties
+## Decoradores e propriedades de função
-It is generally safe to replace a function or a method with a decorated one, except for one little thing. If the original function had properties on it, like `func.calledCount` or whatever, then the decorated one will not provide them. Because that is a wrapper. So one needs to be careful if one uses them.
+É geralmente seguro substituir uma função ou um método por um decorado, exceto por uma pequena coisa. Se a função original tinha propriedades, como `func.calledCount` ou qualquer outra, então a função decorada não as fornecerá. Porque isso é um embrulhador. Portanto, é preciso ter cuidado ao usá-las.
-E.g. in the example above if `slow` function had any properties on it, then `cachingDecorator(slow)` is a wrapper without them.
+Por exemplo, no exemplo acima se a função `slow` tivesse algum propriedade, então `cachingDecorator(slow)` é um embrulhador sem estas.
-Some decorators may provide their own properties. E.g. a decorator may count how many times a function was invoked and how much time it took, and expose this information via wrapper properties.
+Alguns decoradores podem fornecer as suas propriedades. Por exemplo, um decorador pode contar quantas vezes uma função foi invocada e quanto tempo demorou, e expor esta informação através das propriedades do embrulhador.
-There exists a way to create decorators that keep access to function properties, but this requires using a special `Proxy` object to wrap a function. We'll discuss it later in the article