You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/04-var/article.md
+97-78Lines changed: 97 additions & 78 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,18 +1,34 @@
1
1
2
-
# The old "var"
2
+
# إفادة «var» القديمة
3
3
4
-
```smart header="This article is for understanding old scripts"
5
-
The information in this article is useful for understanding old scripts.
4
+
```smart header="هذه المقالة من أجل فهم النصوص القديمة"
5
+
المعلومات داخل هذه المقالة تساعدنا فى فهم النصوص القديمة أكثر ولا تحتوي علي أي معلومات عن كيفية كتابة كود جديد
6
6
7
-
That's not how we write a new code.
8
7
```
9
8
10
-
In the very first chapter about [variables](info:variables), we mentioned three ways of variable declaration:
9
+
ذكرنا في أوائل الفصول حين تكلمنا عن [المتغيرات](info:variables), ذكرنا ثلاث طرائق للتصريح عنها:
11
10
12
11
1.`let`
13
12
2.`const`
14
13
3.`var`
15
14
15
+
16
+
تصرّف كلا الإفادتين `let` و`const` بذات الطريقة (بالمقايسة مع البيئات المُعجمية).
17
+
18
+
بينما `var` فهو وحش آخر مختلف جذريًا ويعود في أصله إلى قرون سحيقة. لا نستعمله عادةً في السكربتات الحديثة ولكنّك ستجده حتمًا خلف إحدى صخور السكربتات القديمة.
19
+
20
+
لو لم ترغب بالتعرّف على هذه السكربتات فيمكنك تخطّي هذا الفصل أو تأجيله لوقت لاحق. ولكن لا تنسَ احتمالية ندمك لاحقًا فيغدر بك هذا الوحش.
21
+
22
+
من أول وهلة نرى بأنّ تصرّف `var` يشابه تصرّف `let`، أي أنّه يُصرّح (مثل الثاني) عن متغير:
23
+
24
+
25
+
```js run
26
+
functionsayHi() {
27
+
var phrase ="Hello"; // متغير محلي، استعملنا «var» بدل «let»
28
+
29
+
alert(phrase); // Hello
30
+
}
31
+
=======
16
32
The `var` declaration is similar to `let`. Mostof the time we can replace `let` by `var` or vice-versa and expect things to work:
17
33
18
34
```js run
@@ -22,69 +38,79 @@ alert(message); // Hi
22
38
23
39
But internally `var` is a very different beast, that originates from very old times. It's generally not used in modern scripts, but still lurks in the old ones.
24
40
41
+
alert(phrase); // خطأ، phrase غير معرّف
42
+
43
+
```
44
+
45
+
ولكن... ما خفي كان أعظم. إليك الفروق.
46
+
=======
25
47
If you don't plan on meeting such scripts you may even skip this chapter or postpone it.
26
48
27
49
On the other hand, it's important to understand differences when migrating old scripts from `var` to `let`, to avoid odd errors.
28
50
29
51
## "var" has no block scope
30
52
31
-
Variables, declared with `var`, are either function-wide or global. They are visible through blocks.
53
+
حين نصرّح عن المتغيرات باستعمال `var` نكون جعلناها معروفة للدالة كاملةً (لو كانت في دالة) أو عمومية في السكربت. يمكنك أن ترى تلك المتغيرات إن اخترقت «جدران» الكُتل.
54
+
55
+
مثال:
32
56
33
-
For instance:
34
57
35
58
```js run
36
59
if (true) {
37
-
var test =true; //use "var" instead of "let"
60
+
var test = true; // نستعمل «var» بدل «let»
38
61
}
39
62
40
-
*!*
41
-
alert(test); // true, the variable lives after if
42
-
*/!*
63
+
alert(test); // الناتج true، أي أنّ المتغير «حيّ يُرزق» بعد إفادة if
64
+
43
65
```
44
66
45
-
As `var` ignores code blocks, we've got a global variable `test`.
46
67
47
-
If we used `let test` instead of `var test`, then the variable would only be visible inside `if`:
68
+
تجاهل `var` كتل الشيفرة، وبهذا صار متغير `test` عموميًا.
69
+
70
+
لو استعملنا `let test` بدل `var test` فسيكون المتغير ظاهرًا لباقي الشيفرة داخل إفادة `if` فقط لا غير:
71
+
48
72
49
73
```js run
50
74
if (true) {
51
-
let test =true; //use "let"
75
+
let test = true; // نستعمل «let»
52
76
}
53
77
54
-
*!*
55
-
alert(test); // Error: test is not defined
56
-
*/!*
57
-
```
78
+
alert(test); // خطأ: لم يُعرّف عن test
58
79
59
-
The same thing for loops: `var` cannot be block- or loop-local:
80
+
```
81
+
يسري الأمر ذاته على الحلقات فلا يمكن أن يكون `var` محليًا حسب الكتلة أو حسب الحلقة:
60
82
61
83
```js
62
84
for (var i = 0; i < 10; i++) {
63
85
// ...
64
86
}
65
87
66
-
*!*
67
-
alert(i); // 10, "i" is visible after loop, it's a global variable
68
-
*/!*
88
+
alert(i); // 10، ظهر «i» بعد الحلقة فهو متغير عمومي
89
+
69
90
```
70
91
71
-
If a code block is inside a function, then `var` becomes a function-level variable:
92
+
لو كتبت كتلة شيفرة في دالة فسيصير `var` متغيرًا على مستوى الدالة كاملةً.
72
93
73
94
```js run
74
95
function sayHi() {
75
96
if (true) {
76
97
var phrase = "Hello";
77
98
}
78
99
79
-
alert(phrase); //works
100
+
alert(phrase); // يمكننا فعل هذا
80
101
}
81
102
82
103
sayHi();
83
-
alert(phrase); // Error: phrase is not defined (Check the Developer Console)
104
+
alert(phrase); // خطأ: phrase غير معرّف (طالِع مِعراض المطوّر)
105
+
84
106
```
85
107
86
-
As we can see, `var` pierces through `if`, `for` or other code blocks. That's because a long time ago in JavaScript blocks had no Lexical Environments. And `var` is a remnant of that.
108
+
كما نرى فإفادة `var` تخترق كُتل `if` و`for` وغيرها من كُتل شيفرة. يعزو ذلك إلى أنّه في الزمن الماضي الجميل لم تكن لكُتل جافاسكربت بيئات مُعجمية. و`var` إحدى آثار ذلك الزمن.
87
109
110
+
## تُعالج التصريحات باستعمال `var` عند بدء الدالة
111
+
112
+
ُعالج التصريحات باستعمال `var` متى ما بدأت الدالة (أو بدأ السكربت، للمتغيرات العمومية).
113
+
=======
88
114
## "var" tolerates redeclarations
89
115
90
116
If we declare the same variable with `let` twice in the same scope, that's an error:
@@ -107,111 +133,105 @@ alert(user); // John
107
133
108
134
## "var" variables can be declared below their use
109
135
110
-
`var` declarations are processed when the function starts (or script starts for globals).
136
+
أي أنّ متغيرات `var` تُعرّف من بداية الدالة مهما كان مكان تعريفها (هذا لو لم يكن التعريف في دالة متداخلة أخرى).
111
137
112
-
In other words, `var` variables are defined from the beginning of the function, no matter where the definition is (assuming that the definition is not in the nested function).
138
+
يعني ذلك أنّ هذه الشيفرة:
113
139
114
-
So this code:
115
140
116
141
```js run
117
142
functionsayHi() {
118
143
phrase ="Hello";
119
144
120
145
alert(phrase);
121
146
122
-
*!*
123
147
var phrase;
124
-
*/!*
125
148
}
126
149
sayHi();
127
-
```
128
150
129
-
...Is technically the same as this (moved `var phrase` above):
151
+
```
152
+
متطابقة تقنيًا مع هذه (بتحريك `var phrase` إلى أعلى):
130
153
131
154
```js run
132
155
functionsayHi() {
133
-
*!*
134
156
var phrase;
135
-
*/!*
136
157
137
158
phrase ="Hello";
138
159
139
160
alert(phrase);
140
161
}
141
162
sayHi();
142
-
```
143
163
144
-
...Or even as this (remember, code blocks are ignored):
164
+
```
145
165
166
+
أو حتى هذه (لا تنسَ بأنّ كُتل الشيفرات مُهملة):
146
167
```js run
147
168
functionsayHi() {
148
169
phrase ="Hello"; // (*)
149
170
150
-
*!*
151
171
if (false) {
152
172
var phrase;
153
173
}
154
-
*/!*
155
174
156
175
alert(phrase);
157
176
}
158
177
sayHi();
178
+
159
179
```
180
+
يدعو الناس هذا السلوك بسلوك «الطفو» _hoisting_ (أو الرفع) إذ أنّ متغيرات `var` «تطفو» إلى أعلى الدالة (أو ترتفع إلى أعلاها).
160
181
161
-
People also call such behavior "hoisting" (raising), because all `var` are "hoisted" (raised) to the top of the function.
182
+
أي أنّه في المثال أعلاه، الفرع `if (false)` من الإفادة لا يعمل قط ولكن هذا ليس بمهم، إذ أنّ `var` داخله سيُعالج في بداية الدالة، وحين تصل عملية التنفيذ إلى `(*)` سيكون المتغير موجودًا لا محالة.
162
183
163
-
So in the example above, `if (false)` branch never executes, but that doesn't matter. The `var` inside it is processed in the beginning of the function, so at the moment of `(*)` the variable exists.
184
+
**التصريحات تطفو صحيح، ولكنّ ليس عبارات الإسناد.**
164
185
165
-
**Declarations are hoisted, but assignments are not.**
186
+
الأفضل لو نمثّل ذلك في هذا المثال:
166
187
167
-
That's best demonstrated with an example:
168
188
169
189
```js run
170
190
functionsayHi() {
171
191
alert(phrase);
172
192
173
-
*!*
174
193
var phrase ="Hello";
175
-
*/!*
176
194
}
177
195
178
196
sayHi();
197
+
179
198
```
180
199
181
-
The line `var phrase = "Hello"` has two actions in it:
200
+
في السطر `var phrase = "Hello"` إجراءان اثنان:
201
+
202
+
1. التصريح عن المتغير باستعمال `var`
203
+
2. إسناد قيمة للمتغير باستعمال `=`.
182
204
183
-
1. Variable declaration `var`
184
-
2. Variable assignment `=`.
205
+
يتعامل المحرّك مع التصريحات متى بدء تنفيذ الدالة (إذ التصريحات تطفو)، ولكنّ عبارة الإسناد لا تعمل إلّا حيثما ظهرت، فقط. إذًا فالشيفرة تعمل بهذا النحو فعليًا:
185
206
186
-
The declaration is processed at the start of function execution ("hoisted"), but the assignment always works at the place where it appears. So the code works essentially like this:
187
207
188
208
```js run
189
209
functionsayHi() {
190
-
*!*
191
-
var phrase; // declaration works at the start...
192
-
*/!*
210
+
var phrase; // بادئ ذي بدء، يعمل التصريح...
193
211
194
-
alert(phrase); //undefined
212
+
alert(phrase); //غير معرّف
195
213
196
-
*!*
197
-
phrase ="Hello"; // ...assignment - when the execution reaches it.
198
-
*/!*
214
+
phrase ="Hello"; // ...هنا.
199
215
}
200
216
201
217
sayHi();
218
+
202
219
```
203
220
204
-
Because all `var` declarations are processed at the function start, we can reference them at any place. But variables are undefined until the assignments.
221
+
يُعالج المحرّك التصريحات `var` حين تبدأ الدوال، وبهذا يمكننا الإشارة إليها أينما أردنا في الشيفرة. ولكن انتبه فالمتغيرات غير معرّفة حتى تُسند إليها قيم.
222
+
223
+
في الأمثلة أعلاه عمل التابِع `alert` دون أيّ أخطاء إذ أن المتغير `phrase` موجود. ولكن لم تُسند فيه قيمة بعد فعرض `undefined`.
205
224
206
-
In both examples above `alert` runs without an error, because the variable `phrase` exists. But its value is not yet assigned, so it shows `undefined`.
207
225
208
-
### IIFE
226
+
### تعريف الدالة المناداة تواً (IIFE)
209
227
210
-
As in the past there was only `var`, and it has no block-level visibility, programmers invented a way to emulate it. What they did was called "immediately-invoked function expressions" (abbreviated as IIFE).
228
+
في الماضي كان هناك فقط `var`, وليس له مستوي كتلة, لكن المبرمجين إخترعوا طريقة لحل ذلك. التي تسمي
211
229
212
-
That's not something we should use nowadays, but you can find them in old scripts.
هذا لا يستخدم حالياً, لكن تستطيع إيجادهم في النصوص القديمة.
233
+
234
+
طريقة كتابة (IIFE):
215
235
216
236
```js run
217
237
(function() {
@@ -222,13 +242,13 @@ An IIFE looks like this:
222
242
223
243
})();
224
244
```
245
+
هذا يعتبر تعريف دالة صُنعت وتمت مناداتها على الفور. لذلك يتم تنفيذ الكود ولها متغيراتها الخاصة.
225
246
226
-
Here a Function Expression is created and immediately called. So the code executes right away and has its own private variables.
247
+
يتم تغليف تعريف الدالة يتم تغليفه بداخل قوسين (function {...})`, لأن عندما تقابل جافاسكريبت `"function"` في الكود الأساسي, تفهمها علي أنها بداية تعريف دالة ولكن بدون إسم لذلك يعطينا خطأ:
227
248
228
-
The Function Expression is wrapped with parenthesis `(function {...})`, because when JavaScript meets `"function"` in the main code flow, it understands it as the start of a Function Declaration. But a Function Declaration must have a name, so this kind of code will give an error:
229
249
230
250
```js run
231
-
//Try to declare and immediately call a function
251
+
//محاولة صنع دالة فورية التنفيذ
232
252
function() { // <-- Error: Function statements require a function name
233
253
234
254
let message ="Hello";
@@ -237,19 +257,19 @@ function() { // <-- Error: Function statements require a function name
237
257
238
258
}();
239
259
```
240
-
241
-
Even if we say: "okay, let's add a name", that won't work, as JavaScript does not allow Function Declarations to be called immediately:
260
+
حتي لو وضعنا إسم, لن يعمل هذا, لأن جافاسكريبت لا تسمح بتعريف دالة ستتم مناداتها فورياً:
242
261
243
262
```js run
244
-
//syntax error because of parentheses below
263
+
//هذا خطأ بسبب الأقواس الموجودة بالأسفل
245
264
functiongo() {
246
265
247
-
}();// <-- can't call Function Declaration immediately
266
+
}();
248
267
```
249
268
250
-
So, the parentheses around the function is a trick to show JavaScript that the function is created in the context of another expression, and hence it's a Function Expression: it needs no name and can be called immediately.
269
+
لذلك, الأقواس حول الدالة تعتبر خدعة لجعل جافاسكريبت فهم أننا نصنع سياق أخر للتعريف, لذلك إن تعريف الدالة: لا يحتاج إلي اسم لذلك تتم مناداتها علي الفور
270
+
251
271
252
-
There exist other ways besides parentheses to tell JavaScript that we mean a Function Expression:
272
+
هناك أيضاً طرق أخرى:
253
273
254
274
```js run
255
275
// Ways to create IIFE
@@ -271,15 +291,14 @@ There exist other ways besides parentheses to tell JavaScript that we mean a Fun
271
291
}();
272
292
```
273
293
274
-
In all the above cases we declare a Function Expression and run it immediately. Let's note again: nowadays there's no reason to write such code.
294
+
## ملخص
275
295
276
-
## Summary
296
+
هناك فرقين جوهرين بين `var` موازنةً بِـ `let/const`:
277
297
278
-
There are two main differences of `var` compared to `let/const`:
298
+
1. ليس لمتغيرات `var` نطاقًا كتليًا وأصغر نطاق لها هو في الدوال.
299
+
2. تُعالج التصريحات باستعمال `var` عند بدء الدالة (أو بدء السكربت، للمتغيرات العمومية).
279
300
280
-
1.`var` variables have no block scope, they are visible minimum at the function level.
281
-
2.`var` declarations are processed at function start (script start for globals).
301
+
هناك فرق آخر صغير يتعلّق بالكائن العمومي وسنشرحه في الفصل التالي.
282
302
283
-
There's one more very minor difference related to the global object, that we'll cover in the next chapter.
303
+
بهذا، غالبًا ما يكون استعمال `var` أسوأ بكثير من `let` بعدما عرفت الفروق بينها، فالمتغيرات على مستوى الكُتل أمر رائع جدًا ولهذا السبب تمامًا أُضيفت `let` إلى معيار اللغة منذ زمن وصارت الآن الطريقة الأساسية (هي و`const`) للتصريح عن متغير.
284
304
285
-
These differences make `var` worse than `let` most of the time. Block-level variables is such a great thing. That's why `let` was introduced in the standard long ago, and is now a major way (along with `const`) to declare a variable.
0 commit comments