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..76338a9a2 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,5 @@ -The answer is: **Pete**. +جواب: **Pete**. -A function gets outer variables as they are now, it uses the most recent values. +یک تابع متغیرهای بیرونی را همانطور که هستند دریافت می‌کند و از آخرین مقدارها استفاده می‌کند. -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..4d5926717 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? +# آیا یک تابع آخرین تغییرات را دریافت می‌کند؟ -The function sayHi uses an external variable name. When the function runs, which value is it going to use? +تابع sayHi از یک متغیر خارجی name استفاده می‌کند. زمانی که تابع اجرا می‌شود، کدام مقدار استفاده خواهد شد؟ ```js let name = "John"; @@ -15,9 +15,9 @@ function sayHi() { name = "Pete"; -sayHi(); // what will it show: "John" or "Pete"? +sayHi(); // ؟"Pete" یا "John" :چه چیزی نمایش خواهد داد ``` -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. +چنین موقعیت‌هایی در توسعه هم سمت مرورگر و هم سمت سرور رایج هستند. ممکن است یک تابع قرار باشد بعد از اینکه ساخته شد اجرا شود، برای مثال بعد از اینکه کاربر کاری انجام داد یا بعد از یک درخواست شبکه. -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 9d99aa717..935f8297a 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,14 @@ -Let's examine what exactly happens inside `makeArmy`, and the solution will become obvious. +بیایید بررسی کنیم که درون `makeArmy` دقیقا چه چیزی پیش می‌آید و راه‌حل واضح می‌شود. -1. It creates an empty array `shooters`: +1. یک آرایه خالی `shooters` می‌سازد: ```js let shooters = []; ``` -2. Fills it with functions via `shooters.push(function)` in the loop. +2. آن را با استفاده از `shooters.push(function)` درون حلقه از تابع‌ها پر می‌کند. - Every element is a function, so the resulting array looks like this: + هر المان تابع است پس نتیجه آرایه اینگونه بنظر می‌رسد: ```js no-beautify shooters = [ @@ -25,40 +25,40 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco ]; ``` -3. The array is returned from the function. +3. آرایه از تابع برگردانده می‌شود. - Then, later, the call to any member, e.g. `army[5]()` will get the element `army[5]` from the array (which is a function) and calls it. + سپس بعدها، فراخوانی هر عددی، برای مثال `army[5]()` المان `army[5]` را از آرایه دریافت می‌کند (که یک تابع است) و آن را فراخوانی می‌کند. - Now why do all such functions show the same value, `10`? + حالا چرا تمام تابع‌ها مقدار یکسان `10` را برمی‌گردانند؟ - 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. + به دلیل اینکه هیچ متغیر محلی `i` درون تابع‌های `shooter` وجود ندارد. زمانی که چنین تابعی صدا زده می‌شود، `i` را از محیط لغوی بیرونی خود دریافت می‌کند. - Then, what will be the value of `i`? - - If we look at the source: + سپس مقدار `i` چه چیزی خواهد بود؟ + اگر ما به کد منبع نگاه کنیم: + ```js function makeArmy() { ... let i = 0; while (i < 10) { - let shooter = function() { // shooter function - alert( i ); // should show its number + let shooter = function() { // shooter تابع + alert( i ); // باید عدد خودش را نشان دهد }; - shooters.push(shooter); // add function to the array + shooters.push(shooter); // اضافه کردن تابع به آرایه i++; } ... } ``` - We can see that all `shooter` functions are created in the lexical environment of `makeArmy()` function. But when `army[5]()` is called, `makeArmy` has already finished its job, and the final value of `i` is `10` (`while` stops at `i=10`). + می‌توانیم ببینیم که تمام تابع‌های `shooter` در محیط لغوی تابع `makeArmy()` ساخته شده‌اند. اما زمانی که `army[5]()` فراخوانی می‌شود، `makeArmy` از قبل کار خودش را انجام داده و مقدار نهایی `i` برابر با `10` است (`while` در `i=10` می‌ایستد). - As the result, all `shooter` functions get the same value from the outer lexical environment and that is, the last value, `i=10`. + به عنوان نتیجه، تمام تابع‌های `shooter` مقدار یکسان را از محیط لغوی بیرونی دریافت می‌کنند و به همین دلیل، مقدار آخر `i=10` است. ![](lexenv-makearmy-empty.svg) - As you can see above, on each iteration of a `while {...}` block, a new lexical environment is created. So, to fix this, we can copy the value of `i` into a variable within the `while {...}` block, like this: + همانطور که در بالا می‌بینید، در هر تکرار از بلوک `while {...}`، یک محیط لغوی جدید ساخته می‌شود. پس برای درست کردن این، ما مقدار `i` را در یک متغیر درون بلوک `while {...}` کپی می‌کنیم، مانند این: ```js run function makeArmy() { @@ -69,8 +69,8 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco *!* let j = i; */!* - let shooter = function() { // shooter function - alert( *!*j*/!* ); // should show its number + let shooter = function() { // shooter تابع + alert( *!*j*/!* ); // باید عدد خودش را نشان دهد }; shooters.push(shooter); i++; @@ -81,18 +81,18 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco let army = makeArmy(); - // Now the code works correctly + // حالا کد به درستی کار می‌کند army[0](); // 0 army[5](); // 5 ``` - Here `let j = i` declares an "iteration-local" variable `j` and copies `i` into it. Primitives are copied "by value", so we actually get an independent copy of `i`, belonging to the current loop iteration. + اینجا `let j = i` یک متغیر «محلی در هر تکرار» `j` را تعریف می‌کند و `i` را در آن کپی می‌کند. مقدارهای اولیه «با مقدار خود» کپی می‌شوند پس در واقع ما یک کپی مستقل از `i` داریم که به تکرار کنونی حلقه تعلق دارد. - The shooters work correctly, because the value of `i` now lives a little bit closer. Not in `makeArmy()` Lexical Environment, but in the Lexical Environment that corresponds to the current loop iteration: + تیراندازها به درستی کار می‌کنند چون حالا مقدار `i` کمی نزدیک‌تر شده است. درون محیط لغوی `makeArmy()` نیست بلکه در محیط لغوی متناظر با تکرار کنونی حلقه وجود دارد: ![](lexenv-makearmy-while-fixed.svg) - Such a problem could also be avoided if we used `for` in the beginning, like this: + اگر ما در ابتدا از `for` استفاده می‌کردیم، از چنین مشکلی جلوگیری میشد، مثل این: ```js run demo function makeArmy() { @@ -102,8 +102,8 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco *!* for(let i = 0; i < 10; i++) { */!* - let shooter = function() { // shooter function - alert( i ); // should show its number + let shooter = function() { // shooter تابع + alert( i ); // باید عدد خودش را نشان دهد }; shooters.push(shooter); } @@ -117,13 +117,13 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco army[5](); // 5 ``` - That's essentially the same, because `for` on each iteration generates a new lexical environment, with its own variable `i`. So `shooter` generated in every iteration references its own `i`, from that very iteration. + این کد اساسا یکسان است چون `for` در هر تکرار یک محیط لغوی جدید را ایجاد می‌کند که متغیر `i` خودش را دارد. پس `shooter` که در هر تکرار ایجاد شده است به `i` خودش از همان تکرار رجوع می‌کند. ![](lexenv-makearmy-for-fixed.svg) -Now, as you've put so much effort into reading this, and the final recipe is so simple - just use `for`, you may wonder -- was it worth that? +حالا همانطور که شما زحمت زیادی را برای خواندن این راه‌حل کشیدید، دستور العمل نهایی بسیار ساده است - فقط از `for` استفاده کنید، شاید بپرسید آیا ارزش آن را داشت؟ -Well, if you could easily answer the question, you wouldn't read the solution. So, hopefully this task must have helped you to understand things a bit better. +خب اگر شما می‌توانستید به راحتی سوال را جواب دهید، راه‌حل را نمی‌خواندید. پس خوشبختانه این تکلیف باید به شما برای فهمیدن این نکات کمی کمک کرده باشد. -Besides, there are indeed cases when one prefers `while` to `for`, and other scenarios, where such problems are real. +علاوه بر آن، مواردی وجود دارد که کسی `while` را به `for` ترجیح دهد یا سناریوهای دیگر در میان باشند که چنین مشکلاتی واقعا پیش بیایند. 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 f50c7dc20..8f3080545 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 +# ارتشی از تابع‌ها -The following code creates an array of `shooters`. +کد پایین یک ارایه از `shooters`(تیراندازها) را می‌سازد. -Every function is meant to output its number. But something is wrong... +هر تابع باید عدد آن را نمایش دهد. اما یک چیز اشتباه است... ```js run function makeArmy() { @@ -14,28 +14,28 @@ function makeArmy() { let i = 0; while (i < 10) { - let shooter = function() { // create a shooter function, - alert( i ); // that should show its number + let shooter = function() { // shooter ساخت یک تابع + alert( i ); // که باید عدد خود را نمایش دهد }; - shooters.push(shooter); // and add it to the array + shooters.push(shooter); // و آن را به ارایه اضافه کند i++; } - // ...and return the array of shooters + // ها را برگرداندshooter و آرایه‌ای از... return shooters; } let army = makeArmy(); *!* -// all shooters show 10 instead of their numbers 0, 1, 2, 3... -army[0](); // 10 from the shooter number 0 -army[1](); // 10 from the shooter number 1 -army[2](); // 10 ...and so on. +// ها به جای عدد خود یعنی ...3 ،2 ،1 ،0 عدد 10 را نمایش می‌دهندshooter تمام +army[0](); // عدد 10 از تیرانداز 0 +army[1](); // عدد 10 از تیرانداز 1 +army[2](); // عدد 10 و همینطور ادامه می‌یابد */!* ``` + +چرا تمام shooterها مقدار یکسان را نمایش می‌دهند؟ -Why do all of the shooters show the same value? - -Fix the code so that they work as intended. +کد را درست کنید تا همانطور که می‌خواهیم کار کند. 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..765c720b8 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,9 @@ -The answer is: **Pete**. +جواب: **Pete**. -The `work()` function in the code below gets `name` from the place of its origin through the outer lexical environment reference: +تابع `work()` در کد زیر `name` را از طریق مرجع محیط لغوی بیرونی، از جایی که منشا گرفته است دریافت می‌کند: ![](lexenv-nested-work.svg) -So, the result is `"Pete"` here. +پس اینجا نتیجه `"Pete"` است. -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"`. +اما اگر `let name` در `makeWorker()` وجود نداشت، همانطور که در زنجیره بالا هم می‌بینیم، سپس جستجو به بیرون می‌رفت و متغیر گلوبال را دریافت می‌کرد. در این صورت نتیجه `"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..9357c8cf1 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? +# کدام متغیرها در دسترس هستند؟ -The function `makeWorker` below makes another function and returns it. That new function can be called from somewhere else. +تابع `makeWorker` پایین یک تابع دیگر می‌سازد و آن را برمی‌گرداند. تابع جدید می‌تواند در جایی دیگر فراخوانی شود. -Will it have access to the outer variables from its creation place, or the invocation place, or both? +این تابع به متغیرهای بیرون از جایی که ساخته شد دسترسی خواهد داشت یا جایی که فراخوانی می‌شود یا هر دو؟ ```js function makeWorker() { @@ -19,11 +19,11 @@ function makeWorker() { let name = "John"; -// create a function +// ساخت یک تابع let work = makeWorker(); -// call it -work(); // what will it show? +// فراخوانی آن +work(); // چه چیزی نمایش خواهد داد؟ ``` -Which value it will show? "Pete" or "John"? +کدام مقدار را نمایش خواهد داد؟ "Pete" یا "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..45df430df 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,5 @@ -The answer: **0,1.** +جواب: **0,1.** -Functions `counter` and `counter2` are created by different invocations of `makeCounter`. +تابع‌های `counter` و `counter2` با فراخوانی‌های متفاوتِ `makeCounter` ساخته شده‌اند. -So they have independent outer Lexical Environments, each one has its own `count`. +پس آنها محیط‌های لغوی بیرونی مستقل دارند که هر کدام آنها `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..0dbf800d7 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,11 @@ importance: 5 --- -# Are counters independent? +# آیا شمارنده‌ها مستقل هستند؟ -Here we make two counters: `counter` and `counter2` using the same `makeCounter` function. +اینجا ما دو شمارنده می‌سازیم: `counter` و `counter2` با استفاده از تابع یکسان `makeCounter`. -Are they independent? What is the second counter going to show? `0,1` or `2,3` or something else? +آیا آنها مستقل هستند؟ دومین شمارنده چه چیزی را نمایش خواهد داد؟ `0,1` یا `2,3` یا چیز دیگری؟ ```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..7582b2f24 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,7 @@ -Surely it will work just fine. +مسلما به درستی کار خواهد کرد. -Both nested functions are created within the same outer Lexical Environment, so they share access to the same `count` variable: +هر دو تابع تودرتو در محیط لغوی بیرونی یکسانی ساخته شده‌اند پس آنها به متغیر `count` یکسان دسترسی دارند: ```js run function Counter() { 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..054dcceb4 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,11 @@ importance: 5 --- -# Counter object +# شیء شمارنده -Here a counter object is made with the help of the constructor function. +اینجا یک شیء شمارنده با کمک تابع سازنده ساخته شده است. -Will it work? What will it show? +آیا کار می‌کند؟ چه چیزی را نمایش خواهد داد؟ ```js function Counter() { 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..bc8f0e7e9 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,3 @@ -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 +تابع `sayHi` درون `if` تعریف شده است پس فقط درون آن وجود دارد. بیرون از آن `sayHi` نداریم. 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..95ed541a5 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 +# تابعی درون if -Look at the code. What will be the result of the call at the last line? +به کد زیر نگاه بیاندازید. نتیجه فراخوانی در خط اخر چه چیزی خواهد بود؟ ```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..147de6e84 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,12 +1,12 @@ -For the second parentheses to work, the first ones must return a function. +برای اینکه پرانتز دوم کار کند، پرانتز اول باید یک تابع برگرداند. -Like this: +مانند این: ```js run function sum(a) { return function(b) { - return a + b; // takes "a" from the outer lexical environment + return a + b; // را از محیط لغوی بیرونی می‌گیرد "a" متغیر }; } 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..3344e5e7a 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,13 +2,13 @@ importance: 4 --- -# Sum with closures +# با استفاده از کلوژرها جمع بزنید -Write function `sum` that works like this: `sum(a)(b) = a+b`. +تابع `sum` را بنویسید که اینگونه کار می‌کند: `sum(a)(b) = a+b`. -Yes, exactly this way, using double parentheses (not a mistype). +بله دقیقا به این شکل، با استفاده از دو پرانتز (اشتباه تایپی نیست). -For instance: +برای مثال: ```js sum(1)(2) = 3 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 b16b35290..249817d79 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,6 +1,6 @@ -The result is: **error**. +نتیجه: **ارور**. -Try running it: +سعی کنید آن را اجرا کنید: ```js run let x = 1; @@ -15,20 +15,20 @@ function func() { func(); ``` -In this example we can observe the peculiar difference between a "non-existing" and "uninitialized" variable. +در این مثال ما می‌توانیم تفاوت خاص بین یک متغیر «ناموجود» و «بدون مقداردهی اولیه» را بفهمیم. -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. +همانطور که در مقاله [](info:closure) خواندید، زمانی که یک بلوک کد (یا یک تابع) شروع به اجرا شدن می‌کند، یک متغیر در حالت «بدون مقداردهی اولیه» قرار می‌گیرد. و تا زمانی که به دستور `let` برسد بدون مقداردهی اولیه می‌ماند. -In other words, a variable technically exists, but can't be used before `let`. +به عبارتی دیگر، یک متغیر به صورت فنی موجود است اما نمی‌تواند قبل از `let` استفاده شود. -The code above demonstrates it. +کد بالا این را نشان می‌دهد. ```js function func() { *!* - // the local variable x is known to the engine from the beginning of the function, - // but "uninitialized" (unusable) until let ("dead zone") - // hence the error + // از ابتدای اجرای تابع برای موتور شناخته‌شده است x متغیر محلی + // برسد، «بدون مقداردهی اولیه» (غیر قابل استفاده) است («منطقه مرگ») let اما تا به + // از این رو با ارور مواجه می‌شویم */!* console.log(x); // ReferenceError: Cannot access 'x' before initialization @@ -37,4 +37,4 @@ function func() { } ``` -This zone of temporary unusability of a variable (from the beginning of the code block till `let`) is sometimes called the "dead zone". +این منطقه که یک متغیر به طور موقتی غیر قابل استفاده است (از ابتدای بلوک کد تا `let`) را بعضی اوقات «منطقه مرگ» می‌گویند. 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..2e978d1be 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? +# آیا متغیر قابل رویت است؟ -What will be the result of this code? +نتیجه این کد چه خواهد بود؟ ```js let x = 1; @@ -18,4 +18,4 @@ function func() { func(); ``` -P.S. There's a pitfall in this task. The solution is not obvious. +پی‌نوشت: یک تله در این تکلیف وجود دارد. راه حل بدیهی نیست. 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..c1f7ae0d6 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,24 +2,24 @@ importance: 5 --- -# Filter through function +# جداسازی از طریق تابع -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. +ما یک متد درون‌ساخت `arr.filter(f)` برای آرایه‌ها داریم. این متد تمام المان‌ها را از طریق `f` جداسازی می‌کند. اگر `true` برگرداند، سپس آن المان در آرایه حاصل برگردانده می‌شود. -Make a set of "ready to use" filters: +یک مجموعه از جداسازی‌های «آماده استفاده» بسازید: -- `inBetween(a, b)` -- between `a` and `b` or equal to them (inclusively). -- `inArray([...])` -- in the given array. +- `inBetween(a, b)` -- بین `a` و `b` یا برابر با آنها (شامل آنها هم می‌شود). +- `inArray([...])` -- در آرایه داده شده. -The usage must be like this: +طریقه استفاده از آنها باید اینگونه باشد: -- `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))` -- تنها مقدارهای بین 3 و 6 را انتخاب کند. +- `arr.filter(inArray([1,2,3]))` -- تنها المان‌هایی که با یکی از اعداد `[1,2,3]` برابر هستند را برگرداند. -For instance: +برای مثال: ```js -/* .. your code for inBetween and inArray */ +/* .. inArray و inBetween کد شما برای */ let arr = [1, 2, 3, 4, 5, 6, 7]; alert( arr.filter(inBetween(3, 6)) ); // 3,4,5,6 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..267111fc7 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,9 @@ importance: 5 --- -# Sort by field +# مرتب‌سازی براساس حوزه -We've got an array of objects to sort: +ما یک ارایه از شیءها را برای مرتب‌سازی دریافت کرده‌ایم: ```js let users = [ @@ -14,23 +14,23 @@ let users = [ ]; ``` -The usual way to do that would be: +راه معمولی برای انجام آن می‌تواند این باشد: ```js -// by name (Ann, John, Pete) +// (Ann، John، Pete) براساس اسم users.sort((a, b) => a.name > b.name ? 1 : -1); -// by age (Pete, Ann, John) +// (Pete، Ann، John) براساس سن users.sort((a, b) => a.age > b.age ? 1 : -1); ``` -Can we make it even less verbose, like this? +آیا می‌توانیم آن را کوتاه‌تر کنیم، مثلا اینگونه؟ ```js users.sort(byField('name')); users.sort(byField('age')); ``` -So, instead of writing a function, just put `byField(fieldName)`. +پس به جای اینکه یک تابع بنویسیم، فقط `byField(fieldName)` را قرار می‌دهیم. -Write the function `byField` that can be used for that. +تابع `byField` را بنویسید که می‌تواند برای این کار استفاده شود. diff --git a/1-js/06-advanced-functions/03-closure/article.md b/1-js/06-advanced-functions/03-closure/article.md index 199887063..0d2dec697 100644 --- a/1-js/06-advanced-functions/03-closure/article.md +++ b/1-js/06-advanced-functions/03-closure/article.md @@ -1,75 +1,75 @@ -# Variable scope, closure +# محدوده متغیر، کلوژِر -JavaScript is a very function-oriented language. It gives us a lot of freedom. A function can be created at any moment, passed as an argument to another function, and then called from a totally different place of code later. +جاوااسکریپت یک زبان بسیار تابع‌محور است. این زبان به ما آزادی زیادی می‌دهد. یک تابع می‌تواند در هر لحظه ساخته شود، به عنوان آرگومان به تابع دیگری داده شود و سپس بعدا در یک جای کاملا متفاوت از کد فراخوانی شود. -We already know that a function can access variables outside of it ("outer" variables). +ما از قبل می‌دانیم که یک تابع می‌تواند به متغیرهای بیرون از خودش دسترسی داشته باشد (متغیرهای «بیرونی»). -But what happens if outer variables change since a function is created? Will the function get newer values or the old ones? +اما اگر متغیرهای بیرونی از زمانی که یک تابع ساخته شد تغییر کنند چه اتفاقی می‌افتد؟ آیا تابع مقدارهای جدید را دریافت می‌کند یا قدیمی‌ها را؟ -And what if a function is passed along as a parameter and called from another place of code, will it get access to outer variables at the new place? +و اگر یک تابع به عنوان یک پارامتر رد و بدل شود و جای دیگری از کد فراخوانی شود، آیا به متغیرهای بیرونی در جای جدید دسترسی پیدا می‌کند؟ -Let's expand our knowledge to understand these scenarios and more complex ones. +بیایید دانش خود را گسترده‌تر کنیم تا این سناریوها و پیچیده‌تر از اینها را درک کنیم. -```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="اینجا ما درباره متغیرهای `let/const` حرف می‌زنیم" +در جاوااسکریپت، 3 راه برای تعریف یک متغیر وجود دارد: `let`، `const` (این دو روش مدرن هستند) و `var` (که از گذشته باقی مانده است). -- 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 . +- در این مقاله ما از متغیرهای `let` در مثال‌ها استفاده می‌کنیم. +- متغیرهایی که با `const` تعریف شوند، رفتار مشابهی دارند پس این مقاله درباره `const` هم هست. +- `var` قدیمی چند تفاوت قابل توجه دارد که در مقاله پوشش داده می‌شوند. ``` -## Code blocks +## بلوک‌های کد -If a variable is declared inside a code block `{...}`, it's only visible inside that block. +اگر یک متغیر درون بلوک کد `{...}` تعریف شود، فقط درون همان بلوک قابل رویت است. -For example: +برای مثال: ```js run { - // do some job with local variables that should not be seen outside + // یک کار با متغیرهای محلی که از بیرون نباید شناخته شوند انجام دهید - let message = "Hello"; // only visible in this block + let message = "Hello"; // فقط درون این بلوک قابل رویت است alert(message); // Hello } -alert(message); // Error: message is not defined +alert(message); // تعریف نشده است message :ارور ``` -We can use this to isolate a piece of code that does its own task, with variables that only belong to it: +ما می‌توانیم از این خاصیت برای ایزوله کردن یک قطعه از کد که دارای متغیرهایی است که فقط به آن تعلق دارند و کار خودش را انجام می‌دهد استفاده کنیم: ```js run { - // show message + // نمایش پیام let message = "Hello"; alert(message); } { - // show another message + // نمایش پیامی دیگر 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="بدون وجود بلوک‌ها ارور ایجاد خواهد شد" +لطفا در نظر داشته باشید که بدون بلوک‌های جدا اگر ما از `let` همراه با یک متغیر موجود استفاده کنیم، یک ارور ایجاد خواهد شد. ```js run -// show message +// نمایش پیام let message = "Hello"; alert(message); -// show another message +// نمایش پیامی دیگر *!* -let message = "Goodbye"; // Error: variable already declared +let message = "Goodbye"; // ارور: متغیر از قبل تعریف شده است */!* alert(message); ``` ```` -For `if`, `for`, `while` and so on, variables declared in `{...}` are also only visible inside: +برای `if`، `for`، `while` و بقیه، متغیرهایی که درون `{...}` تعریف شده باشند تنها درون آنها قابل رویت هستند: ```js run if (true) { @@ -78,53 +78,53 @@ if (true) { alert(phrase); // Hello! } -alert(phrase); // Error, no such variable! +alert(phrase); // !ارور، چنین متغیری وجود ندارد ``` -Here, after `if` finishes, the `alert` below won't see the `phrase`, hence the error. +اینجا، بعد از اینکه `if` تمام می‌شود، `alert` متغیر `phrase` را نمی‌بیند و به همین دلیل ارور ایجاد می‌شود. -That's great, as it allows us to create block-local variables, specific to an `if` branch. +این عالی است چون به ما اجازه می‌دهد که متغیرهایی در سطح بلوک محلی بسازیم که به یک شاخه `if` اختصاص دارند. -The similar thing holds true for `for` and `while` loops: +همین موضوع برای حلقه‌های `for` و `while` هم صادق است: ```js run for (let i = 0; i < 3; i++) { - // the variable i is only visible inside this for - alert(i); // 0, then 1, then 2 + // قابل رویت است for فقط درون این حلقه i متغیر + alert(i); // اول 0، سپس 1، سپس 2 } -alert(i); // Error, no such variable +alert(i); // ارور، چنین متغیری وجود ندارد ``` -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. +از لحاظ ظاهری، `let i` بیرون از `{...}` است. اما اینجا ساختار `for` خاص است: متغیری که درون آن ساخته شود، جزئی از بلوک کد فرض می‌شود. -## Nested functions +## تابع‌های تودرتو -A function is called "nested" when it is created inside another function. +به تابعی که درون تابع دیگری ساخته شود «تودرتو» گفته می‌شود. -It is easily possible to do this with JavaScript. +این کار را به راحتی در جاوااسکریپت می‌توان انجام داد. -We can use it to organize our code, like this: +می‌توانیم از آن برای سازماندهی کد خود استفاده کنیم، مثلا اینگونه: ```js function sayHiBye(firstName, lastName) { - // helper nested function to use below + // تابع کمک کننده که پایین‌تر استفاده می‌شود function getFullName() { return firstName + " " + lastName; } - alert( "Hello, " + getFullName() ); - alert( "Bye, " + getFullName() ); + alert( "سلام " + getFullName() ); + alert( "خداحافظ " + getFullName() ); } ``` -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. +اینجا تابع *تودرتو* `getFullName()` برای راحتی استفاده شده است. این تابع می‌تواند به متغیرهای بیرونی دسترسی داشته باشد پس می‌تواند اسم کامل را برگرداند. تابع‌های تودرتو در جاوااسکریپت بسیار رایج هستند. -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. +یک چیز جالب‌تر این است که یک تابع تودرتو می‌تواند برگردانده شود: حالا یا به عنوان یک ویژگی از شیءای جدید یا خودش به عنوان نتیجه برگردانده شود. بعدا می‌تواند در جایی دیگر مورد استفاده قرار بگیرد. مهم نیست کجا باشد، هنوز هم به متغیرهای بیرونی یکسان دسترسی دارد. -Below, `makeCounter` creates the "counter" function that returns the next number on each invocation: +در کد پایین، `makeCounter` تابع «شمارنده» را می‌سازد که با هر بار فراخوانی عدد بعدی را برمی‌گرداند: ```js run function makeCounter() { @@ -142,87 +142,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. +علاوه بر اینکه ساده است، گونه‌هایی که نسبت به آن کد کمی تغییر کرده‌اند موارد استفاده کاربردی‌ای دارند، برای مثال یک [سازنده عدد تصادفی](https://fa.wikipedia.org/wiki/مولد_اعداد_شبه_تصادفی) تا برای آزمایش‌های خودکار مقدارهای تصادفی تولید کند. -How does this work? If we create multiple counters, will they be independent? What's going on with the variables here? +این چگونه کار می‌کند؟ اگر ما چند شمارنده بسازیم، آیا آنها مستقل خواهند بود؟ چه چیزی در حال رخ دادن روی متغیرها است؟ -Understanding such things is great for the overall knowledge of JavaScript and beneficial for more complex scenarios. So let's go a bit in-depth. +درک چنین چیزهایی برای دانش کلی از جاوااسکریپت و سناریوهای پیچیده‌تر خوب است. پس بیایید کمی عمیق‌تر شویم. -## Lexical Environment +## محیط لغوی (Lexical Environment) -```warn header="Here be dragons!" -The in-depth technical explanation lies ahead. +```warn header="مطالب ناشناخته‌ای وجود دارند!" +توضیحات عمیق فنی را ادامه می‌خوانید. -As far as I'd like to avoid low-level language details, any understanding without them would be lacking and incomplete, so get ready. +هر چقدر که می‌خواهم از جزئیات سطح پایین زبان دوری کنم، هرگونه درکی بدون آنها کمبود دارد و کامل نیست، پس آماده باشید. ``` -For clarity, the explanation is split into multiple steps. +برای واضح بودن، توضیحات به چند مرحله تقسیم شده‌اند. -### Step 1. Variables +### مرحله 1. متغیرها -In JavaScript, every running function, code block `{...}`, and the script as a whole have an internal (hidden) associated object known as the *Lexical Environment*. +در جاوااسکریپت، هر تابع در حال اجرا، بلوک کد `{...}` و تمام اسکریپت، یک شیء درونی (پنهان) اختصاص یافته دارد که به عنوان *محیط لغوی* شناخته می‌شود. -The Lexical Environment object consists of two parts: +شیء محیط لغوی شامل دو بخش است: -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. *ذخایر محیط (Environment Record)* -- یک شیء که تمام متغیرهای محلی را به عنوان ویژگی‌های خود (و اطلاعات دیگری مانند مقدار `this`) ذخیره می‌کند. +2. یک رجوع به *محیط لغوی بیرونی (outer)*، محیطی که به کد بیرونی اختصاص دارد. -**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".** +**یک «متغیر» فقط یک ویژگی از شیء خاص درونی `Environment Record` است. «دریافت یا تغییر یک متغیر» به معنی «دریافت یا تغییر یک ویژگی از آن شیء» است.** -In this simple code without functions, there is only one Lexical Environment: +در این کد ساده که تابعی ندارد، تنها یک محیط لغوی وجود دارد: ![lexical environment](lexical-environment-global.svg) -This is the so-called *global* Lexical Environment, associated with the whole 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`. +در تصویر بالا، مستطیل به معنای ذخایر محیط (ذخایر متغیر) است و کمان به معنی مرجع بیرونی. محیط لغوی گلوبال مرجع بیرونی ندارد و به همین دلیل است که کمان به `null` اشاره می‌کند. -As the code starts executing and goes on, the Lexical Environment changes. +همانطور که کد شروع به اجرا شدن می‌کند و ادامه می‌یابد، محیط لغوی تغییر می‌کند. -Here's a little bit longer code: +یک کد طولانی‌تر را اینجا داریم: ![lexical environment](closure-variable-phrase.svg) -Rectangles on the right-hand side demonstrate how the global Lexical Environment changes during the execution: +مستطیل‌های سمت راست نشان می‌دهند که محیط لغوی گلوبال در حین اجرا شدن چگونه تغییر می‌کند: -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 from this point forward. -3. `phrase` is assigned a value. -4. `phrase` changes the value. +1. زمانی که اسکریپت شروع می‌کند، محیط لغوی از تمام متغیرهای تعریف شده پر می‌شود. + - در ابتدا، آنها در حالت «بدون مقدار اولیه (Uninitialized)» هستند. این یک حالت درونی خاص است و به این معنی است که موتور درباره متغیر آگاه است اما تا زمانی که با `let` تعریف شود نمی‌توان به آن رجوع کرد. تقریبا مانند این است که متغیر وجود ندارد. +2. تعریف `let phrase` نمایان می‌شود. هنوز مقداردهی نشده است، پس مقدار آنها `undefined` است. ما می‌توانیم از اینجا به بعد از متغیر استفاده کنیم. +3. `phrase` یک مقدار گرفته است. +4. `phrase` مقدار را تغییر می‌دهد. -Everything looks simple for now, right? +تا اینجا همه چیز ساده بنظر می‌رسد نه؟ -- 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. +- یک متغیر، ویژگی یک شیء خاص درونی است که به بلوک/تابع/اسکریپتی که در حال اجرا است اختصاص یافته. +- کارکردن با متغیرها در واقع کارکردن با ویژگی‌های آن شیء است. -```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="محیط لغوی یک شیء درون مشخصات است" +«محیط لغوی» یک شیء درون مشخصات است: این شیء فقط «به صورت تئوری» در [مشخصات زبان](https://tc39.es/ecma262/#sec-lexical-environments) وجود دارد تا چگونگی کارکردن چیزها را توصیف کند. ما نمی‌توانیم این شیء را در کدمان دریافت کنیم و آن را به صورت مستقیم دستکاری کنیم. -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. + تا آنجایی که رفتار قابل مشاهده همانطور که توصیف شد باقی بماند، موتورهای جاوااسکریپت ممکن است آن را بهینه کنند مثلا برای صرفه‌جویی در اشغال حافظه متغیرهایی که استفاده نمی‌شوند را حذف کنند و ترفندهای درونی دیگری را اجرا کنند. ``` -### Step 2. Function Declarations +### مرحله 2. Function Declaration -A function is also a value, like a variable. +یک تابع هم مانند یک متغیر، مقدار است. -**The difference is that a Function Declaration is instantly fully initialized.** +**تفاوت اینجاست که Function Declaration سریعا به طور کامل مقداردهی می‌شوند.** -When a Lexical Environment is created, a Function Declaration immediately becomes a ready-to-use function (unlike `let`, that is unusable till the declaration). +زمانی که یک محیط لغوی ساخته می‌شود، یک Function Declaration سریعا به یک تابع آماده استفاده تبدیل می‌شود (برخلاف `let` که تا زمان تعریف آن در کد غیر قابل استفاده است). -That's why we can use a function, declared as Function Declaration, even before the declaration itself. +به همین دلیل است که از تابعی که به صورت Function Declaration تعریف شده باشد، حتی قبل از رسیدن به تعریف آن می‌توانیم استفاده کنیم. -For example, here's the initial state of the global Lexical Environment when we add a function: +برای مثال، زمانی که ما یک تابع اضافه می‌کنیم وضعیت اولیه محیط لغوی گلوبال اینگونه است: ![](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)...`. +طبیعتا، این رفتار فقط برای Function Declarations است نه برای اعلان تابع Expression که ما یک متغیر را برابر با یک تابع قرار می‌دهیم مانند `let say = function(name)...`. -### Step 3. Inner and outer Lexical Environment +### مرحله 3. محیط‌های لغوی درونی و بیرونی -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. +زمانی که یک تابع اجرا می‌شود، در ابتدای فراخوانی، به طور خودکار یک محیط لغوی جدید برای ذخیره متغیرهای محلی و پارامترهای فراخوانی ایجاد می‌شود. -For instance, for `say("John")`, it looks like this (the execution is at the line, labelled with an arrow): +برای مثال، برای `say("John)"` اینگونه بنظر می‌رسد (فرایند اجرا شدن در خطی است که با کمان نشانه گذاری شده است):