diff --git a/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/solution.md b/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/solution.md index 7cbd85ab7..0afef63ab 100644 --- a/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/solution.md +++ b/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/solution.md @@ -1,5 +1,6 @@ -The answer is: **Pete**. +La respuesta es: **Pete**. -A function gets outer variables as they are now, it uses the most recent values. +Una función obtiene variables externas con su estado actual, y utiliza los valores más recientes. + +Los valores de variables anteriores no se guardan en ningún lado. Cuando una función quiere una variable, toma el valor actual de su propio entorno léxico o el externo. -Old variable values are not saved anywhere. When a function wants a variable, it takes the current value from its own Lexical Environment or the outer one. diff --git a/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/task.md b/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/task.md index 819189773..e5795d4e0 100644 --- a/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/task.md +++ b/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/task.md @@ -2,9 +2,9 @@ importance: 5 --- -# Does a function pickup latest changes? +# ¿Una función recoge los últimos cambios? -The function sayHi uses an external variable name. When the function runs, which value is it going to use? +La función sayHi usa un nombre de variable externo. Cuando se ejecuta la función, ¿qué valor va a utilizar? ```js let name = "John"; @@ -15,9 +15,10 @@ function sayHi() { name = "Pete"; -sayHi(); // what will it show: "John" or "Pete"? +sayHi(); // ¿qué mostrará: "John" o "Pete"? + ``` +Tales situaciones son comunes tanto en el desarrollo del navegador como del lado del servidor. Se puede programar que una función se ejecute más tarde de lo que se creó, por ejemplo, después de una acción del usuario o una solicitud de red. -Such situations are common both in browser and server-side development. A function may be scheduled to execute later than it is created, for instance after a user action or a network request. +Entonces, la pregunta es: ¿recoge los últimos cambios? -So, the question is: does it pick up the latest changes? diff --git a/1-js/06-advanced-functions/03-closure/10-make-army/solution.md b/1-js/06-advanced-functions/03-closure/10-make-army/solution.md index 0fb0b4a49..c83cb37e3 100644 --- a/1-js/06-advanced-functions/03-closure/10-make-army/solution.md +++ b/1-js/06-advanced-functions/03-closure/10-make-army/solution.md @@ -1,14 +1,15 @@ -Let's examine what's done inside `makeArmy`, and the solution will become obvious. +Examinemos lo que se hace dentro de `makeArmy`, y la solución será obvia. -1. It creates an empty array `shooters`: +1. Crea un array vacío. `shooters`: ```js let shooters = []; ``` -2. Fills it in the loop via `shooters.push(function...)`. - Every element is a function, so the resulting array looks like this: +2. Lo llena en el bucle a través de `shooters.push(function...)`. + + Cada elemento es una función, por lo que el array resultante se ve así: ```js no-beautify shooters = [ @@ -24,18 +25,18 @@ Let's examine what's done inside `makeArmy`, and the solution will become obviou function () { alert(i); } ]; ``` + +3. El array se devuelve desde la función. -3. The array is returned from the function. - -Then, later, the call to `army[5]()` will get the element `army[5]` from the array (it will be a function) and call it. +Luego, más tarde, la llamada a `army[5] ()` obtendrá el elemento `army[5]` de el array (será una función) y lo llamará. -Now why all such functions show the same? +Ahora, ¿por qué todas esas funciones muestran lo mismo? -That's because there's no local variable `i` inside `shooter` functions. When such a function is called, it takes `i` from its outer lexical environment. +Esto se debe a que no hay una variable local `i` dentro de las funciones `shooter`. Cuando se llama a tal función, toma `i` de su entorno léxico externo. -What will be the value of `i`? +¿Cuál será el valor de 'i'? -If we look at the source: +Si miramos la fuente: ```js function makeArmy() { @@ -43,7 +44,7 @@ function makeArmy() { let i = 0; while (i < 10) { let shooter = function() { // shooter function - alert( i ); // should show its number + alert( i ); // debería mostrar su número }; ... } @@ -51,11 +52,11 @@ function makeArmy() { } ``` -...We can see that it lives in the lexical environment associated with the current `makeArmy()` run. But when `army[5]()` is called, `makeArmy` has already finished its job, and `i` has the last value: `10` (the end of `while`). +... Podemos ver que vive en el entorno léxico asociado con la ejecución actual de `makeArmy()`. Pero cuando se llama a `army[5]()`, `makeArmy` ya ha terminado su trabajo, y `i` tiene el último valor: `10` (el final de `while`). -As a result, all `shooter` functions get from the outer lexical envrironment the same, last value `i=10`. +Como resultado, todas las funciones `shooter` obtienen del mismo entorno léxico externo, el último valor `i = 10`. -We can fix it by moving the variable definition into the loop: +Podemos arreglarlo moviendo la definición de variable al bucle: ```js run demo function makeArmy() { @@ -66,7 +67,7 @@ function makeArmy() { for(let i = 0; i < 10; i++) { */!* let shooter = function() { // shooter function - alert( i ); // should show its number + alert( i ); // debería mostrar su número }; shooters.push(shooter); } @@ -80,15 +81,15 @@ army[0](); // 0 army[5](); // 5 ``` -Now it works correctly, because every time the code block in `for (let i=0...) {...}` is executed, a new Lexical Environment is created for it, with the corresponding variable `i`. +Ahora funciona correctamente, porque cada vez que se ejecuta el bloque de código en `for (let i = 0 ...) {...}`, se crea un nuevo entorno léxico para él, con la variable correspondiente `i`. -So, the value of `i` now lives a little bit closer. Not in `makeArmy()` Lexical Environment, but in the Lexical Environment that corresponds the current loop iteration. That's why now it works. +Entonces, el valor de `i` ahora vive un poco más cerca. No en el entorno léxico `makeArmy()`, sino en el entorno léxico que corresponde a la iteración del bucle actual. Por eso ahora funciona. ![](lexenv-makearmy.svg) -Here we rewrote `while` into `for`. +Aquí reescribimos `while` en `for`. -Another trick could be possible, let's see it for better understanding of the subject: +Podría usarse otro truco, veámoslo para comprender mejor el tema: ```js run function makeArmy() { @@ -100,7 +101,7 @@ function makeArmy() { let j = i; */!* let shooter = function() { // shooter function - alert( *!*j*/!* ); // should show its number + alert( *!*j*/!* ); // debería verse el núemero }; shooters.push(shooter); i++; @@ -115,6 +116,7 @@ army[0](); // 0 army[5](); // 5 ``` -The `while` loop, just like `for`, makes a new Lexical Environment for each run. So here we make sure that it gets the right value for a `shooter`. +El bucle `while`, al igual que `for`, crea un nuevo entorno léxico para cada ejecución. Así que aquí nos aseguramos de que obtenga el valor correcto para un `shooter`. + +Copiamos `let j = i`. Esto hace que el cuerpo del bucle sea `j` local y copia el valor de `i` en él. Los primitivos se copian "por valor", por lo que en realidad obtenemos una copia independiente completa de `i`, que pertenece a la iteración del bucle actual. -We copy `let j = i`. This makes a loop body local `j` and copies the value of `i` to it. Primitives are copied "by value", so we actually get a complete independent copy of `i`, belonging to the current loop iteration. diff --git a/1-js/06-advanced-functions/03-closure/10-make-army/task.md b/1-js/06-advanced-functions/03-closure/10-make-army/task.md index 93e64f2d0..66e984352 100644 --- a/1-js/06-advanced-functions/03-closure/10-make-army/task.md +++ b/1-js/06-advanced-functions/03-closure/10-make-army/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Army of functions +# Ejército de funciones -The following code creates an array of `shooters`. +El siguiente código crea una serie de `shooters`. -Every function is meant to output its number. But something is wrong... +Cada función está destinada a generar su número. Pero algo anda mal ... ```js run function makeArmy() { @@ -15,7 +15,7 @@ function makeArmy() { let i = 0; while (i < 10) { let shooter = function() { // shooter function - alert( i ); // should show its number + alert( i ); // debería mostrar su número }; shooters.push(shooter); i++; @@ -26,10 +26,10 @@ function makeArmy() { let army = makeArmy(); -army[0](); // the shooter number 0 shows 10 -army[5](); // and number 5 also outputs 10... -// ... all shooters show 10 instead of their 0, 1, 2, 3... +army[0](); // el tirador número 0 muestra 10 +army[5](); //y el número 5 también produce 10... +// ... todos los tiradores muestran 10 en lugar de sus 0, 1, 2, 3 ... ``` -Why do all of the shooters show the same value? Fix the code so that they work as intended. +¿Por qué todos los tiradores muestran el mismo valor? Arregle el código para que funcionen según lo previsto. diff --git a/1-js/06-advanced-functions/03-closure/2-closure-variable-access/solution.md b/1-js/06-advanced-functions/03-closure/2-closure-variable-access/solution.md index 0a522132f..b7e7bc9cc 100644 --- a/1-js/06-advanced-functions/03-closure/2-closure-variable-access/solution.md +++ b/1-js/06-advanced-functions/03-closure/2-closure-variable-access/solution.md @@ -1,9 +1,11 @@ -The answer is: **Pete**. -The `work()` function in the code below gets `name` from the place of its origin through the outer lexical environment reference: +La respuesta es: **Pete**. + +La función `work()` en el código a continuación obtiene `name` del lugar de su origen a través de la referencia del entorno léxico externo: ![](lexenv-nested-work.svg) -So, the result is `"Pete"` here. +Entonces, el resultado es "Pete". + +Pero si no hubiera `let name` en` makeWorker () `, entonces la búsqueda saldría y tomaría la variable global como podemos ver en la cadena de arriba. En ese caso, el resultado sería `John`. -But if there were no `let name` in `makeWorker()`, then the search would go outside and take the global variable as we can see from the chain above. In that case the result would be `"John"`. diff --git a/1-js/06-advanced-functions/03-closure/2-closure-variable-access/task.md b/1-js/06-advanced-functions/03-closure/2-closure-variable-access/task.md index d12a385c8..0e3ca3428 100644 --- a/1-js/06-advanced-functions/03-closure/2-closure-variable-access/task.md +++ b/1-js/06-advanced-functions/03-closure/2-closure-variable-access/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Which variables are available? +# ¿Qué variables están disponibles? -The function `makeWorker` below makes another function and returns it. That new function can be called from somewhere else. +La función `makeWorker` a continuación crea otra función y la devuelve. Esa nueva función se puede llamar desde otro lugar. -Will it have access to the outer variables from its creation place, or the invocation place, or both? +¿Tendrá acceso a las variables externas desde su lugar de creación, o desde el lugar de invocación, o ambos? ```js function makeWorker() { @@ -19,11 +19,11 @@ function makeWorker() { let name = "John"; -// create a function +// crea una función let work = makeWorker(); -// call it -work(); // what will it show? +// la llama +work(); // ¿qué mostrará? ``` -Which value it will show? "Pete" or "John"? +¿Qué valor mostrará? "Pete" o "John"? diff --git a/1-js/06-advanced-functions/03-closure/3-counter-independent/solution.md b/1-js/06-advanced-functions/03-closure/3-counter-independent/solution.md index 25ecbea4c..6c306c2c9 100644 --- a/1-js/06-advanced-functions/03-closure/3-counter-independent/solution.md +++ b/1-js/06-advanced-functions/03-closure/3-counter-independent/solution.md @@ -1,5 +1,7 @@ -The answer: **0,1.** -Functions `counter` and `counter2` are created by different invocations of `makeCounter`. +La respuesta: **0,1.** + +Las funciones `counter` y` counter2` son creadas por diferentes invocaciones de `makeCounter`. + +Por lo tanto, tienen entornos léxicos externos independientes, cada uno tiene su propio `count`. -So they have independent outer Lexical Environments, each one has its own `count`. diff --git a/1-js/06-advanced-functions/03-closure/3-counter-independent/task.md b/1-js/06-advanced-functions/03-closure/3-counter-independent/task.md index e8c17dd31..39deda7be 100644 --- a/1-js/06-advanced-functions/03-closure/3-counter-independent/task.md +++ b/1-js/06-advanced-functions/03-closure/3-counter-independent/task.md @@ -2,11 +2,12 @@ importance: 5 --- -# Are counters independent? +# ¿Son independientes los contadores? -Here we make two counters: `counter` and `counter2` using the same `makeCounter` function. +Aquí hacemos dos contadores: `counter` y `counter2` usando la misma función `makeCounter`. + +¿Son independientes? ¿Qué va a mostrar el segundo contador? `0,1` o `2,3` o algo más? -Are they independent? What is the second counter going to show? `0,1` or `2,3` or something else? ```js function makeCounter() { diff --git a/1-js/06-advanced-functions/03-closure/4-counter-object-independent/solution.md b/1-js/06-advanced-functions/03-closure/4-counter-object-independent/solution.md index cd4e641e4..e18f7b151 100644 --- a/1-js/06-advanced-functions/03-closure/4-counter-object-independent/solution.md +++ b/1-js/06-advanced-functions/03-closure/4-counter-object-independent/solution.md @@ -1,7 +1,8 @@ -Surely it will work just fine. +Seguramente funcionará bien. + +Ambas funciones anidadas se crean dentro del mismo entorno léxico externo, por lo que comparten acceso a la misma variable `count`: -Both nested functions are created within the same outer Lexical Environment, so they share access to the same `count` variable: ```js run function Counter() { @@ -10,7 +11,6 @@ function Counter() { this.up = function() { return ++count; }; - this.down = function() { return --count; }; diff --git a/1-js/06-advanced-functions/03-closure/4-counter-object-independent/task.md b/1-js/06-advanced-functions/03-closure/4-counter-object-independent/task.md index d770b0ffc..046ec0ba5 100644 --- a/1-js/06-advanced-functions/03-closure/4-counter-object-independent/task.md +++ b/1-js/06-advanced-functions/03-closure/4-counter-object-independent/task.md @@ -2,11 +2,12 @@ importance: 5 --- -# Counter object +# Objeto contador -Here a counter object is made with the help of the constructor function. +Aquí se crea un objeto contador con la ayuda de la función constructora. + +¿Funcionará? ¿Qué mostrará? -Will it work? What will it show? ```js function Counter() { @@ -26,4 +27,3 @@ alert( counter.up() ); // ? alert( counter.up() ); // ? alert( counter.down() ); // ? ``` - diff --git a/1-js/06-advanced-functions/03-closure/5-function-in-if/solution.md b/1-js/06-advanced-functions/03-closure/5-function-in-if/solution.md index e2e7a91b3..01c7c21c1 100644 --- a/1-js/06-advanced-functions/03-closure/5-function-in-if/solution.md +++ b/1-js/06-advanced-functions/03-closure/5-function-in-if/solution.md @@ -1,3 +1,5 @@ -The result is **an error**. -The function `sayHi` is declared inside the `if`, so it only lives inside it. There is no `sayHi` outside. \ No newline at end of file +El resultado es **un error**. + +La función `sayHi` se declara dentro de `if`, por lo que solo vive dentro de ella. No hay `sayHi` afuera. + diff --git a/1-js/06-advanced-functions/03-closure/5-function-in-if/task.md b/1-js/06-advanced-functions/03-closure/5-function-in-if/task.md index d02c53b99..9480e2487 100644 --- a/1-js/06-advanced-functions/03-closure/5-function-in-if/task.md +++ b/1-js/06-advanced-functions/03-closure/5-function-in-if/task.md @@ -1,7 +1,7 @@ -# Function in if +# Función en if -Look at the code. What will be the result of the call at the last line? +Mira el código ¿Cuál será el resultado de la llamada en la última línea? ```js run let phrase = "Hello"; diff --git a/1-js/06-advanced-functions/03-closure/6-closure-sum/solution.md b/1-js/06-advanced-functions/03-closure/6-closure-sum/solution.md index a6679cd20..baaca18e9 100644 --- a/1-js/06-advanced-functions/03-closure/6-closure-sum/solution.md +++ b/1-js/06-advanced-functions/03-closure/6-closure-sum/solution.md @@ -1,14 +1,13 @@ -For the second parentheses to work, the first ones must return a function. +Para que funcionen los segundos paréntesis, los primeros deben devolver una función. -Like this: +Como esto: ```js run function sum(a) { return function(b) { - return a + b; // takes "a" from the outer lexical environment + return a + b; // toma "a" del entorno léxico externo }; - } alert( sum(1)(2) ); // 3 diff --git a/1-js/06-advanced-functions/03-closure/6-closure-sum/task.md b/1-js/06-advanced-functions/03-closure/6-closure-sum/task.md index b45758562..eb34d8a08 100644 --- a/1-js/06-advanced-functions/03-closure/6-closure-sum/task.md +++ b/1-js/06-advanced-functions/03-closure/6-closure-sum/task.md @@ -2,16 +2,16 @@ importance: 4 --- -# Sum with closures +# Suma con clausuras -Write function `sum` that works like this: `sum(a)(b) = a+b`. +Escriba la función `sum` que funcione así: `sum(a)(b) = a+b`. -Yes, exactly this way, using double parentheses (not a mistype). +Sí, exactamente de esta manera, usando paréntesis dobles (no es un error de tipeo). + +Por ejemeplo: -For instance: ```js sum(1)(2) = 3 sum(5)(-1) = 4 ``` - diff --git a/1-js/06-advanced-functions/03-closure/7-let-scope/solution.md b/1-js/06-advanced-functions/03-closure/7-let-scope/solution.md index 404bae80b..1c8e4ff0e 100644 --- a/1-js/06-advanced-functions/03-closure/7-let-scope/solution.md +++ b/1-js/06-advanced-functions/03-closure/7-let-scope/solution.md @@ -1,40 +1,42 @@ -The result is: **error**. -Try running it: +El resultado es: **error**. + +Intenta correr esto: ```js run let x = 1; function func() { *!* - console.log(x); // ReferenceError: Cannot access 'x' before initialization + console.log(x); // ReferenceError: No se puede acceder a 'x' antes de la inicialización */!* let x = 2; } - func(); ``` -In this example we can observe the peculiar difference between a "non-existing" and "unitialized" variable. +En este ejemplo podemos observar la diferencia peculiar entre una variable "no existente" y una variable "no inicializada". -As you may have read in the article [](info:closure), a variable starts in the "uninitialized" state from the moment when the execution enters a code block (or a function). And it stays uninitalized until the corresponding `let` statement. +Como habrás leído en el artículo [](info:closure), una variable comienza en el estado "no inicializado" desde el momento en que la ejecución entra en un bloque de código (o una función). Y permanece sin inicializar hasta la correspondiente declaración `let`. -In other words, a variable technically exists, but can't be used before `let`. +En otras palabras, una variable técnicamente existe, pero no se puede usar antes de `let`. -The code above demonstrates it. +El código anterior lo demuestra. ```js function func() { *!* - // the local variable x is known to the engine from the beginning of the function, - // but "unitialized" (unusable) until let ("dead zone") - // hence the error + +// la variable local x es conocida por el motor desde el comienzo de la función, +// pero "unitialized" (inutilizable) hasta let ("zona muerta") +// de ahí el error */!* - console.log(x); // ReferenceError: Cannot access 'x' before initialization + console.log(x); // ReferenceError: No se puede acceder a 'x' antes de la inicialización let x = 2; } ``` -This zone of temporary unusability of a variable (from the beginning of the code block till `let`) is sometimes called the "dead zone". +Esta zona de inutilización temporal de una variable (desde el comienzo del bloque de código hasta `let`) a veces se denomina" zona muerta ". + diff --git a/1-js/06-advanced-functions/03-closure/7-let-scope/task.md b/1-js/06-advanced-functions/03-closure/7-let-scope/task.md index fb7445e66..ea764bc0f 100644 --- a/1-js/06-advanced-functions/03-closure/7-let-scope/task.md +++ b/1-js/06-advanced-functions/03-closure/7-let-scope/task.md @@ -2,9 +2,9 @@ importance: 4 --- -# Is variable visible? +# ¿Es visible la variable? -What will be the result of this code? +¿Cuál será el resultado de este código? ```js let x = 1; @@ -18,4 +18,5 @@ function func() { func(); ``` -P.S. There's a pitfall in this task. The solution is not obvious. +P.D Hay una trampa en esta tarea. La solución no es obvia. + diff --git a/1-js/06-advanced-functions/03-closure/8-filter-through-function/solution.md b/1-js/06-advanced-functions/03-closure/8-filter-through-function/solution.md index 46c5514a8..d522bd1f1 100644 --- a/1-js/06-advanced-functions/03-closure/8-filter-through-function/solution.md +++ b/1-js/06-advanced-functions/03-closure/8-filter-through-function/solution.md @@ -1,5 +1,6 @@ -# Filter inBetween +# Filtrar inBetween + ```js run function inBetween(a, b) { @@ -12,7 +13,8 @@ let arr = [1, 2, 3, 4, 5, 6, 7]; alert( arr.filter(inBetween(3, 6)) ); // 3,4,5,6 ``` -# Filter inArray +# Filtrar inArray + ```js run demo function inArray(arr) { diff --git a/1-js/06-advanced-functions/03-closure/8-filter-through-function/task.md b/1-js/06-advanced-functions/03-closure/8-filter-through-function/task.md index d1c39f949..aeccdacca 100644 --- a/1-js/06-advanced-functions/03-closure/8-filter-through-function/task.md +++ b/1-js/06-advanced-functions/03-closure/8-filter-through-function/task.md @@ -2,28 +2,28 @@ importance: 5 --- -# Filter through function +# Filtrar a través de una función -We have a built-in method `arr.filter(f)` for arrays. It filters all elements through the function `f`. If it returns `true`, then that element is returned in the resulting array. +Tenemos un método incorporado `arr.filter(f)` para arrays. Filtra todos los elementos a través de la función `f`. Si devuelve `true`, entonces ese elemento se devuelve en el array resultante. -Make a set of "ready to use" filters: +Haga un conjunto de filtros "listos para usar": -- `inBetween(a, b)` -- between `a` and `b` or equal to them (inclusively). -- `inArray([...])` -- in the given array. +- `inBetween(a, b)` -- entre `a` y `b` o igual a ellos (inclusive). +- `inArray([...])` -- en el array dado -The usage must be like this: +El uso debe ser así: -- `arr.filter(inBetween(3,6))` -- selects only values between 3 and 6. -- `arr.filter(inArray([1,2,3]))` -- selects only elements matching with one of the members of `[1,2,3]`. +- `arr.filter(inBetween(3,6))` -- selecciona solo valores entre 3 y 6. +- `arr.filter(inArray([1,2,3]))` -- selecciona solo elementos que coinciden con uno de los miembros de `[1,2,3]`. -For instance: +Por ejemplo: ```js -/* .. your code for inBetween and inArray */ +/* .. tu código para inBetween y inArray */ + let arr = [1, 2, 3, 4, 5, 6, 7]; alert( arr.filter(inBetween(3, 6)) ); // 3,4,5,6 alert( arr.filter(inArray([1, 2, 10])) ); // 1,2 ``` - diff --git a/1-js/06-advanced-functions/03-closure/9-sort-by-field/task.md b/1-js/06-advanced-functions/03-closure/9-sort-by-field/task.md index 08fb5cc34..8832f4df9 100644 --- a/1-js/06-advanced-functions/03-closure/9-sort-by-field/task.md +++ b/1-js/06-advanced-functions/03-closure/9-sort-by-field/task.md @@ -2,9 +2,10 @@ importance: 5 --- -# Sort by field +# Ordenar por campo + +Tenemos una variedad de objetos para ordenar: -We've got an array of objects to sort: ```js let users = [ @@ -14,23 +15,25 @@ let users = [ ]; ``` -The usual way to do that would be: +La forma habitual de hacerlo sería: ```js -// by name (Ann, John, Pete) +// por nombre(Ann, John, Pete) users.sort((a, b) => a.name > b.name ? 1 : -1); -// by age (Pete, Ann, John) +// por edad (Pete, Ann, John) users.sort((a, b) => a.age > b.age ? 1 : -1); ``` -Can we make it even less verbose, like this? +¿Podemos hacerlo aún menos detallado, como este? + ```js users.sort(byField('name')); users.sort(byField('age')); ``` -So, instead of writing a function, just put `byField(fieldName)`. +Entonces, en lugar de escribir una función, simplemente ponga `byField (fieldName)`. + +Escriba la función `byField` que se pueda usar para eso. -Write the function `byField` that can be used for that. diff --git a/1-js/06-advanced-functions/03-closure/article.md b/1-js/06-advanced-functions/03-closure/article.md index 1845482e5..9d875899b 100644 --- a/1-js/06-advanced-functions/03-closure/article.md +++ b/1-js/06-advanced-functions/03-closure/article.md @@ -1,71 +1,70 @@ -# Variable scope +# Ámbito de Variable -JavaScript is a very function-oriented language. It gives us a lot of freedom. A function can be created dynamically, passed as an argument to another function and called from a totally different place of code later. +JavaScript es un lenguaje muy orientado a funciones. Nos da mucha libertad. Se puede crear una función dinámicamente, pasarla como argumento a otra función y llamarla desde un lugar de código totalmente diferente más adelante. -We already know that a function can access variables outside of it. +Ya sabemos que una función puede acceder a variables fuera de ella. -Now let's expand our knowledge to include more complex scenarios. +Ahora ampliemos nuestro conocimiento para incluir escenarios más complejos. -```smart header="We'll talk about `let/const` variables here" -In JavaScript, there are 3 ways to declare a variable: `let`, `const` (the modern ones), and `var` (the remnant of the past). +```smart header="Hablaremos de las variables let / const aquí" +En JavaScript, hay 3 formas de declarar una variable: `let`, `const` (las modernas) y `var` (más antigua). -- In this article we'll use `let` variables in examples. -- Variables, declared with `const`, behave the same, so this article is about `const` too. -- The old `var` has some notable differences, they will be covered in the article . +- En este artículo usaremos las variables `let` en los ejemplos. +- Las variables, declaradas con `const`, se comportan igual, por lo que este artículo también trata sobre `const`. +- El antiguo `var` tiene algunas diferencias notables, se tratarán en el artículo . ``` -## Code blocks +## Bloques de código -If a variable is declared inside a code block `{...}`, it's only visible inside that block. +Si una variable se declara dentro de un bloque de código `{...}`, solo es visible dentro de ese bloque. -For example: +Por ejemplo: ```js run { - // do some job with local variables that should not be seen outside - - let message = "Hello"; // only visible in this block - + // hacer un trabajo con variables locales que no deberían verse fuera + let message = "Hello"; // solo visible en este bloque alert(message); // Hello } -alert(message); // Error: message is not defined +alert(message); // Error: el mensaje no se ha definido (undefined) ``` -We can use this to isolate a piece of code that does its own task, with variables that only belong to it: +Podemos usar esto para aislar un fragmento de código que realiza su propia tarea, con variables que solo le pertenecen a él: ```js run { - // show message + // ver mensaje let message = "Hello"; alert(message); } { - // show another message + // ver otro mensaje let message = "Goodbye"; alert(message); } ``` -````smart header="There'd be an error without blocks" -Please note, without separate blocks there would be an error, if we use `let` with the existing variable name: +````smart header="Habría un error sin bloques" +Tenga en cuenta que sin bloques separados, habría un error, si usamos 'let' con el nombre de la variable existente: ```js run -// show message +// ver mensaje let message = "Hello"; alert(message); -// show another message +// ver otro mensaje *!* -let message = "Goodbye"; // Error: variable already declared +let message = "Goodbye"; // Error: la variable ya ha sido declarada */!* alert(message); ``` ```` -For `if`, `for`, `while` and so on, variables declared in `{...}` are also only visible inside: +Para `if`,` for`, `while` y así sucesivamente, las variables declaradas en `{...} ` de igual manera solo son visibles en el interior: + ```js run if (true) { @@ -74,38 +73,39 @@ if (true) { alert(phrase); // Hello! } -alert(phrase); // Error, no such variable! +alert(phrase); // ¡Error, no hay tal variable! ``` -Here, after `if` finishes, the `alert` below won't see the `phrase`, hence the error. +Aquí, después de que `if` termine, la` alerta` a continuación no verá la `phrase`, de ahí el error. -That's great, as it allows us to create block-local variables, specific to an `if` branch. +Eso es genial, ya que nos permite crear variables locales de bloque, específicas de una rama `if`. -The similar thing holds true for `for` and `while` loops: +De la misma manera que para los bucles `for` y `while`: ```js run for (let i = 0; i < 3; i++) { - // the variable i is only visible inside this for + // la variable i solo es visible dentro de este for alert(i); // 0, then 1, then 2 } -alert(i); // Error, no such variable +alert(i); // ¡Error, no hay tal variable! ``` -Visually, `let i` is outside of `{...}`. But the `for` construct is special here: the variable, declared inside it, is considered a part of the block. +Visualmente, `let i` está fuera de `{...} `. Pero la construcción `for` es especial aquí: la variable, declarada dentro de ella, se considera parte del bloque. -## Nested functions -A function is called "nested" when it is created inside another function. +## Funciones anidadas -It is easily possible to do this with JavaScript. +Una función se llama "anidada" cuando se crea dentro de otra función. -We can use it to organize our code, like this: +Es fácilmente posible hacer esto con JavaScript. + +Podemos usarlo para organizar nuestro código, así: ```js function sayHiBye(firstName, lastName) { - // helper nested function to use below + // función anidada auxiliar para usar a continuación function getFullName() { return firstName + " " + lastName; } @@ -116,11 +116,12 @@ function sayHiBye(firstName, lastName) { } ``` -Here the *nested* function `getFullName()` is made for convenience. It can access the outer variables and so can return the full name. Nested functions are quite common in JavaScript. +Aquí la función *anidada* `getFullName()` se hace por conveniencia. Puede acceder a las variables externas y, por lo tanto, puede devolver el nombre completo. Las funciones anidadas son bastante comunes en JavaScript. + +Lo que es mucho más interesante, es que puede devolverse una función anidada: ya sea como propiedad de un nuevo objeto o como resultado en sí mismo. Luego se puede usar en otro lugar. No importa dónde, todavía tiene acceso a las mismas variables externas. -What's much more interesting, a nested function can be returned: either as a property of a new object or as a result by itself. It can then be used somewhere else. No matter where, it still has access to the same outer variables. +A continuación, `makeCounter` crea la función "contador "que devuelve el siguiente número en cada invocación: -Below, `makeCounter` creates the "counter" function that returns the next number on each invocation: ```js run function makeCounter() { @@ -138,87 +139,87 @@ alert( counter() ); // 1 alert( counter() ); // 2 ``` -Despite being simple, slightly modified variants of that code have practical uses, for instance, as a [random number generator](https://en.wikipedia.org/wiki/Pseudorandom_number_generator) to generate random values for automated tests. +A pesar de ser simples, las variantes ligeramente modificadas de ese código tienen usos prácticos, por ejemplo, como [random number generator](https://en.wikipedia.org/wiki/Pseudorandom_number_generator) para generar valores aleatorios para pruebas automatizadas. -How does this work? If we create multiple counters, will they be independent? What's going on with the variables here? +¿Cómo funciona esto? Si creamos múltiples contadores, ¿serán independientes? ¿Qué está pasando con las variables aquí? -Undestanding such things is great for the overall knowledge of JavaScript and beneficial for more complex scenarios. So let's go a bit in-depth. +Entender tales cosas es excelente para el conocimiento general de JavaScript y beneficioso para escenarios más complejos. Así que vamos a profundizar un poco. -## Lexical Environment +## Ámbito o alcance léxico -```warn header="Here be dragons!" -The in-depth technical explanation lies ahead. +```warn header="¡Aquí hay dragones!" +La explicación técnica en profundidad está por venir. -As far as I'd like to avoid low-level language details, any understanding without them would be lacking and incomplete, so get ready. +Me gustaría evitar los detalles de lenguaje de bajo nivel, pero cualquier comprensión sin ellos sería insuficiente e incompleta, así que prepárate. ``` -For clarity, the explanation is split into multiple steps. +Para mayor claridad, la explicación se divide en múltiples pasos. -### Step 1. Variables +### Paso 1. Variables -In JavaScript, every running function, code block `{...}`, and the script as a whole have an internal (hidden) associated object known as the *Lexical Environment*. +En JavaScript, todas las funciones en ejecución, el bloque de código `{...}` y el script en su conjunto tienen un objeto interno (oculto) asociado, conocido como *Alcance léxico*. -The Lexical Environment object consists of two parts: +El objeto del alcance léxico consta de dos partes: -1. *Environment Record* -- an object that stores all local variables as its properties (and some other information like the value of `this`). -2. A reference to the *outer lexical environment*, the one associated with the outer code. +1. *Registro de entorno*: un objeto que almacena todas las variables locales como sus propiedades (y alguna otra información como el valor de `this`). +2. Una referencia al *entorno léxico externo*, asociado con el código externo. -**A "variable" is just a property of the special internal object, `Environment Record`. "To get or change a variable" means "to get or change a property of that object".** +**Una "variable" es solo una propiedad del objeto interno especial, `Registro de entorno`. "Obtener o cambiar una variable" significa "obtener o cambiar una propiedad de ese objeto".** -In this simple code without functions, there is only one Lexical Environment: +En este código simple y sin funciones, solo hay un entorno léxico: ![lexical environment](lexical-environment-global.svg) -This is the so-called *global* Lexical Environment, associated with the whole script. +Este es el denominado entorno léxico *global*, asociado con todo el script. -On the picture above, the rectangle means Environment Record (variable store) and the arrow means the outer reference. The global Lexical Environment has no outer reference, that's why the arrow points to `null`. +En la imagen de arriba, el rectángulo significa Registro de entornos (almacén de variables) y la flecha significa la referencia externa. El entorno léxico global no tiene referencia externa, por eso la flecha apunta a `nulo`. -As the code starts executing and goes on, the Lexical Environment changes. +A medida que el código comienza a ejecutarse y continúa, el entorno léxico cambia. -Here's a little bit longer code: +Aquí hay un código un poco más largo: ![lexical environment](closure-variable-phrase.svg) -Rectangles on the right-hand side demonstrate how the global Lexical Environment changes during the execution: +Los rectángulos en el lado derecho demuestran cómo cambia el entorno léxico global durante la ejecución: -1. When the script starts, the Lexical Environment is pre-populated with all declared variables. - - Initially, they are in the "Uninitialized" state. That's a special internal state, it means that the engine knows about the variable, but it cannot be referenced until it has been declared with `let`. It's almost the same as if the variable didn't exist. -2. Then `let phrase` definition appears. There's no assignment yet, so its value is `undefined`. We can use the variable since this moment. -3. `phrase` is assigned a value. -4. `phrase` changes the value. +1. Cuando se inicia el script, el entorno léxico se rellena previamente con todas las variables declaradas. +     - Inicialmente, están en el estado "No inicializado". Ese es un estado interno especial, significa que el motor conoce la variable, pero no se puede hacer referencia a ella hasta que se haya declarado con `let`. Es casi lo mismo que si la variable no existiera. +2. Luego aparece la definición `let phrase`.Todavía no hay una asignación, por lo que su valor es `undefined`. Podemos usar la variable desde este momento. +3. `phrase` se le asigna un valor. +4. `phrase` cambia el valor. -Everything looks simple for now, right? +Todo parece simple por ahora, ¿verdad? -- A variable is a property of a special internal object, associated with the currently executing block/function/script. -- Working with variables is actually working with the properties of that object. +- Una variable es una propiedad de un objeto interno especial, asociado con el bloque / función / script actualmente en ejecución. +- Trabajar con variables es realmente trabajar con las propiedades de ese objeto. -```smart header="Lexical Environment is a specification object" -"Lexical Environment" is a specification object: it only exists "theoretically" in the [language specification](https://tc39.es/ecma262/#sec-lexical-environments) to describe how things work. We can't get this object in our code and manipulate it directly. +```smart header="El entorno léxico es un objeto de especificación" +"El entorno léxico "es un objeto de especificación: solo existe" teóricamente "en el [language specification](https://tc39.es/ecma262/#sec-lexical-environments) para describir cómo funcionan las cosas. No podemos obtener este objeto en nuestro código y manipularlo directamente. -JavaScript engines also may optimize it, discard variables that are unused to save memory and perform other internal tricks, as long as the visible behavior remains as described. +Los motores de JavaScript también pueden optimizarlo, descartar variables que no se utilizan para ahorrar memoria y realizar otros trucos internos, siempre que el comportamiento visible permanezca como se describe. ``` -### Step 2. Function Declarations +### Paso 2. Declaración de funciones -A function is also a value, like a variable. +Una función también es un valor, como una variable. -**The difference is that a Function Declaration is instantly fully initialized.** +**La diferencia es que una `declaración de función` se inicializa completamente al instante.** -When a Lexical Environment is created, a Function Declaration immediately becomes a ready-to-use function (unlike `let`, that is unusable till the declaration). +Cuando se crea un entorno léxico, una declaración de función se convierte inmediatamente en una función lista para usar (a diferencia de `let`, que no se puede usar hasta la declaración). -That's why we can use a function, declared as Function Declaration, even before the declaration itself. +Es por eso que podemos usar una función, declarada como `declaración de función`, incluso antes de la declaración misma. -For example, here's the initial state of the global Lexical Environment when we add a function: +Por ejemplo, aquí está el estado inicial del entorno léxico global cuando agregamos una función: ![](closure-function-declaration.svg) -Naturally, this behavior only applies to Function Declarations, not Function Expressions where we assign a function to a variable, such as `let say = function(name)...`. +Naturalmente, este comportamiento solo se aplica a las `declaraciones de funciones`, no a las `expresiones de funciones`, donde asignamos una función a una variable, como `let say = function (name) ...`. -### Step 3. Inner and outer Lexical Environment +### Paso 3. Entorno léxico interno y externo -When a function runs, at the beginning of the call, a new Lexical Environment is created automatically to store local variables and parameters of the call. +Cuando se ejecuta una función, al comienzo de la llamada, se crea automáticamente un nuevo entorno léxico para almacenar variables y parámetros locales de la llamada. -For instance, for `say("John")`, it looks like this (the execution is at the line, labelled with an arrow): +Por ejemplo, para `say (" John ")`, se ve así (la ejecución está en la línea, etiquetada con una flecha):