Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
02bb058
Translate a part of article
mahdiHash Sep 3, 2021
c804c16
Translate a part of article
mahdiHash Sep 3, 2021
1da9b01
Translate some error messages
mahdiHash Sep 3, 2021
8e30e70
Translate a part of article
mahdiHash Sep 4, 2021
a030eca
Translate a part of article
mahdiHash Sep 4, 2021
efb7c91
Translate a part of article
mahdiHash Sep 5, 2021
b420819
Translate a part of article
mahdiHash Sep 6, 2021
645cfdc
Change some lines for better readability or understanding
mahdiHash Sep 6, 2021
3b97485
Translate a part of article
mahdiHash Sep 7, 2021
d4a1f7d
Translate a part of article
mahdiHash Sep 7, 2021
80f180f
Translate article
mahdiHash Sep 8, 2021
67c299e
Translate task of "closure-latest-changes"
mahdiHash Sep 9, 2021
328b3a9
Translate solution of "closure-latest-changes"
mahdiHash Sep 9, 2021
1a91fdf
Translate task of "closure-variable-access"
mahdiHash Sep 9, 2021
c0360a3
Translate solution of "closure-variable-access"
mahdiHash Sep 9, 2021
1698afa
Translate task of "counter-independent"
mahdiHash Sep 9, 2021
539ffcf
Translate solution of "counter-independent"
mahdiHash Sep 9, 2021
3f88e03
Translate task of "counter-object-independent"
mahdiHash Sep 9, 2021
684a4d2
Translate task of "counter-object-independent"
mahdiHash Sep 9, 2021
c641e77
Translate task of "function-in-if"
mahdiHash Sep 9, 2021
0654b5d
Translate solution of "function-in-if"
mahdiHash Sep 9, 2021
f8c0af6
Translate task of "closure-sum"
mahdiHash Sep 10, 2021
6b9c591
Translate solution of "closure-sum"
mahdiHash Sep 10, 2021
8dc9297
Translate task of "let-scope"
mahdiHash Sep 10, 2021
ef57382
Translate solution of "let-scope"
mahdiHash Sep 10, 2021
26678cb
Change a comment for better readability
mahdiHash Sep 10, 2021
eb9f373
Translate task of "filter-through-function"
mahdiHash Sep 10, 2021
53eaa4a
Translate task of "sort-by-field"
mahdiHash Sep 10, 2021
5dfb504
Translate task of "make-army"
mahdiHash Sep 10, 2021
d22754e
Translate solution of "make-army"
mahdiHash Sep 10, 2021
b7290e2
Translate a word
mahdiHash Sep 10, 2021
d238e45
Add the deleted line
mahdiHash Sep 10, 2021
f973524
Remove the untranslated line
mahdiHash Sep 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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.
مقدارهای قدیمی متغیر جایی ذخیره نمی‌شوند. زمانی که تابعی یک متغیر را می‌خواهد، مقدار کنونی آن را از محیط لغوی خودش یا محیط بیرونی دریافت می‌کند.
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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?
پس سوال این است: آیا این تابع آخرین تغییرات را دریافت می‌کند؟
58 changes: 29 additions & 29 deletions 1-js/06-advanced-functions/03-closure/10-make-army/solution.md
Original file line number Diff line number Diff line change
@@ -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 = [
Expand All @@ -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() {
Expand All @@ -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++;
Expand All @@ -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() {
Expand All @@ -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);
}
Expand All @@ -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` ترجیح دهد یا سناریوهای دیگر در میان باشند که چنین مشکلاتی واقعا پیش بیایند.

28 changes: 14 additions & 14 deletions 1-js/06-advanced-functions/03-closure/10-make-army/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,40 @@ 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() {
let shooters = [];

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.
کد را درست کنید تا همانطور که می‌خواهیم کار کند.

Original file line number Diff line number Diff line change
@@ -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"` می‌شد.
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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"؟
Original file line number Diff line number Diff line change
@@ -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` خودش را دارد.
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
تابع `sayHi` درون `if` تعریف شده است پس فقط درون آن وجود دارد. بیرون از آن `sayHi` نداریم.
Original file line number Diff line number Diff line change
@@ -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";
Expand Down
Original file line number Diff line number Diff line change
@@ -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" متغیر
};

}
Expand Down
8 changes: 4 additions & 4 deletions 1-js/06-advanced-functions/03-closure/6-closure-sum/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading