From 70d8d94386bd521918a8ee37b0cd01c00b110c1b Mon Sep 17 00:00:00 2001 From: vplentinax Date: Sun, 24 May 2020 21:25:03 -0400 Subject: [PATCH 1/2] bind --- .../2-write-to-object-after-bind/solution.md | 6 +- .../2-write-to-object-after-bind/task.md | 4 +- .../10-bind/3-second-bind/solution.md | 6 +- .../10-bind/3-second-bind/task.md | 6 +- .../solution.md | 4 +- .../4-function-property-after-bind/task.md | 6 +- .../10-bind/5-question-use-bind/solution.md | 13 +- .../10-bind/5-question-use-bind/task.md | 10 +- .../10-bind/6-ask-partial/solution.md | 16 ++ .../10-bind/6-ask-partial/task.md | 34 +++ 1-js/06-advanced-functions/10-bind/article.md | 211 ++++++++++++++---- 11 files changed, 245 insertions(+), 71 deletions(-) create mode 100644 1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md create mode 100644 1-js/06-advanced-functions/10-bind/6-ask-partial/task.md diff --git a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md index 737a14481..7b786e286 100644 --- a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/solution.md @@ -1,4 +1,4 @@ -The answer: `null`. +Respuesta: `null`. ```js run @@ -13,6 +13,6 @@ let user = { user.g(); ``` -The context of a bound function is hard-fixed. There's just no way to further change it. +El contexto de una función enlazada es fijo. Simplemente no hay forma de cambiarlo más. -So even while we run `user.g()`, the original function is called with `this=null`. +Entonces, incluso mientras ejecutamos `user.g()`, la función original se llama con `this = null`. diff --git a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md index 6d7e1fb24..c9bb09d58 100644 --- a/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md +++ b/1-js/06-advanced-functions/10-bind/2-write-to-object-after-bind/task.md @@ -2,9 +2,9 @@ importance: 5 --- -# Bound function as a method +# Función enlazada como método -What will be the output? +¿Cuál será el resultado? ```js function f() { diff --git a/1-js/06-advanced-functions/10-bind/3-second-bind/solution.md b/1-js/06-advanced-functions/10-bind/3-second-bind/solution.md index 97e1c2809..aa3d2f20b 100644 --- a/1-js/06-advanced-functions/10-bind/3-second-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/3-second-bind/solution.md @@ -1,4 +1,4 @@ -The answer: **John**. +Respuesta: **John**. ```js run no-beautify function f() { @@ -10,6 +10,6 @@ f = f.bind( {name: "John"} ).bind( {name: "Pete"} ); f(); // John ``` -The exotic [bound function](https://tc39.github.io/ecma262/#sec-bound-function-exotic-objects) object returned by `f.bind(...)` remembers the context (and arguments if provided) only at creation time. +El objeto exótico [bound function](https://tc39.github.io/ecma262/#sec-bound-function-exotic-objects) devuelto por `f.bind(...)` recuerda el contexto (y los argumentos si se proporcionan) solo en el momento de la creación. -A function cannot be re-bound. +Una función no se puede volver a vincular. diff --git a/1-js/06-advanced-functions/10-bind/3-second-bind/task.md b/1-js/06-advanced-functions/10-bind/3-second-bind/task.md index 5daf053c6..dd6821223 100644 --- a/1-js/06-advanced-functions/10-bind/3-second-bind/task.md +++ b/1-js/06-advanced-functions/10-bind/3-second-bind/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Second bind +# Segundo enlace -Can we change `this` by additional binding? +¿Podemos cambiar `this` por un enlace adicional? -What will be the output? +¿Cuál será el resultado? ```js no-beautify function f() { diff --git a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/solution.md b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/solution.md index 181555d95..b5cfc3c6f 100644 --- a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/solution.md @@ -1,4 +1,4 @@ -The answer: `undefined`. +Respuesta: `undefined`. -The result of `bind` is another object. It does not have the `test` property. +El resultado de `bind` es otro objeto. No tiene la propiedad `test`. diff --git a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md index 8cd18ec56..a9999368a 100644 --- a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md +++ b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md @@ -2,9 +2,9 @@ importance: 5 --- -# Function property after bind +# Propiedad de función después del enlace -There's a value in the property of a function. Will it change after `bind`? Why, elaborate? +Hay un valor en la propiedad de una función. ¿Cambiará después de `bind`? ¿Por qué sí o por qué no? ```js run function sayHi() { @@ -17,7 +17,7 @@ let bound = sayHi.bind({ name: "John" }); -alert( bound.test ); // what will be the output? why? +alert( bound.test ); // ¿Cuál será la salida? ¿por qué? */!* ``` diff --git a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md index 0cb673b12..92acf4651 100644 --- a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md @@ -1,9 +1,9 @@ -The error occurs because `ask` gets functions `loginOk/loginFail` without the object. +El error se produce porque `ask` obtiene las funciones `loginOk/loginFail` sin el objeto. -When it calls them, they naturally assume `this=undefined`. +Cuando los llama, asumen naturalmente `this = undefined`. -Let's `bind` the context: +Vamos a usar `bind` para enlazar el contexto: ```js run function askPassword(ok, fail) { @@ -30,14 +30,15 @@ askPassword(user.loginOk.bind(user), user.loginFail.bind(user)); */!* ``` -Now it works. +Ahora funciona. -An alternative solution could be: +Una solución alternativa podría ser: ```js //... askPassword(() => user.loginOk(), () => user.loginFail()); ``` -Usually that also works, but may fail in more complex situations where `user` has a chance of being overwritten between the moments of asking and running `() => user.loginOk()`. +Por lo general, eso también funciona y se ve bien. +Es un poco menos confiable, aunque en situaciones más complejas donde la variable `user` podría cambiar *después* de que se llama a `askPassword`, pero *antes* el visitante responde y llama a `() => user.loginOk ()`. diff --git a/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md b/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md index eb19e6644..e11265df5 100644 --- a/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md +++ b/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md @@ -2,13 +2,13 @@ importance: 5 --- -# Ask losing this +# Arreglar una función que perdió "this" -The call to `askPassword()` in the code below should check the password and then call `user.loginOk/loginFail` depending on the answer. +La llamada a `askPassword()` en el código a continuación debe verificar la contraseña y luego llamar a `user.loginOk/loginFail` dependiendo de la respuesta. -But it leads to an error. Why? +Pero lleva a un error. ¿Por qué? -Fix the highlighted line for everything to start working right (other lines are not to be changed). +Arregle la línea resaltada para que todo comience a funcionar correctamente (no se deben cambiar otras líneas). ```js run function askPassword(ok, fail) { @@ -34,5 +34,3 @@ let user = { askPassword(user.loginOk, user.loginFail); */!* ``` - - diff --git a/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md b/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md new file mode 100644 index 000000000..0e501dc69 --- /dev/null +++ b/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md @@ -0,0 +1,16 @@ + + +1. Utilice una función de contenedor, una flecha para ser conciso: + + ```js + askPassword(() => user.login(true), () => user.login(false)); + ``` + + Ahora obtiene `user` de variables externas y lo ejecuta de la manera normal. + +2. O cree una función parcial desde `user.login` que use `user` como contexto y tenga el primer argumento correcto: + + + ```js + askPassword(user.login.bind(user, true), user.login.bind(user, false)); + ``` diff --git a/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md b/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md new file mode 100644 index 000000000..0550efb7e --- /dev/null +++ b/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md @@ -0,0 +1,34 @@ +importance: 5 + +--- + +# Aplicación parcial para inicio de sesión + +La tarea es una variante un poco más compleja de . + +El objeto `user` fue modificado. Ahora, en lugar de dos funciones `loginOk/loginFail`, tiene una sola función `user.login(true/false) `. + +¿Qué deberíamos pasar a `askPassword` en el código a continuación, para que llame a `user.login(true)` como `ok` y `user.login(false)` como `fail`? + +```js +function askPassword(ok, fail) { + let password = prompt("Password?", ''); + if (password == "rockstar") ok(); + else fail(); +} + +let user = { + name: 'John', + + login(result) { + alert( this.name + (result ? ' logged in' : ' failed to log in') ); + } +}; + +*!* +askPassword(?, ?); // ? +*/!* +``` + +Sus cambios solo deberían modificar el fragmento resaltado. + diff --git a/1-js/06-advanced-functions/10-bind/article.md b/1-js/06-advanced-functions/10-bind/article.md index fdb07c608..fc0bcf6b6 100644 --- a/1-js/06-advanced-functions/10-bind/article.md +++ b/1-js/06-advanced-functions/10-bind/article.md @@ -3,17 +3,17 @@ libs: --- -# Function binding +# Función vinculadora -When using `setTimeout` with object methods or passing object methods along, there's a known problem: "losing `this`". +Al pasar métodos de objeto como devoluciones de llamada, por ejemplo a `setTimeout`, genera un problema conocido: "pérdida de `this`". -Suddenly, `this` just stops working right. The situation is typical for novice developers, but happens with experienced ones as well. +En este capítulo veremos las formas de solucionarlo. -## Losing "this" +## Pérdida de "this" -We already know that in JavaScript it's easy to lose `this`. Once a method is passed somewhere separately from the object -- `this` is lost. +Ya hemos visto ejemplos de pérdida de `this`. Una vez que se pasa un método en algún lugar separado del objeto -- `this` se pierde. -Here's how it may happen with `setTimeout`: +Así es como puede suceder con `setTimeout`: ```js run let user = { @@ -28,22 +28,22 @@ setTimeout(user.sayHi, 1000); // Hello, undefined! */!* ``` -As we can see, the output shows not "John" as `this.firstName`, but `undefined`! +Como podemos ver, el resultado no muestra "John" como `this.firstName`, ¡sino como `undefined`! -That's because `setTimeout` got the function `user.sayHi`, separately from the object. The last line can be rewritten as: +Esto se debe a que `setTimeout` tiene la función `user.sayHi`, separada del objeto. La última línea se puede reescribir como: ```js let f = user.sayHi; -setTimeout(f, 1000); // lost user context +setTimeout(f, 1000); // user pierde el contexto ``` -The method `setTimeout` in-browser is a little special: it sets `this=window` for the function call (for Node.JS, `this` becomes the timer object, but doesn't really matter here). So for `this.firstName` it tries to get `window.firstName`, which does not exist. In other similar cases as we'll see, usually `this` just becomes `undefined`. +El método `setTimeout` en el navegador es un poco especial: establece `this = window` para la llamada a la función (para Node.js, `this` se convierte en el objeto temporizador (timer), pero realmente no importa aquí). Entonces, en `this.firstName` intenta obtener `window.firstName`, que no existe. En otros casos similares, `this` simplemente se vuelve `undefined`. -The task is quite typical -- we want to pass an object method somewhere else (here -- to the scheduler) where it will be called. How to make sure that it will be called in the right context? +La tarea es bastante típica --queremos pasar un método de objeto a otro lugar (aquí --al planificador) donde se llamará. ¿Cómo asegurarse de que se llamará en el contexto correcto? -## Solution 1: a wrapper +## Solución 1: un contenedor o envoltura -The simplest solution is to use a wrapping function: +La solución más simple es usar una función de envoltura: ```js run let user = { @@ -60,17 +60,17 @@ setTimeout(function() { */!* ``` -Now it works, because it receives `user` from the outer lexical environment, and then calls the method normally. +Ahora funciona, porque recibe a `user` del entorno léxico externo, y luego llama al método normalmente. -The same, but shorter: +Aquí hacemos lo mismo, pero de otra manera: ```js setTimeout(() => user.sayHi(), 1000); // Hello, John! ``` -Looks fine, but a slight vulnerability appears in our code structure. +Se ve bien, pero aparece una ligera vulnerabilidad en nuestra estructura de código.. -What if before `setTimeout` triggers (there's one second delay!) `user` changes value? Then, suddenly, it will call the wrong object! +¿Qué pasa si antes de que `setTimeout` se active (¡hay un segundo retraso!) `user` cambia el valor? Entonces, de repente, ¡llamará al objeto equivocado! ```js run @@ -83,30 +83,32 @@ let user = { setTimeout(() => user.sayHi(), 1000); -// ...within 1 second -user = { sayHi() { alert("Another user in setTimeout!"); } }; +// ...el valor de user cambia en 1 segundo +user = { + sayHi() { alert("Another user in setTimeout!"); } +}; -// Another user in setTimeout?!? +// Otro user en setTimeout! ``` -The next solution guarantees that such thing won't happen. +La siguiente solución garantiza que tal cosa no sucederá. -## Solution 2: bind +## Solución 2: bind -Functions provide a built-in method [bind](mdn:js/Function/bind) that allows to fix `this`. +Las funciones proporcionan un método incorporado [bind](mdn:js/Function/bind) que permite encontrar a `this`. -The basic syntax is: +La sintaxis básica es: ```js -// more complex syntax will be little later +// la sintaxis más compleja vendrá un poco más tarde let boundFunc = func.bind(context); -```` +``` -The result of `func.bind(context)` is a special function-like "exotic object", that is callable as function and transparently passes the call to `func` setting `this=context`. +El resultado de `func.bind(context)` es una función especial "objeto exótico" similar a una función regular, que se puede llamar como función y pasa la llamada de forma transparente a `func` estableciendo `this = context`. -In other words, calling `boundFunc` is like `func` with fixed `this`. +En otras palabras, llamar a `boundFunc` es como `func` con un `this` fijo. -For instance, here `funcUser` passes a call to `func` with `this=user`: +Por ejemplo, aquí `funcUser` pasa una llamada a `func` con `this = user`: ```js run let user = { @@ -123,9 +125,9 @@ funcUser(); // John */!* ``` -Here `func.bind(user)` as a "bound variant" of `func`, with fixed `this=user`. +Aquí `func.bind(user)` es como una "variante ligada" de `func`, con `this = user` fijo en ella. -All arguments are passed to the original `func` "as is", for instance: +Todos los argumentos se pasan al `func` original "tal cual", por ejemplo: ```js run let user = { @@ -136,15 +138,15 @@ function func(phrase) { alert(phrase + ', ' + this.firstName); } -// bind this to user +// vincula this a user let funcUser = func.bind(user); *!* -funcUser("Hello"); // Hello, John (argument "Hello" is passed, and this=user) +funcUser("Hello"); // Hello, John (argumento "Hello" se pasa, y this=user) */!* ``` -Now let's try with an object method: +Ahora intentemos con un método de objeto: ```js run @@ -159,14 +161,21 @@ let user = { let sayHi = user.sayHi.bind(user); // (*) */!* +// puede ejecutarlo sin un objeto sayHi(); // Hello, John! setTimeout(sayHi, 1000); // Hello, John! + +// incluso si el valor del usuario cambia en 1 segundo +// sayHi usa el valor pre-enlazado +user = { + sayHi() { alert("Another user in setTimeout!"); } +}; ``` -In the line `(*)` we take the method `user.sayHi` and bind it to `user`. The `sayHi` is a "bound" function, that can be called alone or passed to `setTimeout` -- doesn't matter, the context will be right. +En la línea `(*)` tomamos el método `user.sayHi` y lo vinculamos a `user`. `sayHi` es una función "enlazada", que se puede llamar sola o pasarse en `setTimeout` -- no importa, el contexto será el correcto. -Here we can see that arguments are passed "as is", only `this` is fixed by `bind`: +Aquí podemos ver que los argumentos se pasan "tal cual", solo que `this` se fija mediante` bind`: ```js run let user = { @@ -178,12 +187,12 @@ let user = { let say = user.say.bind(user); -say("Hello"); // Hello, John ("Hello" argument is passed to say) +say("Hello"); // Hello, John ("Hello" se pasa a say) say("Bye"); // Bye, John ("Bye" is passed to say) ``` -````smart header="Convenience method: `bindAll`" -If an object has many methods and we plan to actively pass it around, then we could bind them all in a loop: +````smart header="Convenience method:bindAll" +Si un objeto tiene muchos métodos y planeamos pasarlo activamente, podríamos vincularlos a todos en un bucle: ```js for (let key in user) { @@ -193,11 +202,127 @@ for (let key in user) { } ``` -JavaScript libraries also provide functions for convenient mass binding , e.g. [_.bindAll(obj)](http://lodash.com/docs#bindAll) in lodash. +Las bibliotecas de JavaScript también proporcionan funciones para un enlace masivo, e.j. [_.bindAll(obj)](http://lodash.com/docs#bindAll) en lodash. ```` -## Summary +## Funciones parciales + +Hasta ahora solo hemos estado hablando de vincular `this`. Vamos un paso más allá. + +Podemos vincular no solo `this`, sino también argumentos. Es algo que no suele hacerse, pero a veces puede ser útil. + +Sintáxis completa de `bind`: + +```js +let bound = func.bind(context, [arg1], [arg2], ...); +``` + +Permite vincular el contexto como `this` y los argumentos iniciales de la función. + +Por ejemplo, tenemos una función de multiplicación `mul(a, b)`: + +```js +function mul(a, b) { + return a * b; +} +``` + +Usemos `bind` para crear una función` double` en su base: + +```js run +function mul(a, b) { + return a * b; +} + +*!* +let double = mul.bind(null, 2); +*/!* + +alert( double(3) ); // = mul(2, 3) = 6 +alert( double(4) ); // = mul(2, 4) = 8 +alert( double(5) ); // = mul(2, 5) = 10 +``` + +La llamada a `mul.bind(null, 2)` crea una nueva función `double` que pasa las llamadas a `mul`, fijando `null` como contexto y `2` como primer argumento. Otros argumentos se pasan "tal cual". + +Eso se llama [aplicación parcial de una función](https://en.wikipedia.org/wiki/Partial_application) -- creamos una nueva función arreglando algunos parámetros de la existente. + +Tenga en cuenta que aquí en realidad no usamos `this`. Pero `bind` lo requiere, por lo que debemos poner algo como `null`. + +La función `triple` en el siguiente código triplica el valor: + +```js run +function mul(a, b) { + return a * b; +} + +*!* +let triple = mul.bind(null, 3); +*/!* + +alert( triple(3) ); // = mul(3, 3) = 9 +alert( triple(4) ); // = mul(3, 4) = 12 +alert( triple(5) ); // = mul(3, 5) = 15 +``` + +¿Por qué solemos hacer una función parcial? + +El beneficio es que podemos crear una función independiente con un nombre legible (`double`,`triple`). Podemos usarlo y no proporcionar el primer argumento cada vez, ya que se fija con `bind`. + +En otros casos, la aplicación parcial es útil cuando tenemos una función muy genérica y queremos una variante menos universal para mayor comodidad. + +Por ejemplo, tenemos una función `send(from, to, text)`. Luego, dentro de un objeto `user` podemos querer usar una variante parcial del mismo: `sendTo(to, text)` que envía desde el usuario actual. + +## Parcial sin contexto + +¿Qué pasa si nos gustaría arreglar algunos argumentos, pero no el contexto `this`? Por ejemplo, para un método de objeto. + +El método `bind` nativo no permite eso. No podemos simplemente omitir el contexto y saltar a los argumentos. + +Afortunadamente, se puede implementar fácilmente una función `parcial` para vincular solo argumentos. + +Cómo esto: + +```js run +*!* +function partial(func, ...argsBound) { + return function(...args) { // (*) + return func.call(this, ...argsBound, ...args); + } +} +*/!* + +// Uso: +let user = { + firstName: "John", + say(time, phrase) { + alert(`[${time}] ${this.firstName}: ${phrase}!`); + } +}; + +// agregar un método parcial con tiempo fijo +user.sayNow = partial(user.say, new Date().getHours() + ':' + new Date().getMinutes()); + +user.sayNow("Hello"); +// Algo como: +// [10:00] John: Hello! +``` + +El resultado de la llamada `parcial(func [, arg1, arg2 ...])` es un contenedor `(*)` que llama a `func` con: +- El mismo `this` (para la llamada a `user.sayNow` es `user`) +- Luego le da `...argsBound` -- argumentos desde la llamada a `partial` (`"10:00"`) +- Luego le da `...args` -- argumentos dados desde la envoltura (`"Hello"`) + +Muy fácil de hacer con la sintaxis de propagación, ¿verdad? + +También hay una implementación preparada [_.partial](https://lodash.com/docs#partial) desde la librería lodash. + +## Resumen + +El método `func.bind(context, ... args)` devuelve una "variante ligada" de la función `func` que fija el contexto `this` y los primeros argumentos si se dan. + +Por lo general, aplicamos `bind` para fijar `this` a un método de objeto, de modo que podamos pasarlo en otro lugar. Por ejemplo, en `setTimeout`. -Method `func.bind(context, ...args)` returns a "bound variant" of function `func` that fixes the context `this` and first arguments if given. +Cuando fijamos algunos argumentos de una función existente, la función resultante (menos universal) se llama *aplicación parcial* o *parcial*. -Usually we apply `bind` to fix `this` in an object method, so that we can pass it somewhere. For example, to `setTimeout`. There are more reasons to `bind` in the modern development, we'll meet them later. +Los parciales son convenientes cuando no queremos repetir el mismo argumento una y otra vez. Al igual que si tenemos una función `send(from, to)`, y `from` siempre debe ser igual para nuestra tarea, entonces, podemos obtener un parcial y continuar la tarea con él. From d8070d3d0f053279d8443c70eb4451b425fc0e96 Mon Sep 17 00:00:00 2001 From: vplentinax Date: Mon, 1 Jun 2020 21:03:38 -0400 Subject: [PATCH 2/2] corrections --- .../10-bind/5-question-use-bind/solution.md | 2 +- .../10-bind/6-ask-partial/solution.md | 2 +- 1-js/06-advanced-functions/10-bind/article.md | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md index 92acf4651..ad4ffa67e 100644 --- a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md +++ b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md @@ -40,5 +40,5 @@ askPassword(() => user.loginOk(), () => user.loginFail()); Por lo general, eso también funciona y se ve bien. -Es un poco menos confiable, aunque en situaciones más complejas donde la variable `user` podría cambiar *después* de que se llama a `askPassword`, pero *antes* el visitante responde y llama a `() => user.loginOk ()`. +Aunque es un poco menos confiable en situaciones más complejas donde la variable `user` podría cambiar *después* de que se llama a `askPassword`, *antes* de que el visitante responde y llame a `() => user.loginOk ()`. diff --git a/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md b/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md index 0e501dc69..cc8fd21ce 100644 --- a/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md +++ b/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md @@ -1,6 +1,6 @@ -1. Utilice una función de contenedor, una flecha para ser conciso: +1. Utilice una función wrapper (envoltura), de tipo arrow (flecha) para ser conciso: ```js askPassword(() => user.login(true), () => user.login(false)); diff --git a/1-js/06-advanced-functions/10-bind/article.md b/1-js/06-advanced-functions/10-bind/article.md index fc0bcf6b6..51288dd32 100644 --- a/1-js/06-advanced-functions/10-bind/article.md +++ b/1-js/06-advanced-functions/10-bind/article.md @@ -3,9 +3,9 @@ libs: --- -# Función vinculadora +# Función binding (vinculadora) -Al pasar métodos de objeto como devoluciones de llamada, por ejemplo a `setTimeout`, genera un problema conocido: "pérdida de `this`". +Al pasar métodos de objeto como devoluciones de llamada, por ejemplo a `setTimeout`, se genera un problema conocido: "pérdida de `this`". En este capítulo veremos las formas de solucionarlo. @@ -41,9 +41,9 @@ El método `setTimeout` en el navegador es un poco especial: establece `this = w La tarea es bastante típica --queremos pasar un método de objeto a otro lugar (aquí --al planificador) donde se llamará. ¿Cómo asegurarse de que se llamará en el contexto correcto? -## Solución 1: un contenedor o envoltura +## Solución 1: un wrapper (envoltura) -La solución más simple es usar una función de envoltura: +La solución más simple es usar una función wrapper (envoltura): ```js run let user = { @@ -104,7 +104,7 @@ La sintaxis básica es: let boundFunc = func.bind(context); ``` -El resultado de `func.bind(context)` es una función especial "objeto exótico" similar a una función regular, que se puede llamar como función y pasa la llamada de forma transparente a `func` estableciendo `this = context`. +El resultado de `func.bind(context)` es un "objeto exótico", una función similar a una función regular, que se puede llamar como función y pasa la llamada de forma transparente a `func` estableciendo `this = context`. En otras palabras, llamar a `boundFunc` es como `func` con un `this` fijo. @@ -173,7 +173,7 @@ user = { }; ``` -En la línea `(*)` tomamos el método `user.sayHi` y lo vinculamos a `user`. `sayHi` es una función "enlazada", que se puede llamar sola o pasarse en `setTimeout` -- no importa, el contexto será el correcto. +En la línea `(*)` tomamos el método `user.sayHi` y lo vinculamos a `user`. `sayHi` es una función "bound" (enlazada). Si se llama sola o se pasa en `setTimeout` no importa, el contexto será el correcto. Aquí podemos ver que los argumentos se pasan "tal cual", solo que `this` se fija mediante` bind`: @@ -275,13 +275,13 @@ Por ejemplo, tenemos una función `send(from, to, text)`. Luego, dentro de un ob ## Parcial sin contexto -¿Qué pasa si nos gustaría arreglar algunos argumentos, pero no el contexto `this`? Por ejemplo, para un método de objeto. +¿Qué pasa si nos gustaría fijar algunos argumentos, pero no el contexto `this`? Por ejemplo, para un método de objeto. El método `bind` nativo no permite eso. No podemos simplemente omitir el contexto y saltar a los argumentos. Afortunadamente, se puede implementar fácilmente una función `parcial` para vincular solo argumentos. -Cómo esto: +Como esto: ```js run *!*