Skip to content

Commit 8995be3

Browse files
authored
Merge pull request #287 from afilahkle/master
Variable scope, closure
2 parents d9a9d00 + 09e19ee commit 8995be3

File tree

3 files changed

+40
-45
lines changed

3 files changed

+40
-45
lines changed

1-js/06-advanced-functions/03-closure/10-make-army/solution.md

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
Let's examine what exactly happens inside `makeArmy`, and the solution will become obvious.
1+
دعنا نفحص ما يحدث بالضبط داخل `makeArmy`، وسيصبح الحل واضحًا.
22

33
1. تُنشئ مصفوفة `‎shooters‎` فارغة:
44

5-
```js
5+
````js
66
let shooters = [];
77
```
88

9-
2. Fills it with functions via `shooters.push(function)` in the loop.
9+
2. يتم ملؤها بالدوال باستخدام `shooters.push(function)` في الحلقة.
1010

1111
```js no-beautify
1212
shooters = [
@@ -43,17 +43,17 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
4343
];
4444
```
4545

46-
3. The array is returned from the function.
46+
3. يتم إرجاع المصفوفة من الدالة.
4747

48-
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.
48+
ثم في وقت لاحق، سيتم استدعاء أي عضو، على سبيل المثال `army[5]()`، وسيتم الحصول على العنصر `army[5]` من المصفوفة (وهو دالة) ويتم استدعاؤها.
4949

50-
Now why do all such functions show the same value, `10`?
50+
السؤال هو لماذا تظهر لجميع الدوال نفس القيمة، وهي الرقم `10`؟
5151

52-
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.
52+
يحدث ذلك لأنه لا يوجد متغير محلي بإسم `i` داخل دوال `shooter`. عند استدعاء مثل هذه الدالة، فإنه يتم أخذ `i` من البيئة اللغوية الخارجية.
5353

54-
Then, what will be the value of `i`?
54+
إذاً، ماهي قيمة `i`؟
5555

56-
If we look at the source:
56+
إذا نظرنا إلى الشفرة المصدرية:
5757

5858
```js
5959
function makeArmy() {
@@ -70,13 +70,13 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
7070
}
7171
```
7272

73-
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`).
74-
75-
As the result, all `shooter` functions get the same value from the outer lexical environment and that is, the last value, `i=10`.
73+
يمكننا ملاحظة أن جميع دوال `shooter` يتم إنشاؤها في البيئة اللغوية الخارجية لدالة `makeArmy()`، لكن عندما يتم استدعاء `army[5]()`، فقدانتهت دالة `makeArmy` من عملها وأصبحت قيمة `i` هي الأخيرة وهي `10` (حيث يتوقف الحلقة عند `i=10`)،
74+
75+
وبالتالي، جميع دوال `shooter` ستحصل على نفس القيمة من البيئة اللغوية الخارجية وهي القيمة الأخيرة `i=10`.
7676

7777
![](lexenv-makearmy-empty.svg)
7878

79-
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:
79+
كما ترون في الصورة أعلاه، في كل تكرار لكتلة `while {...}` يتم إنشاء بيئة لغوية جديدة. لحل هذه المشكلة، يمكننا نسخ قيمة `i` في متغير داخل كتلة `while {...}`، مثل هذا:
8080

8181
```js run
8282
function makeArmy() {
@@ -99,18 +99,18 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
9999
100100
let army = makeArmy();
101101
102-
// Now the code works correctly
102+
// الآن يعمل الكود بشكل صحيح
103103
army[0](); // 0
104104
army[5](); // 5
105105
```
106106

107-
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.
107+
هنا `let j = i` يعلن عن متغير "محلي للتكرار" `j` ويقوم بنسخ `i` فيه. القيم الأساسية تنسخ "بالقيمة"، لذلك نحصل فعليًا على نسخة مستقلة من `i` تنتمي إلى تكرار الحلقة الحالي.
108108

109-
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 the current loop iteration:
109+
يعمل الدوال `shooter` بشكل صحيح، لأن قيمة `i` تعيش الآن قليلاً أقرب. ليس في بيئة اللغة الخارجية لـ `makeArmy()`، ولكنفي البيئة اللغوية الخارجية التي تتوافق مع التكرار الحالي:
110110

111111
![](lexenv-makearmy-while-fixed.svg)
112112

113-
Such problem could also be avoided if we used `for` in the beginning, like this:
113+
كما يمكن تجنب مشكلة من هذا النوع إذا استخدمنا `for` في البداية، مثل هذا:
114114

115115
```js run demo
116116
function makeArmy() {
@@ -135,12 +135,12 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
135135
army[5](); // 5
136136
```
137137

138-
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.
138+
هذا بشكل أساسي نفس الأمر، لأن `for` في كل تكرار ينشئ بيئة لغوية جديدة، مع متغير `i` الخاص به. لذلك تشير الدالة التي تم إنشاؤها في كل تكرار إلى `i` الخاص بها، من تلك التكرار.
139139

140140
![](lexenv-makearmy-for-fixed.svg)
141141

142-
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?
142+
الآن، بعد أن قدمنا جهدًا كبيرًا في قراءة هذا الحل، وأن الوصفة النهائية هي بسيطة - استخدم `for` - قد تتساءل: هل كان ذلك يستحق كل هذا العناء؟
143143

144-
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.
144+
حسنًا، إذا كان بإمكانك الإجابة على السؤال بسهولة، فلن تقرأ الحل. لذلك، نأمل أن يكون قد ساعدك هذا السؤال على فهم الأمور بشكل أفضل.
145145

146-
Besides, there are indeed cases when one prefers `while` to `for`, and other scenarios, where such problems are real.
146+
بالإضافة إلى ذلك، ه

1-js/06-advanced-functions/03-closure/10-make-army/task.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@ army[2](); // 10 ...and so on.
3535
*/!*
3636
```
3737

38-
Why do all of the shooters show the same value?
38+
لماذا يظهر لكل من المدفعين الرقم نفسه؟
3939

40-
Fix the code so that they work as intended.
40+
قم بإصلاح الكود حتى يعمل كما هو مفترض به.

1-js/06-advanced-functions/03-closure/article.md

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
# نطاق المُتغير
21

3-
# Variable scope, closure
2+
# نطاق المتغيرات، الإغلاق
43

5-
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.
4+
جافا سكريبت هي لغة موجهة نحو الدوال. تمنحنا اللغة حرية كبيرة، حيث يمكن إنشاء دالة في أي وقت، وإرسالها كوسيط لدالة أخرى ومن ثم استدعائها من مكان مختلف في الكود لاحقًا.
65

7-
We already know that a function can access variables outside of it ("outer" variables).
6+
نحن بالفعل نعلم أن الدالة يمكنها الوصول إلى المتغيرات الخارجية منها ("المتغيرات الخارجية").
87

9-
But what happens if outer variables change since a function is created? Will the function get newer values or the old ones?
8+
ولكن ماذا يحدث إذا تغيرت المتغيرات الخارجية بعد إنشاء الدالة؟ هل ستحصل الدالة على القيم الأحدث أم القيم القديمة؟
109

11-
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?
10+
وماذا إذا تم تمرير دالة كمعلمة واستدعاؤها من مكان آخر في الكود؟ هل ستحصل الدالة على وصول إلى المتغيرات الخارجية في المكان الجديد؟
1211

13-
Let's expand our knowledge to understand these scenarios and more complex ones.
12+
دعنا نوسع معرفتنا لفهم هذه السيناريوهات والسيناريوهات الأكثر تعقيدًا.
1413

1514
سنتحدث عن المُتغيرات `let/const` هنا
1615

@@ -203,11 +202,11 @@ alert(counter()); // 2
203202

204203
# بسيط حتّى الآن، أم لا؟
205204

206-
1. When the script starts, the Lexical Environment is pre-populated with all declared variables.
207-
- 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.
208-
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.
209-
3. `phrase` is assigned a value.
210-
4. `phrase` changes the value.
205+
1. عند بدء تشغيل البرنامج، تمتلئ البيئة اللغوية (Lexical Environment) مسبقًا بجميع المتغيرات المعلنة.
206+
- في البداية، تكون المتغيرات في الحالة "Uninitialized". هذه حالة داخلية خاصة، وتعني أن المحرك يعرف المتغير، ولكن لا يمكن الإشارة إليه حتى يتم تعريفه بـ `let`. إنها تقريبًا نفس الشيء كما لو أن المتغير لم يكن موجودًا.
207+
2. ثم يظهر تعريف `let phrase`. لا يوجد تعيين حتى الآن، لذلك قيمتها هي `undefined`. يمكننا استخدام المتغير من هذه النقطة فصاعدًا.
208+
3. يتم تعييين قيمة `phrase`.
209+
4. تتغير قيمة `phrase`.
211210

212211
- المتغير هو فعليًا خاصية لإحدى الكائنات الداخلية الخاصة، وهذا الكائن مرتبط بالكتلة أو الدالة أو السكربت الذي يجري تنفيذه حاليًا.
213212
- حين نعمل مع المتغيرات نكون في الواقع نعمل مع خصائص ذلك الكائن.
@@ -310,10 +309,7 @@ let counter = makeCounter();
310309

311310
![](closure-makecounter-nested-call.svg)
312311

313-
# الأن عندما يبدأ الكود في البحث عن المتغير `count` داخل الدالة `counter()`, يبحث أولاً في البيئة المعجمية الخاصة به وإذا كانت فارفة يبحث في البيئة المعجمية الخارجية, ثم الخارج ثم الخارج حتي يجده.
314-
315-
Now when the code inside `counter()` looks for `count` variable, it first searches its own Lexical Environment (empty, as there are no local variables there), then the Lexical Environment of the outer `makeCounter()` call, where it finds and changes it.
316-
312+
الآن عندما يبحث الكود داخل `counter()` عن متغير `count` ، يبحث أولاً في بيئته اللغوية الخاصة (التي تكون فارغة ، لأنه لا توجد متغيرات محلية هناك) ، ثم في بيئة `makeCounter()` الخارجية التي يتم استدعاؤها منها، حيث يجد المتغير ويقوم بتغييره.
317313
** المتغير تم تعديله في البيئة المعجمية حيث يعيش.**
318314

319315
ها هي الحالة بعد التنفيذ:
@@ -337,9 +333,9 @@ A [المنغلقات](https://en.wikipedia.org/wiki/Closure_(computer_programmi
337333

338334
عادةً ما تُمسح وتُحذف البيئة المُعجمية بعدما تعمل الدالة
339335

340-
However, if there's a nested function that is still reachable after the end of a function, then it has `[[Environment]]` property that references the lexical environment.
336+
ومع ذلك، إذا كان هناك دالة متداخلة يمكن الوصول إليها بعد انتهاء الدالة الأصلية، فإن لديها خاصية `[[Environment]]` التي تشير إلى البيئة اللغوية.
341337

342-
In that case the Lexical Environment is still reachable even after the completion of the function, so it stays alive.
338+
في هذه الحالة، يمكن الوصول إلى البيئة اللغوية حتى بعد اكتمال الدالة، لذلك تبقى حية.
343339

344340
مثال:
345341

@@ -356,7 +352,7 @@ let g = f(); // g.[[Environment]] stores a reference to the Lexical Environment
356352
// of the corresponding f() call
357353
```
358354

359-
Please note that if `f()` is called many times, and resulting functions are saved, then all corresponding Lexical Environment objects will also be retained in memory. In the code below, all 3 of them:
355+
يرجى ملاحظة أنه إذا تم استدعاء `f()` العديد من المرات، وتم حفظ الدوال الناتجة، فسيتم الإحتفاظ بجميع كائنات البيئة اللغوية المقابلة في الذاكرة. في الكود أدناه، سيتم الإحتفاظ بجميع الكائنات اللغوية الثلاثة:
360356

361357
```js
362358
function f() {
@@ -395,7 +391,6 @@ g = null; // ...والآن لم تعد كذلك ونكون قد نظّفنا ا
395391

396392
كما رأينا، فنظريًا طالما الدالة «حيّة تُرزق» تبقى معها كل متغيراتها الخارجية.
397393

398-
**An important side effect in V8 (Chrome, Edge, Opera) is that such variable will become unavailable in debugging.**
399394

400395
**ثمّة -في محرّك V8 (كروم وأوبرا)- تأثير مهمّ ألا وهو أنّ هذا المتغير لن يكون مُتاحًا أثناء التنقيح.**
401396

@@ -439,6 +434,6 @@ let g = f();
439434
g();
440435
```
441436

442-
This feature of V8 is good to know. If you are debugging with Chrome/Edge/Opera, sooner or later you will meet it.
437+
هذه الميزة في V8 جيدة للمعرفة. إذا كنت تقوم بتصحيح الأخطاء باستخدام Chrome / Edge / Opera ، في وقت ما ستواجه هذه الميزة.
443438

444-
That is not a bug in the debugger, but rather a special feature of V8. Perhaps it will be changed sometime. You can always check for it by running the examples on this page.
439+
لا يعتبر هذا خطأ في مصحح الأخطاء ، بل هو ميزة خاصة في V8. ربما سيتم تغييرها في وقت ما. يمكنك دائمًا التحقق من ذلك عن طريق تشغيل الأمثلة على هذه الصفحة.

0 commit comments

Comments
 (0)