Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Decorators and forwarding, call/apply#205

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
vplentinax merged 11 commits intojavascript-tutorial:masterfromvplentinax:decorators
Jul 3, 2020
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
11 commits
Select commitHold shift + click to select a range
c48b45d
decorators
vplentinaxMay 24, 2020
af63975
Merge branch 'master' into decorators
joaquinelioJun 2, 2020
2b55933
Update 1-js/06-advanced-functions/09-call-apply-decorators/02-delay/t…
vplentinaxJul 1, 2020
6459ac4
Update 1-js/06-advanced-functions/09-call-apply-decorators/04-throttl…
vplentinaxJul 1, 2020
41121bb
Update 1-js/06-advanced-functions/09-call-apply-decorators/article.md
vplentinaxJul 1, 2020
4d76e41
Update 1-js/06-advanced-functions/09-call-apply-decorators/article.md
vplentinaxJul 1, 2020
771a79f
Update 1-js/06-advanced-functions/09-call-apply-decorators/article.md
vplentinaxJul 1, 2020
fd754f1
Update 1-js/06-advanced-functions/09-call-apply-decorators/article.md
vplentinaxJul 1, 2020
5de203e
Update 1-js/06-advanced-functions/09-call-apply-decorators/article.md
vplentinaxJul 1, 2020
266ca70
Update 1-js/06-advanced-functions/09-call-apply-decorators/article.md
vplentinaxJul 1, 2020
c0a8b2f
Update 1-js/06-advanced-functions/09-call-apply-decorators/article.md
vplentinaxJul 1, 2020
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
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
The wrapper returned by `spy(f)`should store all arguments and then use`f.apply`to forward the call.
El contenedor devuelto por `spy(f)`debe almacenar todos los argumentos y luego usar`f.apply`para reenviar la llamada.
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,17 +2,17 @@ importance: 5

---

#Spy decorator
#Decorador espía

Create a decorator `spy(func)`that should return a wrapper that saves all calls to function in its`calls` property.
Cree un decorador `spy(func)`que debería devolver un contenedor que guarde todas las llamadas para que funcionen en su propiedad`calls`

Every call is saved as an arrayof arguments.
Cada llamada se guarda como un arrayde argumentos.

For instance:
Por ejemplo

```js
function work(a, b) {
alert( a + b ); // workis an arbitrary function or method
alert( a + b ); // workes una función o método arbitrario
}

*!*
Expand All@@ -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.D Ese decorador a veces es útil para pruebas unitarias. Su forma avanzada es `sinon.spy`en la librería[Sinon.JS](http://sinonjs.org/).
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
The solution:
Solución:

```js run demo
function delay(f, ms) {
Expand All@@ -11,22 +11,22 @@ function delay(f, ms) {

let f1000 = delay(alert, 1000);

f1000("test"); //shows "test"after 1000ms
f1000("test"); //mostrar "test"después de 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.
Tenga en cuenta cómo se utiliza una función de flecha aquí. Como sabemos, las funciones de flecha no tienen contextos propios`this`ni `argumentos`,por lo que`f.apply(this, arguments)`toma `this`y `arguments`del contenedor.

If we pass a regular function, `setTimeout`would call it without arguments and`this=window` (assuming we're in the browser).
Si pasamos una función regular, `setTimeout`lo llamaría sin argumentos y`this =window` (suponiendo que estemos en el navegador).

We still can pass the right`this`by using an intermediatevariable, but that's a little bit more cumbersome:
Todavía podemos pasar el`this`correcto usando unavariable intermedia, pero eso es un poco más engorroso:

```js
function delay(f, ms) {

return function(...args) {
let savedThis = this; //store this into an intermediatevariable
let savedThis = this; //almacenar esto en unavariable intermedia
setTimeout(function() {
f.apply(savedThis, args); //use it here
f.apply(savedThis, args); //úsalo aquí
}, ms);
};

Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,25 +2,25 @@ importance: 5

---

#Delaying decorator
#Decorador de retraso

Create a decorator `delay(f, ms)`that delays each call of `f`by `ms`milliseconds.
Cree un decorador `delay(f, ms)`que retrase cada llamada de `f`en `ms`milisegundos.

For instance:
Por ejemplo

```js
function f(x) {
alert(x);
}

//create wrappers
//crear contenedores
let f1000 = delay(f, 1000);
let f1500 = delay(f, 1500);

f1000("test"); //shows "test"after 1000ms
f1500("test"); //shows "test"after 1500ms
f1000("test"); //mostrar "test"después de 1000ms
f1500("test"); //mostrar "test"después de 1500ms
```

In other words, `delay(f, ms)`returns a "delayed by `ms`"variant of`f`.
En otras palabras, `delay(f, ms)`devuelve una variante "Retrasada 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`.
En el código anterior, `f`es una función de un solo argumento, pero en esta solución debe pasar todos los argumentos y el contexto `this`.
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -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.

Una llamada a `debounce` devuelve un contenedor wrapper. Cuando se le llama, planifica la llamada a la función original después de los `ms` dados y cancela el tiempo de espera anterior.
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,50 +2,50 @@ importance: 5

---

#Debounce decorator
#Decorador debounce

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.
El resultado del decorador`debounce(f, ms)`es un contenedor que suspende las llamadas a `f`hasta que haya`ms`milisegundos de inactividad (sin llamadas, "período de enfriamiento"),luego invoca `f`una vez con los últimos argumentos.

For instance, we had a function`f`and replaced it with `f = debounce(f, 1000)`.
Por ejemplo, teníamos una función`f`y la reemplazamos con `f = debounce(f, 1000)`.

Then if the wrapped function is called at 0ms, 200msand 500ms,and then there arenocalls, then the actual `f` will be only called once, at 1500ms.That is: after the cooldown period of 1000ms from the last call.
Entonces, si la función contenedora se llama a 0ms, 200msy 500ms,y luegonohay llamadas, entonces la 'f' real solo se llamará una vez, a 1500ms.Es decir: después del período de enfriamiento de 1000 ms desde la última llamada.

![](debounce.svg)

...And it will get the arguments of the very last call, other calls are ignored.
... Y obtendrá los argumentos de la última llamada, y se ignorarán otras llamadas.

Here's the code for it (uses thedebouncedecorator from the [Lodash library](https://lodash.com/docs/4.17.15#debounce):
Aquí está el código para ello (usa el decoradordebouncedel [Lodash library](https://lodash.com/docs/4.17.15#debounce):

```js
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")
//la función debounce espera 1000 ms después de la última llamada y luego ejecuta: 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.
Ahora un ejemplo práctico. Digamos que el usuario escribe algo y nos gustaría enviar una solicitud al servidor cuando finalice la entrada.

There's no point in sending the request for every character typed. Instead we'd like to wait, and then process the whole result.
No tiene sentido enviar la solicitud para cada caracter escrito. En su lugar, nos gustaría esperar y luego procesar todo el resultado.

In aweb-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 by1000ms,then it will be only called once, after1000msafter the last input.
En un navegadorweb, podemos configurar un controlador de eventos, una función que se llama en cada cambio de un campo de entrada. Normalmente, se llama a un controlador de eventos con mucha frecuencia, por cada tecla escrita. Pero si le pasamos`debounce`por1000ms,entonces solo se llamará una vez, después de1000msdespués de la última entrada.

```online

In this live example, the handler puts the result into a box below, try it:
En este ejemplo en vivo, el controlador coloca el resultado en un cuadro a continuación, pruébelo:

[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.
¿Ve? La segunda entrada llama a la función debounce, por lo que su contenido se procesa después de 1000 ms desde la ú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.
Entonces, `debounce`es una excelente manera de procesar una secuencia de eventos: ya sea una secuencia de pulsaciones de teclas, movimientos del mouse u otra cosa.


It waits the given time after the last call, and then runs its function, that can process the result.
Espera el tiempo dado después de la última llamada y luego ejecuta su función, que puede procesar el resultado.

The task is to implement`debounce` decorator.
La tarea es implementar el decorador`debounce`.

Hint: that's just a few lines if you think about it :)
Sugerencia: son solo algunas líneas si lo piensas :)
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,10 +30,10 @@ function throttle(func, ms) {
}
```

A call to `throttle(func, ms)`returns `wrapper`.
Una llamada a `throttle(func, ms)`devuelve un `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 la primera llamada, el `wrapper`solo ejecuta `func`y establece el estado de enfriamiento (`isThrottled = true`).
2.En este estado, todas las llamadas se memorizan en`savedArgs/savedThis`.Tenga en cuenta que tanto el contexto como los argumentos son igualmente importantes y deben memorizarse. Los necesitamos simultáneamente para reproducir la llamada.
3.Después de que pasan`ms`milisegundos, se activa`setTimeout`. El estado de enfriamiento se elimina(`isThrottled = false`)y, si ignoramos las llamadas,`wrapper`se ejecuta con los últimos argumentos y 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.
El tercer paso no ejecuta `func`,sino `wrapper`,porque no solo necesitamos ejecutar`func`,sino que una vez más ingresamos al estado de enfriamiento y configuramos el tiempo de espera para restablecerlo.
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,50 +2,50 @@ importance: 5

---

#Throttle decorator
#Decorador throttle

Create a"throttling"decorator`throttle(f, ms)` --that returns a wrapper.
Crea un decorador"throttling" `throttle(f, ms)` --que devuelve un contenedor.

When it's called multiple times, it passes the call to`f`at maximum once per`ms`milliseconds.
Cuando se llama varias veces, pasa la llamada a`f`como máximo una vez por`ms`milisegundos.

The difference withdebounce is that it's completely different decorator:
- `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.
La diferencia con *debounce* es que es un decorador completamente diferente:
- `debounce`ejecuta la función una vez después del período de `enfriamiento`. Es bueno para procesar el resultado final.
- `throttle`lo ejecuta no más de lo que se le da en el tiempo`ms`. Es bueno para actualizaciones regulares que no deberían ser muy frecuentes.

Let's check the real-life application to better understand that requirement and to see where it comes from.
Revisemos una aplicación de la vida real para comprender mejor ese requisito y ver de dónde proviene.

**For instance, we want to track mouse movements.**
**Por ejemplo, queremos rastrear los movimientos del mouse.**

In a browser we can setup a function to run at everymousemovement and get the pointer location as it moves. During an active mouse usage, this function usually runs very frequently, can be something like100times per second (every 10 ms).
**We'd like to update some information on the web-page when the pointer moves.**
En un navegador, podemos configurar una función para que se ejecute en cada movimiento delmousey obtener la ubicación del puntero a medida que se mueve. Durante un uso activo del mouse, esta función generalmente se ejecuta con mucha frecuencia, puede ser algo así como100veces por segundo (cada 10 ms).
**Nos gustaría actualizar cierta información en la página web cuando se mueve el puntero.**

...But updating function`update()`is too heavy to do it on everymicro-movement. There is also no sense in updating more often than once per 100ms.
...Pero la función de actualización`update()`es demasiado pesada para hacerlo en cadamicro-movimiento. Tampoco tiene sentido actualizar más de una vez cada 100 ms.

So we'll wrap it into the decorator: use `throttle(update, 100)`as the function to run on each mouse move instead of theoriginal `update()`.The decorator will be called often, but forward the call to `update()`at maximum once per 100ms.
Entonces lo envolveremos en el decorador: use `throttle(update, 100)`como la función para ejecutar en cada movimiento del mouse en lugar deloriginal `update()`.Se llamará al decorador con frecuencia, pero reenviará la llamada a `update()`como máximo una vez cada 100 ms.

Visually, it will look like this:
Visualmente, se verá así:

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 mousestops 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 el primer movimiento del mouse, el variante decorador pasa inmediatamente la llamada a`update`.Eso es importante, el usuario ve nuestra reacción a su movimiento de inmediato
2.Luego, a medida que el mouse avanza, hasta `100ms`no sucede nada. La variante decorador ignora las llamadas.
3.Al final de`100ms` --ocurre un `update`más con las últimas coordenadas.
4.Entonces, finalmente, el mousese detiene en alguna parte. La variante decorador espera hasta que expire`100ms`y luego ejecuta`update`con las últimas coordenadas. Entonces, y esto es bastante importante, se procesan las coordenadas finales del mouse.

A code example:
Un código de ejemplo:

```js
function f(a) {
console.log(a);
}

// f1000passes calls to fat maximum once per 1000 ms
// f1000pasa llamadas a fcomo máximo una vez cada 1000 ms
let f1000 = throttle(f, 1000);

f1000(1); //shows 1
f1000(2); // (throttling, 1000msnot out yet)
f1000(3); // (throttling, 1000msnot out yet)
f1000(1); //muestra 1
f1000(2); // (throttling, 1000msaún no)
f1000(3); // (throttling, 1000msaún no)

//when1000 mstime out...
// ...outputs 3,intermediate value 2 was ignored
//tiempo de espera de1000 ms ...
// ...devuelve 3,el valor intermedio 2 fue ignorado
```

P.S. Arguments and the context`this`passed to `f1000`should be passed to the original`f`.
P.D Los argumentos y el contexto`this`pasado a `f1000`deben pasarse a la`f` original.
Loading

[8]ページ先頭

©2009-2025 Movatter.jp