Skip to content

Commit e906a3c

Browse files
authored
Merge pull request #630 from javascript-tutorial/joaquinelio-patch-2
Decorators Update
2 parents e4786b5 + 071f8c0 commit e906a3c

File tree

6 files changed

+40
-40
lines changed

6 files changed

+40
-40
lines changed

1-js/06-advanced-functions/09-call-apply-decorators/02-delay/solution.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ let f1000 = delay(alert, 1000);
1414
f1000("test"); // mostrar "test" después de 1000ms
1515
```
1616

17-
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 `arguments`, por lo que `f.apply(this, arguments)` toma `this` y `arguments` del contenedor.
17+
Tenga en cuenta cómo se utiliza una función de flecha aquí. Sabemos que las funciones de flecha no tienen contextos propios `this` ni `arguments`, por lo que `f.apply(this, arguments)` toma `this` y `arguments` del contenedor.
1818

19-
Si pasamos una función regular, `setTimeout` lo llamaría sin argumentos y `this = window` (suponiendo que estemos en el navegador).
19+
Si pasamos una función regular, `setTimeout` la llamará sin argumentos y, suponiendo que estemos en el navegador, con `this = window`.
2020

21-
Todavía podemos pasar el `this` correcto usando una variable intermedia, pero eso es un poco más engorroso:
21+
Todavía podemos pasar el `this` correcto usando una variable intermedia, pero eso es algo más engorroso:
2222

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

1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/solution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ function debounce(func, ms) {
99

1010
```
1111

12-
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.
12+
Una llamada a `debounce` devuelve un contenedor "wrapper". Cuando se lo llama, planifica la llamada a la función original después de los `ms` dados y cancela el tiempo de espera anterior.

1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/task.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Entonces, si la función contenedora se llama a 0ms, 200ms y 500ms, y luego no h
1414

1515
![](debounce.svg)
1616

17-
... Y obtendrá los argumentos de la última llamada, y se ignorarán otras llamadas.
17+
... Y obtendrá los argumentos de la última llamada, y se ignoran las otras llamadas.
1818

1919
Aquí está el código para ello (usa el decorador debounce del [Lodash library](https://lodash.com/docs/4.17.15#debounce):
2020

@@ -40,7 +40,7 @@ En este ejemplo en vivo, el controlador coloca el resultado en un cuadro a conti
4040
4141
[iframe border=1 src="debounce" height=200]
4242
43-
¿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.
43+
¿Lo 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.
4444
```
4545

4646
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.

1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/solution.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ function throttle(func, ms) {
2929
}
3030
```
3131

32-
Una llamada a `throttle(func, ms)` devuelve un `wrapper`.
32+
Una llamada a `throttle(func, ms)` devuelve el contenedor `wrapper`.
3333

3434
1. Durante la primera llamada, el `wrapper` solo ejecuta `func` y establece el estado de enfriamiento (`isThrottled = true`).
3535
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.
36-
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.
36+
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.
3737

3838
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.

1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/task.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ importance: 5
44

55
# Decorador throttle
66

7-
Crea un decorador "throttling" `throttle(f, ms)` que devuelve un contenedor.
7+
Crea un decorador "limitador" o "throttling" `throttle(f, ms)` que devuelve un contenedor.
88

99
Cuando se llama varias veces, pasa la llamada a `f` como máximo una vez por `ms` milisegundos.
1010

11-
La diferencia con *debounce* es que es un decorador completamente diferente:
12-
- `debounce` ejecuta la función una vez después del período de `enfriamiento`. Es bueno para procesar el resultado final.
13-
- `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.
11+
Comparado con el decorador *debounce*, el comportamiento es completamente diferente:
12+
- `debounce` ejecuta la función una vez *después* del período de `enfriamiento`. Es bueno para procesar el resultado final.
13+
- `throttle` la ejecuta una y no más veces por el tiempo de `ms` dado. Es bueno para actualizaciones regulares que no deberían ser muy frecuentes.
1414

15-
En otras palabras, "throttle" es como una secretaria que acepta llamadas telefónicas, pero molesta al jefe (llama a la "f" real) no más de una vez por milisegundos `ms`.
15+
En otras palabras, "throttle" es como una secretaria que acepta llamadas telefónicas, pero molesta al jefe (llama a la "f" real) no más de una vez por `ms` milisegundos.
1616

1717
Revisemos una aplicación de la vida real para comprender mejor ese requisito y ver de dónde proviene.
1818

@@ -21,16 +21,16 @@ Revisemos una aplicación de la vida real para comprender mejor ese requisito y
2121
En un navegador, podemos configurar una función para que se ejecute en cada movimiento del mouse y 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í como 100 veces por segundo (cada 10 ms).
2222
**Nos gustaría actualizar cierta información en la página web cuando se mueve el puntero.**
2323

24-
...Pero la función de actualización `update()` es demasiado pesada para hacerlo en cada micro-movimiento. Tampoco tiene sentido actualizar más de una vez cada 100 ms.
24+
... Pero la función de actualización `update()` es demasiado pesada para hacerlo en cada micro-movimiento. Tampoco tiene sentido actualizar más de una vez cada 100 ms.
2525

26-
Entonces lo envolveremos en el decorador: para ejecutar en cada movimiento del mouse, usamos `throttle(update, 100)` en lugar del `update()` original. Se llamará al decorador con frecuencia, pero reenviará la llamada a `update()` como máximo una vez cada 100 ms.
26+
Entonces lo envolveremos en el decorador: para ejecutar en cada movimiento del mouse, usamos `throttle(update, 100)` en lugar del `update()` original. Se llamará al decorador con frecuencia, pero este reenviará la llamada a `update()` como máximo una vez cada 100 ms.
2727

2828
Visualmente, se verá así:
2929

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

3535
Un código de ejemplo:
3636

@@ -50,4 +50,4 @@ f1000(3); // (throttling, 1000ms aún no)
5050
// ...devuelve 3, el valor intermedio 2 fue ignorado
5151
```
5252

53-
P.D Los argumentos y el contexto `this` pasado a `f1000` deben pasarse a la `f` original.
53+
P.D. Los argumentos y el contexto `this` pasado a `f1000` deben pasarse a la `f` original.

1-js/06-advanced-functions/09-call-apply-decorators/article.md

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
# Decoradores y redirecciones, call/apply
22

3-
JavaScript ofrece una flexibilidad excepcional cuando se trata de funciones. Se pueden pasar, usar como objetos, y ahora veremos cómo *redirigir* las llamadas entre ellos y *decorarlos*.
3+
JavaScript ofrece una flexibilidad excepcional cuando se trata de funciones. Se pueden pasar, usar como objetos, y ahora veremos cómo *redirigir* las llamadas entre ellas y *decorarlas*.
44

55
## Caché transparente
66

7-
Digamos que tenemos una función `slow(x)` que es pesada para la CPU, pero sus resultados son estables. En otras palabras, la misma `x` siempre devuelve el mismo resultado.
7+
Digamos que tenemos una función `slow(x)`, que es pesada para la CPU pero cuyos resultados son "estables": es decir que con la misma `x` siempre devuelve el mismo resultado.
88

9-
Si la función se llama con frecuencia, es posible que queramos almacenar en caché (recordar) los resultados para evitar perder tiempo extra en nuevos cálculos.
9+
Si la función se llama con frecuencia, es posible que queramos almacenar en caché (recordar) los resultados obtenidos para evitar perder tiempo en calcularlos de nuevo.
1010

11-
Pero en lugar de agregar esa funcionalidad en `slow()` crearemos una función de contenedor, que agrega almacenamiento en caché. Como veremos, hacer esto trae beneficios.
11+
Pero en lugar de agregar esta funcionalidad en `slow()`, crearemos una función contenedora (en inglés "wrapper", envoltorio) que agregue almacenamiento en caché. Como veremos, hacer esto tiene sus beneficios.
1212

13-
Aquí está el código, y siguiendo las explicaciones:
13+
Aquí está el código, seguido por su explicación:
1414

1515
```js run
1616
function slow(x) {
@@ -29,7 +29,7 @@ function cachingDecorator(func) {
2929

3030
let result = func(x); // de lo contrario llame a func
3131

32-
cache.set(x, result); // y cacheamos (recordamos) el resultado
32+
cache.set(x, result); // y almacenamos en caché (recordamos) el resultado
3333
return result;
3434
};
3535
}
@@ -236,9 +236,9 @@ Hay muchas posibles soluciones:
236236

237237
Para muchas aplicaciones prácticas, la tercera variante es lo suficientemente buena, por lo que nos mantendremos en esa opción.
238238

239-
También necesitamos pasar no solo `x`, sino todos los argumentos en `func.call`. Recordemos que en una `función()` podemos obtener un pseudo-array (*array-like*) de sus argumentos como `arguments`, por lo que `func.call(this, x)` debería reemplazarse por `func.call(this, ...arguments) `.
239+
También necesitamos pasar no solo `x` sino todos los argumentos en `func.call`. Recordemos que en una `función()`, con el uso de `arguments` podemos obtener un pseudo-array de sus argumentos, así que `func.call(this, x)` debería reemplazarse por `func.call(this, ...arguments)`.
240240

241-
Aquí un mejorado y poderosísimo `cachingDecorator`:
241+
Aquí un mejorado y más potente `cachingDecorator`:
242242

243243
```js run
244244
let worker = {
@@ -286,7 +286,7 @@ Hay dos cambios:
286286

287287
## func.apply
288288

289-
En vez de `func.call(this, ...arguments)` nosotros podríamos usar `func.apply(this, arguments)`.
289+
En vez de `func.call(this, ...arguments)`, podríamos usar `func.apply(this, arguments)`.
290290

291291
La sintaxis del método incorporado [func.apply](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Function/apply) es:
292292

@@ -309,10 +309,10 @@ Estas hacen la misma llamada de `func` con el contexto y argumento dados.
309309

310310
Solo hay una sutil diferencia con respect○ a `args`:
311311

312-
- La sintaxis extendida `...` permite pasar un *iterable* `args` como una lista para `call`.
313-
- La opción `apply` acepta solo `args` como *array-like*.
312+
- La sintaxis con el operador "spread" `...` -- en `call` permite pasar una lista *iterable* `args`.
313+
- La opción `apply` -- acepta solamente `args` que sean *símil-array*.
314314

315-
Y para los objetos que son iterables y array-like, como un array real, podemos usar cualquiera de ellos, pero `apply` probablemente será más rápido, porque la mayoría de los motores de JavaScript lo optimizan mejor internamente.
315+
Para los objetos que son iterables y símil-array, como un array real, podemos usar cualquiera de ellos, pero `apply` probablemente será más rápido porque la mayoría de los motores de JavaScript lo optimizan mejor internamente.
316316

317317
Pasar todos los argumentos junto con el contexto a otra función se llama *redirección de llamadas*.
318318

@@ -324,7 +324,7 @@ let wrapper = function() {
324324
};
325325
```
326326

327-
Cuando un código externo llama a tal `wrapper`, no se puede distinguir de la llamada de la función original `func` .
327+
Cuando un código externo llama a tal contenedor `wrapper`, no se puede distinguir de la llamada de la función original `func` .
328328

329329
## Préstamo de método [#method-borrowing]
330330

@@ -346,7 +346,7 @@ function hash(args) {
346346
}
347347
```
348348

349-
... Desafortunadamente, eso no funcionará. Debido a que estamos llamando a `hash (arguments)`, y el objeto `arguments` es iterable y *array-like* (similar a un array, pero no es un array real).
349+
... desafortunadamente, eso no funcionará. Esto es debido a que estamos llamando a `hash (arguments)`, y el objeto `arguments` es iterable y *símil-array* (no es un array real).
350350

351351
Por lo tanto, llamar a `join` en él fallará, como podemos ver a continuación:
352352

@@ -390,28 +390,28 @@ Tomado de la especificación casi "tal cual":
390390
6. ...hacerlo hasta que la cantidad `this.length` de elementos estén adheridos.
391391
7. Devolver `result`.
392392

393-
Entonces, técnicamente `this` une `this[0]`, `this[1]` ...etc. Está escrito intencionalmente de una manera que permite cualquier tipo de array `this` (no es una coincidencia, muchos métodos siguen esta práctica). Es por eso que también funciona con `this = arguments`
393+
Entonces, técnicamente toma a `this` y le une `this[0]`, `this[1]`... etc. Está escrito intencionalmente de una manera que permite cualquier tipo de array `this` (no es una coincidencia, muchos métodos siguen esta práctica). Es por eso que también funciona con `this = arguments`
394394

395395
## Decoradores y propiedades de funciones
396396

397397
Por lo general, es seguro reemplazar una función o un método con un decorador, excepto por una pequeña cosa. Si la función original tenía propiedades (como `func.calledCount` o cualquier otra) entonces la función decoradora no las proporcionará. Porque es una envoltura. Por lo tanto, se debe tener cuidado al usarlo.
398398

399399
En el ejemplo anterior, si la función `slow` tuviera propiedades, `cachingDecorator(slow)` sería un contenedor sin dichas propiedades.
400400

401-
Algunos decoradores pueden proporcionar sus propias propiedades. P.ej. un decorador puede contar cuántas veces se invocó una función y cuánto tiempo tardó, y exponer esta información a través de propiedades de envoltura.
401+
Algunos decoradores pueden proporcionar sus propias propiedades. P.ej. un decorador puede contar cuántas veces se invocó una función y cuánto tiempo tardó, y exponer esta información por medio de propiedades del contenedor.
402402

403403
Existe una forma de crear decoradores que mantienen el acceso a las propiedades de la función, pero esto requiere el uso de un objeto especial `Proxy` para ajustar una función. Lo discutiremos más adelante en el artículo <info:proxy#proxy-apply>.
404404

405405
## Resumen
406406

407-
*Decorator* o decorador es un contenedor alrededor de una función que altera su comportamiento. El trabajo principal todavía lo realiza la función.
407+
El *decorador* es un contenedor alrededor de una función que altera su comportamiento. El trabajo principal todavía lo realiza la función.
408408

409409
Los decoradores se pueden ver como "características" o "aspectos" que se pueden agregar a una función. Podemos agregar uno o agregar muchos. ¡Y todo esto sin cambiar su código!
410410

411-
Para implementar `cachingDecorator`, estudiamos los siguientes métodos:
411+
Para implementar `cachingDecorator`, hemos estudiado los siguientes métodos:
412412

413413
- [func.call(context, arg1, arg2...)](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Function/call) -- llama a `func` con el contexto y argumentos dados.
414-
- [func.apply(context, args)](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Function/apply) -- llama a `func` pasando `context` como `this` y array-like `args` en una lista de argumentos.
414+
- [func.apply(context, args)](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Function/apply) -- llama a `func`, pasando `context` como `this`, y un símil-array `args` como lista de argumentos.
415415

416416
La *redirección de llamadas* genérica generalmente se realiza con `apply`:
417417

@@ -421,6 +421,6 @@ let wrapper = function() {
421421
};
422422
```
423423

424-
También vimos un ejemplo de *préstamo de método* cuando tomamos un método de un objeto y lo `llamamos` en el contexto de otro objeto. Es bastante común tomar métodos de array y aplicarlos al símil-array `arguments`. La alternativa es utilizar el objeto de parámetros rest que es un array real.
424+
También vimos un ejemplo de *préstamo de método* cuando tomamos un método de un objeto y lo "llamamos" (`call`) en el contexto de otro objeto. Es bastante común tomar métodos de array y aplicarlos al símil-array `arguments`. La alternativa es utilizar el objeto de parámetros rest, que es un array real.
425425

426426
Hay muchos decoradores a tu alrededor. Verifica qué tan bien los entendiste resolviendo las tareas de este capítulo.

0 commit comments

Comments
 (0)