<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A; JavaScript</title><link>https://academy.hsoub.com/programming/javascript/page/12/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A; JavaScript</description><language>ar</language><item><title>&#x627;&#x644;&#x646;&#x648;&#x639; &#x627;&#x644;&#x631;&#x645;&#x632;&#x64A; (Symbol) &#x641;&#x64A; &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A;</title><link>https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%86%D9%88%D8%B9-%D8%A7%D9%84%D8%B1%D9%85%D8%B2%D9%8A-symbol-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r798/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/28.jpg.6e8af14b459419dddcef6637325e249e.jpg" /></p>

<p>
	وفقًا للمواصفات، قد تكون مفاتيح خصائص الكائنات من نوع نصي (string) أو رمزي (Symbol)، ولا تكون أرقامًا ولا قيمًا منطقية، إما نصًا أو رمزًا فقط.
</p>

<p>
	حتى الآن، استخدمنا النوع النصي فقط. الآن، لنرى فوائد النوع الرمزي.
</p>

<h2>
	الرموز
</h2>

<p>
	يُمَثِّل الرمز مُعَرِّفًا فريدًا، ويمكن إنشاء قيمة من هذا النوع باستخدام <code>Symbol()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_7" style="">
<span class="com">// هو رمز جديد id </span><span class="pln">
let id </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">();</span></pre>

<p>
	يمكننا إعطاء وصف للرمز أثناء الإنشاء (ما يُسمَّى أيضًا باسم الرمز)، ويكون مفيدًا لعملية تصحيح الأخطاء:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_9" style="">
<span class="com">// "id" هو رمز مع الوصف id</span><span class="pln">
let id </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span></pre>

<p>
	تتصف الرموز بكونها فريدة حتى إن أنشأنا أكثر من رمز بالوصف ذاته، تبقى الرموز قيمًا مختلفة. يُعد الوصف مجرد طابع ولا يؤثر على أي شيء.
</p>

<p>
	مثلًا، هنا رمزين بالوصف ذاته لكنهما غير متساويان:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_11" style="">
<span class="pln">let id1 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">
let id2 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln">id1 </span><span class="pun">==</span><span class="pln"> id2</span><span class="pun">);</span><span class="pln"> </span><span class="com">// false</span></pre>

<p>
	إن كانت لديك خلفية عن لغة Ruby أو أي لغة برمجية أخرى تستخدم الرموز فلا تخلط الأمور. فالرموز في JavaScript مختلفة.
</p>

<p>
	<strong>لا تتحول الرموز تلقائيًا إلى نص</strong>
</p>

<p>
	تتضمن أغلب القيم في JavaScript تحويلًا ضمنيًا إلى نص. مثلًا، يمكننا عرض أي قيمة تقريبا باستخدام <code>alert</code> وتعمل بشكل صحيح. لكن الرموز خاصة، فهي لا تتحول تلقائيًا. مثلا، أمر <code>alert</code> التالي سَيعرض خطأ:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_13" style="">
<span class="pln">let id </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">id</span><span class="pun">);</span><span class="pln"> </span><span class="com">// TypeError: Cannot convert a Symbol value to a string</span></pre>

<p>
	يُعد هذا الأمر من حرَّاس اللغة لتجنب الخطأ، لأن النصوص والرموز مختلفة جذريًا ولا يجب أن يتحول نوع منهما للآخر عن طريق الخطأ.
</p>

<p>
	إن كنا نريد عرض رمز ما، يجب أن نستدعي الدالة <code>.toString()‎</code>. كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_15" style="">
<span class="pln">let id </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">id</span><span class="pun">.</span><span class="pln">toString</span><span class="pun">());</span><span class="pln"> </span><span class="com">// Symbol(id), أصبحت تعمل الآن</span></pre>

<p>
	أو استخدم الخاصية <code>symbol.description</code> لعرض الوصف فقط:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_17" style="">
<span class="pln">let id </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">id</span><span class="pun">.</span><span class="pln">description</span><span class="pun">);</span><span class="pln"> </span><span class="com">// id</span></pre>

<h2>
	خاصيات "خفية"
</h2>

<p>
	تتيح لنا الرموز إنشاء خاصيات "خفية" للكائن، والتي لا يمكن لأي شيفرة الوصول إليها وتغيير محتواها حتى عن طريق الخطأ. مثلا، إن كنا نتعامل مع كائنات تنتمي إلى شيفرة من طرف ثالث ونريد إضافة مُعرفات لها، نستخدم مفتاحًا رمزيًا لذلك:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_19" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// ينتمي لِشيفرة أخرى</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

let id </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">

user</span><span class="pun">[</span><span class="pln">id</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> user</span><span class="pun">[</span><span class="pln">id</span><span class="pun">]</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// يمكننا الوصول إلى البيانات باستخدام الرمز كمفتاح</span></pre>

<p>
	ما الفائدة من استخدام <code>Symbol("id")‎</code> على النص <code>"id"</code>؟ بما أن كائنات <code>user</code> تنتمي لِشيفرة أخرى، وبما أن الشيفرة أعلاه تتعامل معها فليس آمنًا إضافة أي حقل لها. لكن لا يمكن الوصول إلى الرمز حتى عن طريق الخطأ، قد لا تراه شيفرة الطرف الثالث أيضًا، لذا فإنها الطريقة الصحيحة للقيام بذلك.
</p>

<p>
	تخيل أيضًا أن سكريبت آخر يريد إضافة معاملاته الخاصة بِداخل <code>user</code> لغرضه الخاص. قد يكون هذا السكريبت مكتبة JavaScript أخرى، لذا فإن كل سكريبت لا يعلم بتواجد الآخر بتاتًا، ثم يمكن لهذا السكريبت إنشاء رمزه الخاص <code>Symbol("id")‎</code> هكذا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_21" style="">
<span class="com">// ...</span><span class="pln">
let id </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">

user</span><span class="pun">[</span><span class="pln">id</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Their id value"</span><span class="pun">;</span></pre>

<p>
	بهذه الطريقة، لن يوجد أي تعارض بين المُعاملات التي انشأناها ومُعاملات السكريبت الآخر لأن الرموز تختلف دومًا حتى إن كان لديها الاسم ذاته. لكن إن استخدمنا النص <code>"id"</code> بدلًا من الرمز للغرض ذاته، فَسيوجد تعارض:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_23" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

</span><span class="com">// "id" يستخدم السكربت الذي أنشأناه الخاصية </span><span class="pln">
user</span><span class="pun">.</span><span class="pln">id </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Our id value"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// لغرض آخر "id" يريد سكريبت آخر استخدام الخاصية</span><span class="pln">

user</span><span class="pun">.</span><span class="pln">id </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Their id value"</span><span class="pln">
</span><span class="com">// !تعارض! تم تغيير المحتوى من قِبل السكريبت الآخر</span></pre>

<h3>
	الرموز في التعريف المختصر لكائن
</h3>

<p>
	إن أردنا استخدام الرموز عند تعريف كائن بالطريقة المختصرة عبر الأقواس <code>{...}</code> فَسنحتاج إلى تغليفها بأقواس مربعة هكذا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_25" style="">
<span class="pln">let id </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">

let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln">
  </span><span class="pun">[</span><span class="pln">id</span><span class="pun">]:</span><span class="pln"> </span><span class="lit">123</span><span class="pln"> </span><span class="com">// "id: 123" ليس </span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	ذلك لأننا نريد القيمة من المتغير <code>id</code> كمفتاح وليس النص "id".
</p>

<h2>
	تتخطى for…in الرموز
</h2>

<p>
	لا تشارك الخصائص الرمزية في الحلقة <code>for..in</code>. مثلًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_27" style="">
<span class="pln">let id </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">
let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln">
  age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">30</span><span class="pun">,</span><span class="pln">
  </span><span class="pun">[</span><span class="pln">id</span><span class="pun">]:</span><span class="pln"> </span><span class="lit">123</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let key in user</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln">key</span><span class="pun">);</span><span class="pln"> </span><span class="com">// name, age (لا يوجد  رموز)</span><span class="pln">

</span><span class="com">// يعمل الوصول المباشر للرمز </span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"Direct: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> user</span><span class="pun">[</span><span class="pln">id</span><span class="pun">]</span><span class="pln"> </span><span class="pun">);</span></pre>

<p>
	يتجاهل <code>Object.keys(user)‎</code> الرموز أيضًا. يُعد هذا من جزءًا من مبدأ "إخفاء الخاصيات الرمزية". إن حاول سكريبت آخر أو مكتبة JavaScript الدخول إلى كائن والتنقل فيه، فلن يصل إلى الخاصيات الرمزية بتاتًا.
</p>

<p>
	في المقابل، تنسخ <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign" rel="external nofollow">Object.assign</a> كلًا من النصوص والخاصيات الرمزية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_29" style="">
<span class="pln">let id </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">
let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">[</span><span class="pln">id</span><span class="pun">]:</span><span class="pln"> </span><span class="lit">123</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

let clone </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">.</span><span class="pln">assign</span><span class="pun">({},</span><span class="pln"> user</span><span class="pun">);</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> clone</span><span class="pun">[</span><span class="pln">id</span><span class="pun">]</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 123</span></pre>

<p>
	لا يوجد لَبسٌ هنا، فهذا الأمر ضمن التصميم. الفكرة هي أنه عند استنساخ كائن أو دمج كائنين، فإننا نريد أن تُنسَخ جميع الخصائص (بما فيها الرموز مثل <code>id</code>).
</p>

<p>
	<strong>تُحوَّل مفاتيح الخاصيات التي من نوع آخر غير الرمز إلى نصوص جبريًا</strong>
</p>

<p>
	يمكننا استخدام النصوص أو الرموز فقط كمفاتيح في الكائنات، ويُحوَّل أي نوع آخر إلى نص. مثلًا، الرقم <code>0</code> يصبح النص <code>"0"</code> عندما يستخدم كمفتاح لخاصية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_31" style="">
<span class="pln">let obj </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="lit">0</span><span class="pun">:</span><span class="pln"> </span><span class="str">"test"</span><span class="pln"> </span><span class="com">// "0": "test" مثل</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">// "إلى الخاصية ذاتها أي يحوَّل الرقم 0 إلى نص "0 alert تصل الدالة</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> obj</span><span class="pun">[</span><span class="str">"0"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// اختبار</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> obj</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// (اختبار (الخاصية ذاتها</span></pre>

<h2>
	الرموز العامة
</h2>

<p>
	جميع الرموز تكون مختلفة دائمًا كما رأينا، حتى إن كانت تحمل الأسماء ذاتها. لكن قد نريد أحيانا أن تكون الرموز التي تحمل الاسم ذاته هي نفس الكائنات. مثلًا، تحتاج أجزاء متعددة في التطبيق الوصول إلى الرمز <code>"id"</code> ما يعني الخاصيات ذاتها.
</p>

<p>
	لنتمكن من القيام بذلك، يوجد <em>سجل للرموز العامة</em>. يمكننا إنشاء رموز فيه والوصول إليها لاحقًا، كما يضمن أن الوصول المتكرر إلى الاسم ذاته يُرجِع الرمز ذاته في كل مرة.
</p>

<p>
	لقراءة، أو إنشاء رمز في حال عدم تواجده في السجل، نستخدم <code>Symbol.for(key)‎</code>. يفحص هذا الاستدعاء السجل العام للرموز، إن كان هناك رمزًا بالوصف <code>key</code>، فإنه يُرجِعه، وإن لم يجده فإنه يُنشئ رمزًا جديدًا بالاستدعاء <code>Symbol(key)‎</code> ويُخزِّنه في السجل بالوصف المُعطى <code>key</code>. إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_33" style="">
<span class="com">// يقرأ من السجل العام</span><span class="pln">
let id </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">.</span><span class="kwd">for</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// إن لم يجد الرمز، ينشئه</span><span class="pln">

</span><span class="com">// يُقرأ مجددًا، ربما من جزء آخر في الشيفرة</span><span class="pln">
let idAgain </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">.</span><span class="kwd">for</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// الرمز ذاته</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> id </span><span class="pun">===</span><span class="pln"> idAgain </span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span></pre>

<p>
	تُدعى الرموز داخل السجل العام رموزًا عامة، ونستعلمها في حال أردنا رمزًا على مستوى تطبيق كامل، وقابلًا للوصول في الشيفرة.
</p>

<p>
	<strong>هذا الأمر مشابه لما في لغة Ruby</strong>
</p>

<p>
	يوجد في بعض اللغات البرمجية مثل Ruby رمزًا واحدًا لكل اسم. كما رأينا، في JavaScript الأمر ذاته صحيح بالنسبة للرموز العامة.
</p>

<h3>
	Symbol.keyFor
</h3>

<p>
	بالنسبة للرموز العامة، ليس فقط الدالة <code>Symbol.for(key)‎</code> تُرجِع الرمز وفقًا لاسمه، بل يوجد استدعاء عكسي: <code>Symbol.keyFor(sym)‎</code>، والتي تعكس ما تقوم به الأخرى: تُرجِع اسمًا بواسطة رمز عام. مثلًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_35" style="">
<span class="com">// نَسترجع الرمز بالاسم</span><span class="pln">
let sym </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">.</span><span class="kwd">for</span><span class="pun">(</span><span class="str">"name"</span><span class="pun">);</span><span class="pln">
let sym2 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">.</span><span class="kwd">for</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// نسترجع الاسم بالرمز</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">.</span><span class="pln">keyFor</span><span class="pun">(</span><span class="pln">sym</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// name</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">.</span><span class="pln">keyFor</span><span class="pun">(</span><span class="pln">sym2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// id</span></pre>

<p>
	تستخدم <code>Symbol.keyFor</code> سجل الرموز العام داخليًا للبحث عن مفتاح الرمز. لذا فإنها لا تعمل مع الرموز الغير عامة. إن كان الرمز غير عام، فلن يتمكن من العثور عليه وسيُرجِع <code>undefined</code>.
</p>

<p>
	يمكن القول أن أي رمز لدية الخاصية <code>description</code>.
</p>

<p>
	مثلا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9790_37" style="">
<span class="pln">let globalSymbol </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">.</span><span class="kwd">for</span><span class="pun">(</span><span class="str">"name"</span><span class="pun">);</span><span class="pln">
let localSymbol </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">(</span><span class="str">"name"</span><span class="pun">);</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">.</span><span class="pln">keyFor</span><span class="pun">(</span><span class="pln">globalSymbol</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// name, رمز عام</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pun">.</span><span class="pln">keyFor</span><span class="pun">(</span><span class="pln">localSymbol</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// undefined, غير عام</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> localSymbol</span><span class="pun">.</span><span class="pln">description </span><span class="pun">);</span><span class="pln"> </span><span class="com">// name</span></pre>

<h2>
	رموز النظام
</h2>

<p>
	يوجد العديد من رموز "النظام" التي تستخدمها JavaScript داخليًا، ويمكن استخدامها لضبط نواحي متعددة من الكائنات بدقة. هذه الرموز مُدرَجة في وصف جدول <a href="https://tc39.github.io/ecma262/#sec-well-known-symbols" rel="external nofollow">الرموز المتعارف عليها</a>:
</p>

<ul>
<li>
		<code>Symbol.hasInstance</code>
	</li>
	<li>
		<code>Symbol.isConcatSpreadable</code>
	</li>
	<li>
		<code>Symbol.iterator</code>
	</li>
	<li>
		<code>Symbol.toPrimitive</code>
	</li>
	<li>
		وهكذا…
	</li>
</ul>
<p>
	مثلًا، يتيح لنا الرمز <code>Symbol.toPrimitive</code> وصف كائن إلى تحويل أولي. سنرى استخدامها قريبًا. ستعتاد على باقي الرموز عند دراسة ميزات اللغة المُقابلة.
</p>

<h2>
	الخلاصة
</h2>

<p>
	النوع <code>Symbol</code> هو نوع أولي للمُعاملات الفريدة. يتم إنشاء الرموز عبر استدعاء الدالة <code>Symbol()‎</code> مع وصف اختياري (اسم).
</p>

<p>
	الرموز تكون دائمًا مختلفة القيم حتى إن كان لها الاسم ذاته، أي تتصف بأنها فريدة. إن أردنا أن يكون الرمز بالاسم ذاته يجمل القيمة ذاتها، يجب أن نستخدم السجل العام: تُرجِع <code>Symbol.for(key)‎</code> (وتُنشِئ في حال الحاجة) رمزًا عامًا بالمفتاح كاسم. تُرجِع الاستدعاءات العديدة لِلدالة <code>Symbol.for</code> باستخدام المفتاح ذاته الرمز نفسه.
</p>

<p>
	لدى الرموز حالتي استخدام:
</p>

<ol>
<li>
		خاصيات الكائن "الخفية". إن أردنا إضافة خاصية إلى كائن ينتمي إلى سكريبت أو مكتبة أخرى، يمكننا إنشاء رمز واستخدامه كمفتاح خاصية. لا تظهر الخاصية الرمزية في <code>for..in</code>، حتى لا تتم معالجته عن طريق الخطأ مع باقي الخاصيات. لن يتم الوصول إليه مباشرةً أيضًا لأن السكريبت الخارجي لا يحوي على هذا الرمز. هكذا تكون الخاصية محمية من الاستخدام الخارجي. لذا، يمكننا إخفاء شيء ما بشكل تام في الكائنات التي نحتاجها، والتي لا يجب أن يراها الآخرون باستخدام الخاصيات الرمزية.
	</li>
	<li>
		يوجد العديد من رموز النظام المستخدمة بواسطة JavaScript التي يمكن الوصول إليها بواسطة <code>Symbol.*‎</code>. يمكننا استخدامها لتعديل سلوك مُدمَج، مثلا، سنستخدم <code>Symbol.iterato</code> لاحقَا في الشرح للحلقات، و <code>Symbol.toPrimitive</code> لإعداد التحويل من كائن لقيمة أولية وهكذا…
	</li>
</ol>
<p>
	عمليًا، الرموز ليست خفية 100%. يوجد دالة مدمجة <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertySymbols" rel="external nofollow">Object.getOwnPropertySymbols(obj)</a><code>‎</code> تتيح لنا الوصول إلى جميع الرموز. كما يوجد دالة تُدعى <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/ownKeys" rel="external nofollow">Reflect.ownKeys(obj)</a><code>‎</code> والتي تُرجِع جميع مفاتيح الكائن بما فيها الرموز. لذا فإن الرموز ليست مخفية فعلًا، لكن أغلب المكاتب، والدوال المدمجة والهياكل لا تستخدم هذه الدوال.
</p>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/symbol" rel="external nofollow">Symbol type</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-%D9%88%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84%D9%87%D8%A7-this-r799/" rel="">الدوال في الكائنات واستعمالها this</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D9%83%D9%86%D8%B3-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%87%D9%85%D9%84%D8%A9-r797/" rel="">كنس البيانات المهملة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">798</guid><pubDate>Thu, 13 Feb 2020 13:02:00 +0000</pubDate></item><item><title>&#x643;&#x646;&#x633; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x627;&#x644;&#x645;&#x647;&#x645;&#x644;&#x629; &#x641;&#x64A; &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A;</title><link>https://academy.hsoub.com/programming/javascript/%D9%83%D9%86%D8%B3-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%87%D9%85%D9%84%D8%A9-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r797/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/27.jpg.dccc620e6739c6bf7709c3076e8a2269.jpg" /></p>

<p>
	تُدَار الذاكرة في JavaScript تلقائيًا في الخفاء. نحن ننشئ المتغيرات الأولية، والكائنات، والدوال وجميعها تأخذ مكانًا في الذاكرة ولكن هل سألت نفسك ماذا يحدث عندما يصبح أحد هذه الأشياء مهملًا وغير مهم؟ كيف يكتشف ذلك مُحرِّك JavaScript ويتخلص منه؟ هذا ما سنعرفه في هذا الفصل.
</p>

<h2>
	قابلية الوصول
</h2>

<p>
	المبدأ الرئيسي لإدارة الذاكرة في JavaScript هو قابلية الوصول (reachability). ببساطة، القيم "القابلة للوصول" هي القيم التي يمكن الوصول إليها واستخدامها بطريقة ما وهذه القيم مخولة لتُخزَّن في الذاكرة.
</p>

<p>
	1- يوجد مجموعة من القيم القابلة للوصول بطبيعة الحال والتي لا يمكن التخلص منها لأسباب وجيهة مثل:
</p>

<ul>
<li>
		المتغيرات المحلية والمُعاملات للدالة الحاليِّة.
	</li>
	<li>
		المتغيرات والمُعاملات لدوال أخرى ضمن السلسلة الحالية في الاستدعاء المُتداخل.
	</li>
	<li>
		المتغيرات العامة.
	</li>
	<li>
		(بالإضافة إلى بعض المتغيرات الأخرى الداخلية)
	</li>
</ul>
<p>
	تُدعى هذه القيم «جذورًا» (roots).
</p>

<p>
	2- تكون أي قيمة أخرى قابلة للوصول إن كان بالإمكان الوصول إليها من جذر باستخدام مرجع أو سلسلة من المراجع. مثلًا، إن كان هناك كائن في متغير محلي، ولدى هذا الكائن خاصية تشير لكائن آخر، فإنَّ هذا الكائن قابل للوصول. وهذه الكائنات التي يُشار إليها قابلة للوصول أيضًا. ستجد أمثلة توضيحية لاحقًا.
</p>

<p>
	يوجد عملية خلفيَّة في محرك JavaScript تُدعَى «كانس المهملات» (<a href="https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)" rel="external nofollow">garbage collector</a>) تعمل على مراقبة الكائنات وحذف التي لم تَعُد قابلة للوصول.
</p>

<h2>
	مثال بسيط
</h2>

<p>
	أبسط مثال هو:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_95_9" style="">
<span class="com">// user يرجِع لكائن</span><span class="pln">
let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	 
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33543" href="https://academy.hsoub.com/uploads/monthly_2020_01/1.png.30f17b271a9d853c615e27206b2a6045.png" rel=""><img alt="1.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33543" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/1.png.30f17b271a9d853c615e27206b2a6045.png"></a>
</p>

<p>
	يُصوِّر السهم في الصورة مرجعًا لكائن. المتغير العام <code>"user"</code> يشير للكائن <code>{name: "John"‎}</code> (سنُسميه John اختصارًا). الخاصية <code>"name"</code> للكائن John تُخزن قيمة أولية، لذ رُسمَت بداخل الكائن. إن استُبدلَت قيمة المتغير <code>user</code>، فَسَنفقد المرجع الذي يشير إلى الكائن John:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_95_11" style="">
<span class="pln">user </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span></pre>

<p>
	 
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33544" href="https://academy.hsoub.com/uploads/monthly_2020_01/2.png.d023d6f627ee7c50ca1ef2395be5c326.png" rel=""><img alt="2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33544" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/2.png.d023d6f627ee7c50ca1ef2395be5c326.png"></a>
</p>

<p>
	أصبح الكائن John غير قابل للوصول الآن أي لا يوجد طريقة للوصول إليه. سيعمل كانس المهملات على حذف البيانات المتمثلة في الكائن John وتحرير الذاكرة التي يحتلها.
</p>

<h2>
	مرجعَان لكائن
</h2>

<p>
	لنفترض أننا نسخنا المرجع من المتغير <code>user</code> إلى متغير آخر باسم <code>admin</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_95_13" style="">
<span class="com">// user يرجِع لكائن</span><span class="pln">
let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

let admin </span><span class="pun">=</span><span class="pln"> user</span><span class="pun">;</span></pre>

<p>
	 
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33545" href="https://academy.hsoub.com/uploads/monthly_2020_01/3.png.6743fb549c9dad2ce051bf2a333a32ec.png" rel=""><img alt="3.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33545" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/3.png.6743fb549c9dad2ce051bf2a333a32ec.png"></a>
</p>

<p>
	إن قمنا بالأمر السابق ذاته الآن:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_95_15" style="">
<span class="pln">user </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span></pre>

<p>
	فسيكون الكائن قابلًا للوصول من خلال المتغير العام <code>admin</code>، لذا يبقى في الذاكرة. إن استبدلنا محتوى المتغير <code>admin</code> أيضًا فسيُحذَف الكائن.
</p>

<h2>
	الكائنات المتداخلة
</h2>

<p>
	الآن ننتقل لمثال أكثر تعقيدًا. ألق نظرة على الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_95_17" style="">
<span class="kwd">function</span><span class="pln"> marry</span><span class="pun">(</span><span class="pln">man</span><span class="pun">,</span><span class="pln"> woman</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  woman</span><span class="pun">.</span><span class="pln">husband </span><span class="pun">=</span><span class="pln"> man</span><span class="pun">;</span><span class="pln">
  man</span><span class="pun">.</span><span class="pln">wife </span><span class="pun">=</span><span class="pln"> woman</span><span class="pun">;</span><span class="pln">

  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    father</span><span class="pun">:</span><span class="pln"> man</span><span class="pun">,</span><span class="pln">
    mother</span><span class="pun">:</span><span class="pln"> woman
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

let family </span><span class="pun">=</span><span class="pln"> marry</span><span class="pun">({</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln">
</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Ann"</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	تربط الدالة <code>marry</code> كائنين بجعل كلاهما يشير إلى الآخر ثم ترجِع كائنًا جديدًا يحوي كلاهما. هيكل الذاكرة الناتج يكون كالتالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33546" href="https://academy.hsoub.com/uploads/monthly_2020_01/4.png.05a82c253b746d1a36cd346fca876d25.png" rel=""><img alt="4.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33546" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/4.png.05a82c253b746d1a36cd346fca876d25.png"></a>
</p>

<p>
	تكون جميع البيانات قابلة للوصول حتى الآن. دعنا نجرب حذف مرجعين الآن:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_95_19" style="">
<span class="kwd">delete</span><span class="pln"> family</span><span class="pun">.</span><span class="pln">father</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">delete</span><span class="pln"> family</span><span class="pun">.</span><span class="pln">mother</span><span class="pun">.</span><span class="pln">husband</span><span class="pun">;</span></pre>

<p>
	 
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33547" href="https://academy.hsoub.com/uploads/monthly_2020_01/5.png.983de9c60deb1f042d54f8e364bcc6af.png" rel=""><img alt="5.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33547" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/5.png.983de9c60deb1f042d54f8e364bcc6af.png"></a>
</p>

<p>
	ليس من الكافِ حذف أحد المرجِعين فقط، لأنَّ جميع الكائنات ستظل قابلة للوصول لكن إن حذفنا كلا المرجعين، فسنرى عدم وجود أي مرجع إلى الكائن John:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33548" href="https://academy.hsoub.com/uploads/monthly_2020_01/6.png.cc532f7ab3d6660115df3024bcba77a7.png" rel=""><img alt="6.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33548" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/6.png.cc532f7ab3d6660115df3024bcba77a7.png"></a>
</p>

<p>
	لا يهم وجود مرجع من الكائن، إذ ما يجعله قابلًا للوصول هو المراجع التي تشير إليه، لذا فإنَّ الكائن John أصبح غير قابل للوصول وسيُحذَف من الذاكرة مع جميع بياناته التي أصبحت غير قابلة للوصول أيضًا.
</p>

<p>
	بعد تجميع البيانات الغير مرغوب بها، يبقى لدينا:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33549" href="https://academy.hsoub.com/uploads/monthly_2020_01/7.png.be0d093422d9717fb91f37ef3bc1d514.png" rel=""><img alt="7.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33549" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/7.png.be0d093422d9717fb91f37ef3bc1d514.png"></a>
</p>

<h2>
	جزيرة غير قابلة للوصول
</h2>

<p>
	يمكن أن تصبح جزيرة من الكائنات المترابطة غير قابلة للوصول وتُحذَف من الذاكرة. الكائن الرئيسي هو الكائن أعلاه ذاته:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_95_21" style="">
<span class="pln">family </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span></pre>

<p>
	تُصبح الصورة في الذاكرة كما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33550" href="https://academy.hsoub.com/uploads/monthly_2020_01/8.png.1cc52b37795b002e8f2b2ff0b6dde2ed.png" rel=""><img alt="8.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33550" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/8.png.1cc52b37795b002e8f2b2ff0b6dde2ed.png"></a>
</p>

<p>
	يوضح هذا المثال أهمية مبدأ قابلية الوصول. من الواضح أن الكائنين John و Ann ما زالا مرتبطين ولكل منهما مراجع لبعضهما، لكن ذلك غير كافٍ.
</p>

<p>
	الكائن السابق <code>"family"</code> أصبح غير مربوط بالجذر، أي لم يعد هناك أي مرجع إليه لذا فإن الجزيرة كاملةً تصبح غير قابلة للوصول وتُحذَف.
</p>

<h2>
	الخوارزميات الداخلية
</h2>

<p>
	تُدعى الخوارزمية الأساسية لتجميع البيانات المهملة «الاستهداف والتمشيط» (mark-and-sweep)؛ تُنفَّذ خطوات جمع البيانات المهملة دوريًا وفق الخطوات التالية:
</p>

<ul>
<li>
		يأخذ كانس المهملات الجذور ويحفظها (يُحدِّدها هدفًا له).
	</li>
	<li>
		ثم يُمشِّط جميع الإشارات الخارجة منها (مراجع لكائنات أخرى) ويحفظها لاستهدافها أيضًا.
	</li>
	<li>
		ثم يُمشِّط جميع الكائنات التي استهدفها مسبقًا ويحفظ مراجعها لاستهدفها لاحقًا. يُمشِّط جميع الكائنات بتلك الطريقة ويتذكرها لكي لا يُمشِّط أي كائن مرةً ثانية مستقبلًا.
	</li>
	<li>
		تستمر العملية مرارًا وتكرارًا حتى يصبح هناك مراجع لم تُمشَّط (غير قابلة للوصول من أي جذر).
	</li>
	<li>
		تُحذَف جميع الكائنات باستثناء تلك استُهدفَت وعُلِّمَت بأنَّها غير مهملة.
	</li>
</ul>
<p>
	مثلًا، ليكن هيكل الكائنات لدينا كما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33551" href="https://academy.hsoub.com/uploads/monthly_2020_01/9.png.7bc2bc3c39c4b6417e5c66b29ad6c6c1.png" rel=""><img alt="9.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33551" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/9.png.7bc2bc3c39c4b6417e5c66b29ad6c6c1.png"></a>
</p>

<p>
	يمكن رؤية جزيرة غير قابلة للوصول في اليمين. الآن لنرى كيف يتعامل معها كانس المهملات وفق خوارزمية الاستهداف والتمشيط.
</p>

<p>
	الخطوة الأولى هي تحديد الجذور:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33552" href="https://academy.hsoub.com/uploads/monthly_2020_01/10.png.bcf17cb130c65e799dd23cb8af8469ea.png" rel=""><img alt="10.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33552" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/10.png.bcf17cb130c65e799dd23cb8af8469ea.png"></a>
</p>

<p>
	ثم تُحدَّد المراجع التي تشير إليها:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33553" href="https://academy.hsoub.com/uploads/monthly_2020_01/11.png.49c24404c5f2de4e487646a56503a489.png" rel=""><img alt="11.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33553" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/11.png.49c24404c5f2de4e487646a56503a489.png"></a>
</p>

<p>
	تُحدَّد المراجع التي تشير لها هذه الكائنات أيضًا:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33554" href="https://academy.hsoub.com/uploads/monthly_2020_01/12.png.713a8da10104d357b13b1efe302a4751.png" rel=""><img alt="12.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33554" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/12.png.713a8da10104d357b13b1efe302a4751.png"></a>
</p>

<p>
	تُعدُّ الكائنات التي لم تُمشَّط أثناء العملية غير قابلة للوصول ويجري حذفها:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33555" href="https://academy.hsoub.com/uploads/monthly_2020_01/13.png.b13b976e0dc7631d6f56641c96b574f4.png" rel=""><img alt="13.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33555" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/13.png.b13b976e0dc7631d6f56641c96b574f4.png"></a>
</p>

<p>
	هذه الآلية التي يعمل بها كانس المهملات.
</p>

<p>
	تطبق محركات JavaScript العديد من التحسينات لتحسين هذه الخوارزمية وتسريع عملها بطريقة لا تؤثر على سرعة التنفيذ.
</p>

<p>
	بعض التحسينات:
</p>

<ul>
<li>
		<strong>التجميع وفق الجيل</strong>: تُقَسَّم الكائنات إلى مجموعتين: "كائنات جديدة" و "كائنات قديمة". تُنشَأ العديد من الكائنات ثمَّ تؤدي عملها ثمَّ تموت بسرعة، ويمكن تنظيفها بقوة. وتلك التي تنجو تصبح قديمة وتُفحَص بوتيرة أقل.
	</li>
	<li>
		<strong>التجميع التدريجي</strong>: إن وُجِد العديد من الكائنات وأردنا المرور خلال جميع الكائنات وتحديدها دفعة واحدة، فقد يأخذ ذلك وقتًا ويظهِِر آنذاك تأخيرٌ ملحوظٌ في التنفيذ، لذا يحاول المُحرِّك تقسيم عملية كنس البيانات المهملة إلى أجزاء ثم تنفيذ الأجزاء واحدًا تلو الآخر بشكل منفصل. قد يتطلب ذلك إجراء حسابات إضافية لتتبع التغييرات، لكن يصبح لدينا الكثير من التأخيرات الغير ملحوظة بدلًا من تأخير واحد كبير.
	</li>
	<li>
		<strong>التجميع وقت الخمول</strong>: يحاول كانس المهملات العمل عندما يكون المعالج غير مشغول لتقليل أي تأثيرات محتملة على التنفيذ.
	</li>
</ul>
<p>
	يوجد تحسينات وإضافات أخرى على خوارزمية كنس المهملات لكن يجب على التوقف هنا لأنَّ المحركات المختلفة تُطبِّق تقنيات مختلفة. والأهم من ذلك، تتغير الأمور بتطور المحركات، لذا فإنَّ التعمق مسبقًا دون الحاجة لذلك لا يستحق العناء. إلا إن كان ذلك رغبة شخصية، فَسنضع بعض الروابط في الأسفل.
</p>

<h2>
	الخلاصة
</h2>

<p>
	الأشياء التي يجب معرفتها:
</p>

<ul>
<li>
		تُكنس البيانات المهملة تلقائيًا، وهو أمر لا يمكن فرضه أو تجنبه.
	</li>
	<li>
		تبقى الكائنات في الذاكرة طالما يمكن الوصول إليها من أي جذر.
	</li>
	<li>
		وجود مرجِع للكائن ليس مثل أن يكون قابلًا للوصول من جذر، ويمكن لمجموعة من الكائنات المترابطة أن تصبح غير قابلة للوصول.
	</li>
</ul>
<p>
	تستخدم المحركات الحديثة خوارزميات متطورة لكنس البيانات المهملة.
</p>

<p>
	يغطي كتاب "The Garbage Collection Handbook: The Art of Automatic Memory Management" (لمؤلفه R. Jones وغيره) بعضًا منها.
</p>

<p>
	إن كنت معتادًا على البرمجة بلغات ذات مستوى منخفض، يوجد معلومات مفصَّلة عن كانس المهملات في المُحرِّك V8 في المقال <a href="http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection" rel="external nofollow">رحلة إلى V8: كنس البيانات المهملة</a>.
</p>

<p>
	تنشر <a href="https://v8.dev/" rel="external nofollow">مدونة V8</a> أيضًا مقالات عن التغييرات في إدارة الذاكرة من وقت لآخر. لتتعلم عن كنس البيانات المهملة، يجب أن تتجهز بتعلم أمور V8 الداخلية كما يُفضَّل أن تقرأ مدونة <a href="http://mrale.ph/" rel="external nofollow">Vyacheslav Egorov</a> الذي عمل كأحد مهندسي V8. أنا أقول V8 لوجود الكثير من المقالات عنه على الإنترنت. العديد من الجوانب متشابهة بالنسبة لباقي المحركات، لكن يختلف كنس البيانات المهملة من عدة نواحي بينها.
</p>

<p>
	المعرفة العميقة بالمحركات جيدة عندما تحتاج إلى إجراء تحسين منخفض المستوى. فكِّر في ذلك وليكن خطوتك التالية بعد أن تعتاد على اللغة.
</p>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/garbage-collection" rel="external nofollow">Garbage collection</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>.
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%86%D9%88%D8%B9-%D8%A7%D9%84%D8%B1%D9%85%D8%B2%D9%8A-symbol-r798/" rel="">النوع الرمزي (Symbol)</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-r796/" rel="">الكائنات</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">797</guid><pubDate>Tue, 11 Feb 2020 18:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x643;&#x627;&#x626;&#x646;&#x627;&#x62A; &#x641;&#x64A; &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A;</title><link>https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r796/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/26.jpg.023d6806026ac75c78203a53bb7acda1.jpg" /></p>

<p>
	يوجد سبعة أنواع للبيانات في JavaScript كما رأينا في فصل <a href="https://academy.hsoub.com/programming/javascript/%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-r672/" rel="">أنواع البيانات</a>. ستة من هذه الأنواع تُدعى "أساسية" (primitive) لأنها تحوي قيمة شيء واحد فقط (سواء كان نصًا أو رقمًا أو أي شيء آخر).
</p>

<p>
	في المُقابل، تُستخدم الكائنات لتخزين مجموعة من البيانات المتنوعة والوحدات المعقدة المُرَمَّزة بمفاتيح. تُضمَّن الكائنات في ما يقارب جميع نواحي JavaScript، لذا يجب علينا أن نفهمها قبل التعمق في أي شيء آخر.
</p>

<p>
	يمكن إنشاء أي كائن باستخدام الأقواس المعقوصة <code>{…}</code> مع قائمة اختيارية بالخاصيات. الخاصية هي زوج من "مفتاح: قيمة" (<code>key: value</code>) إذ يكون المفتاح عبارة عن نص (يُدعى "اسم الخاصية")، والقيمة يمكن أن تكون أي شيء.
</p>

<p>
	يمكننا تخيل الكائن كخزانة تحوي ملفات. يُخزن كل جزء من هذه البيانات في الملف الخاص به باستخدام المفتاح. يمكن إيجاد، أو إضافة، أو حذف ملف باستخدام اسمه.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33534" href="https://academy.hsoub.com/uploads/monthly_2020_01/1.png.14a65bbf833dc492e74151db0f1aa150.png" rel=""><img alt="1.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33534" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/1.png.14a65bbf833dc492e74151db0f1aa150.png"></a>
</p>

<p>
	يمكن إنشاء كائن فارغ (خزانة فارغة) باستخدام إحدى الصيغتين التاليتين:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_6" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">();</span><span class="pln"> </span><span class="com">// (object constructor) صياغة باني كائن</span><span class="pln">
let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">  </span><span class="com">// (object literal) صياغة مختصرة لكائن عبر الأقواس</span></pre>

<p>
	 
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33535" href="https://academy.hsoub.com/uploads/monthly_2020_01/2.png.ffb520338c8621815ebb26aa95243595.png" rel=""><img alt="2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33535" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/2.png.ffb520338c8621815ebb26aa95243595.png"></a>
</p>

<p>
	تُستخدم الأقواس المعقوصة <code>{...}</code> عادة، وهذا النوع من التصريح يُسمى «<em>الصياغة المختصرة لتعريف كائن</em>» (<em>object literal</em>).
</p>

<h2>
	القيم المُجرَّدة والخاصيات
</h2>

<p>
	يمكننا إضافة بعض الخاصيات (properties) إلى الكائن المعرَّف بالأقواس <code>{...}</code> مباشرة بشكل أزواج "مفتاح: قيمة":
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_8" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">     </span><span class="com">// كائن</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln">  </span><span class="com">// name عبر المفتاح John خزِّن القيمة </span><span class="pln">
  age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">30</span><span class="pln">        </span><span class="com">// age خزِّن القيمة 30 عبر المفتاح </span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لدى كل خاصية مفتاح (يُدعى أيضًا "اسم " أو "مُعَرِّف") قبل النقطتين <code>":"</code> وقيمة لهذه الخاصية بعد النقطتين.
</p>

<p>
	يوجد خاصيتين في الكائن <code>user</code>:
</p>

<ol>
<li>
		اسم الخاصية الأولى هو <code>"name"</code> وقيمتها هي <code>"John"</code>.
	</li>
	<li>
		اسم الخاصية الثانية هو <code>"age"</code> وقيمتها هي <code>"30"</code>.
	</li>
</ol>
<p>
	يمكن تخيل الكائن السابق <code>user</code> كخزانة بملفين مُسَمَّيان "name" و "age".
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33536" href="https://academy.hsoub.com/uploads/monthly_2020_01/3.png.d0a4bdcab9be0bfb341e3a51176db401.png" rel=""><img alt="3.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33536" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/3.png.d0a4bdcab9be0bfb341e3a51176db401.png"></a>
</p>

<p>
	يمكننا إضافة، وحذف، وقراءة الملفات من الخزانة في أي وقت. يمكن الوصول إلى قيم الخاصيات باستخدام الصيغة النُقَطية (dot notation):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_10" style="">
<span class="com">// الحصول على قيم خاصيات الكائن:</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> user</span><span class="pun">.</span><span class="pln">name </span><span class="pun">);</span><span class="pln"> </span><span class="com">// John</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> user</span><span class="pun">.</span><span class="pln">age </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 30</span></pre>

<p>
	يمكن للقيمة أن تكون من أي نوع، لِنُضِف قيمة من نوع بيانات منطقية (boolean):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_12" style="">
<span class="pln">user</span><span class="pun">.</span><span class="pln">isAdmin </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span></pre>

<p>
	 
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33537" href="https://academy.hsoub.com/uploads/monthly_2020_01/4.png.f1b4c2f1bdc7831cbd791723b42b925a.png" rel=""><img alt="4.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33537" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/4.png.f1b4c2f1bdc7831cbd791723b42b925a.png"></a>
</p>

<p>
	يمكننا استخدام المُعامِل <code>delete</code> لحذف خاصية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_14" style="">
<span class="kwd">delete</span><span class="pln"> user</span><span class="pun">.</span><span class="pln">age</span><span class="pun">;</span></pre>

<p>
	 
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33538" href="https://academy.hsoub.com/uploads/monthly_2020_01/5.png.8a345fcd005ccc06b4d4a2f8eed4baca.png" rel=""><img alt="5.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33538" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/5.png.8a345fcd005ccc06b4d4a2f8eed4baca.png"></a>
</p>

<p>
	يمكننا أيضا استخدام خاصيات بأسماء تحوي أكثر من كلمة، لكن يجب وضعها بين علامات الاقتباس "":
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_16" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln">
  age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">30</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"likes birds"</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">  </span><span class="com">// يجب أن تكون الخاصية ذات الاسم المُحتوي على أكثر من كلمة بين علامتي اقتباس</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	 
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33539" href="https://academy.hsoub.com/uploads/monthly_2020_01/6.png.c8f85aeb831058286413252cd238ded9.png" rel=""><img alt="6.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33539" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/6.png.c8f85aeb831058286413252cd238ded9.png"></a>
</p>

<p>
	يمكن إضافة فاصلة بعد آخر خاصية في القائمة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_18" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln">
  age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">30</span><span class="pun">,</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	وتُسمى بفاصلة "مُعَلِّقَة" أو "زائدة" فهي تجعل إضافة أو حذف أو التنقل بين الخاصيات أسهل لأن جميع الأسطر تُصبِح متشابهة.
</p>

<h2>
	الأقواس المعقوفة
</h2>

<p>
	لا تعمل طريقة الوصول إلى الخاصيات ذات الأسماء المحتوية على أكثر من كلمة باستخدام الصيغة النُقَطية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_20" style="">
<span class="com">// تعرض هذه التعليمة وجود خطأ في الصياغة</span><span class="pln">
user</span><span class="pun">.</span><span class="pln">likes birds </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span></pre>

<p>
	ذلك لأن الصيغة النُقطية تحتاج لاسم متغير صحيح. لا يحوي مسافات أو حدود أخرى. يوجد بديل يعمل مع أي نص "صيغة الأقواس المعقوفة" <code>[]</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_22" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">

</span><span class="com">// تخزين</span><span class="pln">
user</span><span class="pun">[</span><span class="str">"likes birds"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">

</span><span class="com">// استرجاع</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">user</span><span class="pun">[</span><span class="str">"likes birds"</span><span class="pun">]);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">

</span><span class="com">// حذف</span><span class="pln">
</span><span class="kwd">delete</span><span class="pln"> user</span><span class="pun">[</span><span class="str">"likes birds"</span><span class="pun">];</span></pre>

<p>
	يعمل كل شيء وفق المطلوب الآن. يُرجى ملاحظة أنَّ النص بداخل الأقواس مُحاط بعلامتي اقتباس (تعمل علامات التنصيص الأخرى بطريقة صحيحة أيضًا).
</p>

<p>
	تتيح لنا الأقواس المعقوفة أيضًا جلب اسم خاصية ناتجة عن قيمة أي تعبير - بدلًا من اسم الخاصية الفعلي - مثل استعمال اسم من متغير كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_24" style="">
<span class="pln">let key </span><span class="pun">=</span><span class="pln"> </span><span class="str">"likes birds"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// user["likes birds"] = true; يماثل قول </span><span class="pln">
user</span><span class="pun">[</span><span class="pln">key</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span></pre>

<p>
	يمكن حساب قيمة المتغير <code>key</code> أثناء التنفيذ أو قد تعتمد قيمته على مدخلات المستخدمين ثم نستخدمه للوصول إلى الخاصية مما يعطي مرونة كبيرة في التعامل. إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_26" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln">
  age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">30</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

let key </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"What do you want to know about the user?"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"name"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// الوصول باستخدام متغير</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> user</span><span class="pun">[</span><span class="pln">key</span><span class="pun">]</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// John (if enter "name")</span></pre>

<p>
	لا يمكن استخدام الصيغة النُقطية بالطريقة نفسها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_28" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln">
  age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">30</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

let key </span><span class="pun">=</span><span class="pln"> </span><span class="str">"name"</span><span class="pun">;</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> user</span><span class="pun">.</span><span class="pln">key </span><span class="pun">)</span><span class="pln"> </span><span class="com">// غير معروف</span></pre>

<h3>
	الخاصيات المحسوبة
</h3>

<p>
	يمكن استخدام الأقواس المعقوفة في كائن معرَّف بالأقواس، وهذا ما يسمى بالخاصيات المحسوبة. إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_30" style="">
<span class="pln">let fruit </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"Which fruit to buy?"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"apple"</span><span class="pun">);</span><span class="pln">

let bag </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">[</span><span class="pln">fruit</span><span class="pun">]:</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="com">// fruit يؤخذ اسم الخاصية من المتغير </span><span class="pln">
</span><span class="pun">};</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> bag</span><span class="pun">.</span><span class="pln">apple </span><span class="pun">);</span><span class="pln"> </span><span class="com">// fruit="apple" قيمتها 5 إذا كانت</span></pre>

<p>
	معنى الخاصية المحسوبة سهل: تعني <code>[fruit]</code> أنَّ اسم الخاصية يجب أن يُؤخذ من <code>fruit</code>؛ لذا، إن أدخل الزائر <code>"apple"</code>، ستصبح قيمة <code>bag</code> هي <code>{apple: 5}</code>.
</p>

<p>
	يعمل الأمر السابق بالطريقة التالية ذاتها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_32" style="">
<span class="pln">let fruit </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"Which fruit to buy?"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"apple"</span><span class="pun">);</span><span class="pln">
let bag </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">

</span><span class="com">// fruit خُذ اسم الخاصية من المتغير </span><span class="pln">
bag</span><span class="pun">[</span><span class="pln">fruit</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span></pre>

<p>
	لكن شكله يبدو أفضل، أليس كذلك؟! يمكن استخدام تعابير أكثر تعقيدًا داخل الأقواس المعقوفة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_34" style="">
<span class="pln">let fruit </span><span class="pun">=</span><span class="pln"> </span><span class="str">'apple'</span><span class="pun">;</span><span class="pln">
let bag </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">[</span><span class="pln">fruit </span><span class="pun">+</span><span class="pln"> </span><span class="str">'Computers'</span><span class="pun">]:</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="com">// bag.appleComputers = 5</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	الأقواس المعقوفة أكثر قوة من الصيغة النُقطية. فهي تسمح باستخدام أي اسم للخاصيات والمتغيرات. لكنها أكثر تعقيدا في الكتابة. لذا، إن كانت أسماء المتغيرات سهلة ومعروفة، تُستخدَم الصيغة النُقَطية غالبًا. وإن أردنا بعض التعقيد، نستخدم إلى الأقواس المعقوفة.
</p>

<h4>
	<strong>يمكن استخدام الأسماء المحجوزة مع أسماء الخاصيات</strong>
</h4>

<p>
	لا يمكن لمتغير أن يحمل اسم إحدى الكلمات المحجوزة في اللغة مثل "for"، أو "let"، أو "return"، …الخ. لكن لا تُطبَّق هذه القاعدة على أسماء خاصيات الكائنات. فيمكن استخدام أي اسم معها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_36" style="">
<span class="pln">let obj </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">for</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln">
  let</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln">
  </span><span class="kwd">return</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> obj</span><span class="pun">.</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> obj</span><span class="pun">.</span><span class="pln">let </span><span class="pun">+</span><span class="pln"> obj</span><span class="pun">.</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">);</span><span class="pln">  </span><span class="com">// 6</span></pre>

<p>
	عمومًا، يمكن استخدام أي اسم، لكن هناك استثناء: <code>"__proto__"</code> لهذا الاسم معاملة خاصة لأسباب تاريخية. مثلًا، لا يمكننا استخدام الاسم على أنَّه قيمة لغير كائن:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_38" style="">
<span class="pln">let obj </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
obj</span><span class="pun">.</span><span class="pln">__proto__ </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">obj</span><span class="pun">.</span><span class="pln">__proto__</span><span class="pun">);</span><span class="pln"> </span><span class="com">// لا تعمل وفق المطلوب [object Object]</span></pre>

<p>
	كما نرى في الشيفرة، تم تجاهل تخزين القيمة الأولية <code>5</code>.
</p>

<p>
	تخزين أزواج الخاصيات التحكمية في كائن وإتاحة تحديد مفاتيح هذه الأزواج للزائر قد يجعل الشيفرة مصدرًا للأخطاء ومليئًا بالثغرات.
</p>

<p>
	في تلك الحالة، قد يختار الزائر - الخبير والماكر - الاسم <code>__proto__</code> ليكون مفتاحًا ويخرِّب البنية المنطقية للشيفرة (كما في المثال أعلاه). يوجد طريقة لجعل الكائنات تتعامل مع <code>__proto__</code> بِعدِّها خاصية عادية وسنتطرق لها لاحقًا بعد فهم الكائنات بشكل أعمق.
</p>

<p>
	يوجد أيضا هيكل بيانات آخر يدعى Map، والذي ستتعلمه في القسم الذي يتحدث عن نوعي البيانات <code>Map</code> و <code>Set</code>، اللذين يدعمان استعمال أي نوع مع المفاتيح.
</p>

<h2>
	اختزال قيم الخاصيات
</h2>

<p>
	نستخدم غالبا قيم متغيرات موجودة مسبقًا لتكون قيمًا لأسماء الخاصيات في الشيفرات الحقيقية. اطلع مثلًا على الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_40" style="">
<span class="kwd">function</span><span class="pln"> makeUser</span><span class="pun">(</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> age</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    name</span><span class="pun">:</span><span class="pln"> name</span><span class="pun">,</span><span class="pln">
    age</span><span class="pun">:</span><span class="pln"> age
    </span><span class="com">// ... خاصيات أخرى</span><span class="pln">
  </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

let user </span><span class="pun">=</span><span class="pln"> makeUser</span><span class="pun">(</span><span class="str">"John"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">30</span><span class="pun">);</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">user</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span><span class="pln"> </span><span class="com">// John</span></pre>

<p>
	تحمل الخاصيات في المثال السابق نفس أسماء المتغيرات. يُعدُّ إنشاء خاصية من متغير موجود مسبقًا حالة استخدام شائعة. أي أنه يوجد اختزال خاص لقيمة الخاصية لاختصار الشيفرة. بدلا من كتابة <code>name:name</code>، يمكننا كتابة <code>name</code> فقط، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_42" style="">
<span class="kwd">function</span><span class="pln"> makeUser</span><span class="pun">(</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> age</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    name</span><span class="pun">,</span><span class="pln"> </span><span class="com">// name: name يماثل كتابة </span><span class="pln">
    age   </span><span class="com">// age: age يماثل كتابة</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
  </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكننا استخدام كلًا من الخاصيات الاعتيادية والاختزال في الكائن ذاته:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_44" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">,</span><span class="pln">  </span><span class="com">// name:name يماثل</span><span class="pln">
  age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">30</span><span class="pln">
</span><span class="pun">};</span></pre>

<h2>
	فحص الكينونة
</h2>

<p>
	قابلية الوصول إلى أي خاصية في الكائن هي إحدى مميزات الكائنات، ولكن ألَا يوجد أي خطأ في حال لم تكن الخاصية موجودة؟! عند محاولة الوصول إلى خاصية غير موجودة، تُرجَع القيمة <code>undefined</code>. مما يُعطي طريقة متعارفة لفحص كينونة (وجود) خاصية ما من عدمه بموازنتها مع القيمة <code>"undefined"</code> ببساطة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_46" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> user</span><span class="pun">.</span><span class="pln">noSuchProperty </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">undefined</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// تحقق هذه الموازنة يشير إلى عدم وجود الخاصية</span></pre>

<p>
	يوجد أيضا مُعامل خاص <code>"in"</code> لفحص تواجد أي خاصية. طريقة استخدام هذا المعامل كالتالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_48" style="">
<span class="str">"key"</span><span class="pln"> in object</span></pre>

<p>
	مثلا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_50" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln"> age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">30</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"age"</span><span class="pln"> in user </span><span class="pun">);</span><span class="pln"> </span><span class="com">// true, user.age موجود</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"blabla"</span><span class="pln"> in user </span><span class="pun">);</span><span class="pln"> </span><span class="com">// false, user.blabla غير موجود</span></pre>

<p>
	لاحظ أنه من الضروري وجود اسم الخاصية على يسار <code>in</code>. ويكون عادة نصًا بين علامتي تنصيص. إن لم نستخدم علامتي التنصيص فهذا يعني فحص متغير يحمل الاسم ذاته مثل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_52" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">30</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

let key </span><span class="pun">=</span><span class="pln"> </span><span class="str">"age"</span><span class="pun">;</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> key in user </span><span class="pun">);</span><span class="pln"> </span><span class="com">// key إذ تؤخذ قيمة المتغير true تطبع القيمة</span><span class="pln">
               </span><span class="com">// user ويُتحقق من وجود خاصية بذلك الاسم في الكائن</span></pre>

<h3>
	<strong>استخدام "in" مع الخاصيات التي تُخزن القيمة <code>undefined</code></strong>
</h3>

<p>
	تفحص عملية الموازنة الصارمة <code>"=== undefined"</code> غالبًا وجود الخاصية وفق المطلوب. لكن يوجد حالة خاصة تفشل فيها هذه العملية، بينما لا يفشل المعامل <code>in</code> إن استعمل مكانها. هذه الحالة هي عند وجود الخاصية في الكائن لكنها تُخزن القيمة <code>undefined</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_54" style="">
<span class="pln">let obj </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  test</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">undefined</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> obj</span><span class="pun">.</span><span class="pln">test </span><span class="pun">);</span><span class="pln"> </span><span class="com">// ولكن هل تُعدُّ الخاصية موجودة أم لا؟ undefined يطبع القيمة</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"test"</span><span class="pln"> in obj </span><span class="pun">);</span><span class="pln"> </span><span class="com">// وتَعدُّ الخاصية موجودة في الكائن true تُطبع القيمة</span></pre>

<p>
	الخاصية <code>obj.test</code> موجودة فعليًا في الشيفرة أعلاه، لذا يعمل المُعامل <code>in</code> بصحة.
</p>

<p>
	تحدث مثل هذه الحالات نادرًا فقط لأن القيمة <code>undefined</code> لا تُستخدَم بكثرة. نستخدم غالبا القيمة <code>null</code> للقيم الفارغة أو الغير معرفة، لذلك يُعد المُعامل <code>in</code> قليل الاستخدام في الشيفرات.
</p>

<h2>
	الحلقة <code>for…in</code>
</h2>

<p>
	يوجد شكل خاص للحلقة <code>for..in</code> للمرور خلال جميع مفاتيح كائنٍ ما. هذه الحلقة مختلفة تمامًا عما درسناه سابقًا، أي الحلقة <code>for(;;)‎</code>.
</p>

<p>
	صياغة الحلقة تكون بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_56" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">key in object</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// يتنفذ ما بداخل الحلقة لكل مفتاح ضمن خاصيات الكائن</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مثلا، لنطبع جميع خاصيات الكائن <code>user</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_58" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln">
  age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">30</span><span class="pun">,</span><span class="pln">
  isAdmin</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let key in user</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// المفاتيح</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> key </span><span class="pun">);</span><span class="pln">  </span><span class="com">// name, age, isAdmin</span><span class="pln">
  </span><span class="com">// قيم المفاتيح</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> user</span><span class="pun">[</span><span class="pln">key</span><span class="pun">]</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// John, 30, true</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ أن جميع تراكيب "for" تتيح لنا تعريف متغير التكرار بِداخل الحلقة، مثل <code>let key</code> في المثال السابق. يمكننا أيضًا استخدام اسم متغير آخر بدلًا من <code>key</code>. إليك مثال يُستخدم بكثرة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_64" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let prop in obj</span><span class="pun">)</span></pre>

<h3>
	الترتيب في الكائنات
</h3>

<p>
	هل الكائنات مرتبة؟ بمعنى آخر، إن تنقلنا في حلقة خلال كائن، هل نحصل على جميع الخاصيات بنفس الترتيب الذي أُضيفت به؟ وهل يمكننا الاعتماد على هذا؟
</p>

<p>
	الإجابة باختصار هي: "مرتب بطريقة خاصة": الخاصيات الرقمية يُعاد ترتيبها، تظهر باقي الخاصيات بترتيب الإنشاء ذاته كما في التفاصيل التالية.
</p>

<p>
	لنرَ مثالًا لكائن بِرموز الهاتف:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_66" style="">
<span class="pln">let codes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="str">"49"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Germany"</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"41"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Switzerland"</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"44"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Great Britain"</span><span class="pun">,</span><span class="pln">
  </span><span class="com">// ..,</span><span class="pln">
  </span><span class="str">"1"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"USA"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let code in codes</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln">code</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 1, 41, 44, 49</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	قد تُستخدم الشيفرة لاقتراح قائمة من الخيارات للمستخدم. إن كنا نبني موقعًا لزوار من ألمانيا فقد نريد أن تظهر <code>49</code> أولا. لكن، عند تشغيل الشيفرة، نرى شيئا مختلفًا تماما:
</p>

<ul>
<li>
		تظهر USA (1)‎ أولًا
	</li>
	<li>
		ثم Switzerland (41)‎ وهكذا.
	</li>
</ul>
<p>
	تُستخدم رموز الهواتف بترتيب تصاعدي لأنها أعدادٌ، لذا نرى <code>1, 41, 44, 49</code>.
</p>

<h4>
	<strong>خاصيات عددية؟ ما هذا؟</strong>
</h4>

<p>
	تعني "الخاصية العددية" (integer property) نصًا يمكن تحويله من وإلى عدد دون أن يتغير. لذا فإن <code>49</code> هو اسم خاصية عددي لأنه عند تحويله إلى عدد وإرجاعه لنص يبقى كما هو. لكن "1.2" و "‎+49" ليست كذلك:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_68" style="">
<span class="com">// هي دالة تحذف الجزء العشري Math.trunc</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="typ">String</span><span class="pun">(</span><span class="typ">Math</span><span class="pun">.</span><span class="pln">trunc</span><span class="pun">(</span><span class="typ">Number</span><span class="pun">(</span><span class="str">"49"</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// "49", الخاصية العددية ذاتها</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="typ">String</span><span class="pun">(</span><span class="typ">Math</span><span class="pun">.</span><span class="pln">trunc</span><span class="pun">(</span><span class="typ">Number</span><span class="pun">(</span><span class="str">"+49"</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// ‏ "49" مختلفة عن "49+" =&gt; إذًا ليست خاصية عددية </span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="typ">String</span><span class="pun">(</span><span class="typ">Math</span><span class="pun">.</span><span class="pln">trunc</span><span class="pun">(</span><span class="typ">Number</span><span class="pun">(</span><span class="str">"1.2"</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">//  ‏ "1" مختلفة عن "1.2" =&gt; إذًا ليست خاصية عددية </span></pre>

<p>
	في المقابل، إن كانت المفاتيح غير عددية، فتُعرَض بالترتيب الذي أُنشِئت به. إليك مثال على ذلك:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_70" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln">
  surname</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Smith"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
user</span><span class="pun">.</span><span class="pln">age </span><span class="pun">=</span><span class="pln"> </span><span class="lit">25</span><span class="pun">;</span><span class="pln"> </span><span class="com">// add one more</span><span class="pln">

</span><span class="com">// تُعرض الخاصيات الغير رقمية بترتيب الإنشاء</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let prop in user</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> prop </span><span class="pun">);</span><span class="pln"> </span><span class="com">// name, surname, age</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لذا، لحل مشكلة رموز الهواتف يمكننا التحايل وجعلها غير عددية بإضافة <code>"+"</code> قبل كل رمز كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_72" style="">
<span class="pln">let codes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="str">"+49"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Germany"</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"+41"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Switzerland"</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"+44"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Great Britain"</span><span class="pun">,</span><span class="pln">
  </span><span class="com">// ..,</span><span class="pln">
  </span><span class="str">"+1"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"USA"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let code in codes</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="pun">+</span><span class="pln">code </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 49, 41, 44, 1</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الآن تعمل وفق المطلوب!
</p>

<h2>
	النسخ بالمرجع
</h2>

<p>
	إحدى الاختلافات الرئيسية بين الكائنات والمتغيرات الأولية هي أنَّ الكائنات تُخزن وتُنسخ "بالمرجع". بينما تُخزن/تُنسخ القيم الأولية: النصوص، والأرقام، والقيم المنطقية بِعدِّها قيمةً كاملةً. إليك المثال التوضيحي التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_74" style="">
<span class="pln">let message </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello!"</span><span class="pun">;</span><span class="pln">
let phrase </span><span class="pun">=</span><span class="pln"> message</span><span class="pun">;</span></pre>

<p>
	لدينا في هذه الشيفرة متغيرين مستقلين كلاهما يُخزن النص <code>"Hello!‎ "</code>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33540" href="https://academy.hsoub.com/uploads/monthly_2020_01/7.png.616fe26fbb5b98d8a7a0b9c14311f447.png" rel=""><img alt="7.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33540" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/7.png.616fe26fbb5b98d8a7a0b9c14311f447.png"></a>
</p>

<p>
	الكائنات ليست كذلك.
</p>

<p>
	<strong>لا يُخزِّن المتغير الكائن نفسه، وإنما "عنوانه في الذاكرة". بمعنى آخر، "مرجع للكائن"</strong>
</p>

<p>
	هنا صورة للكائن:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_76" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	 
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33541" href="https://academy.hsoub.com/uploads/monthly_2020_01/8.png.eba4b62f533606b30c8da05cfea2260e.png" rel=""><img alt="8.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33541" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/8.png.eba4b62f533606b30c8da05cfea2260e.png"></a>
</p>

<p>
	كما نرى، يُخزَّن المتغير في مكان ما في الذاكرة ويُخزِّن المتغير <code>user</code> <em>مرجعًا</em> إليه.
</p>

<p>
	<strong>عند نسخ متغير من نوع كائن، يُنسَخ المرجع الذي يشير إلى ذلك الكائن ولا يُنسَخ الكائن نفسه ويُكرَّر.</strong> إذا تخيلنا الكائن كخزانة، فإن المتغير هو مفتاح الخزانة ونسخ المتغير يكرِّر المفتاح وليس الخزانة ذاتها. إليك مثال يوضح ما ذكرناه:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_78" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

let admin </span><span class="pun">=</span><span class="pln"> user</span><span class="pun">;</span><span class="pln"> </span><span class="com">// يُنسَخ المرجع</span></pre>

<p>
	الآن، أصبح لدينا متغيرين، كلاهما يحمل مرجعًا للكائن ذاته:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33542" href="https://academy.hsoub.com/uploads/monthly_2020_01/9.png.7f506f827902c560096b5739a5d8d3df.png" rel=""><img alt="9.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33542" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/9.png.7f506f827902c560096b5739a5d8d3df.png"></a>
</p>

<p>
	يمكننا استخدام كلا المتغيرين (المفتاحين) للوصول إلى الخزانة وتعديل محتواها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_80" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">'John'</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

let admin </span><span class="pun">=</span><span class="pln"> user</span><span class="pun">;</span><span class="pln">

admin</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Pete'</span><span class="pun">;</span><span class="pln"> </span><span class="com">// "admin" عُدِّلت باستخدام المرجع </span><span class="pln">

alert</span><span class="pun">(</span><span class="pln">user</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span><span class="pln"> </span><span class="com">// "user" أي يمكن رؤية التعديلات من المرجع 'Pete' تُعرَض القيمة</span></pre>

<p>
	يوضح المثال أعلاه وجود كائن واحد فقط. كما لو كان لدينا خزامة بمفتاحين، واستخدمنا أحدهما (<code>admin</code>) للوصول إلى الخزانة. ثم إذا استخدمنا الآخر (<code>user</code>) لاحقًا، فسنرى إنعكاس التغييرات التي أجراها الأول.
</p>

<h3>
	الموازنة بالمرجع
</h3>

<p>
	يعمل مُعاملي المساواة <code>==</code> والمساواة الصارمة <code>===</code> بنفس الطريقة للكائنات. <strong>يكون الكائنان متساويان إذا كانَا الكائن نفسه فقط.</strong> أي، إذا كان متغيران يشيران للكائن ذاته، فهما متساويان:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_82" style="">
<span class="pln">let a </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
let b </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">;</span><span class="pln"> </span><span class="com">// نفس المرجع</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> a </span><span class="pun">==</span><span class="pln"> b </span><span class="pun">);</span><span class="pln"> </span><span class="com">// true, كلا المتغيرين يشيران للكائن نفسه</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> a </span><span class="pun">===</span><span class="pln"> b </span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span></pre>

<p>
	وهنا متغيران مستقلان ليسا متساويين أي يشيران إلى كائنين منفصلين حتى وإن كانا متماثلين تمامًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_84" style="">
<span class="pln">let a </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
let b </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln"> </span><span class="com">// متغيران منفصلان</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> a </span><span class="pun">==</span><span class="pln"> b </span><span class="pun">);</span><span class="pln"> </span><span class="com">// خطأ</span></pre>

<p>
	يُحوَّل الكائن إلى قيمة أولية (أساسية) في الموازنات مثل <code>obj1 &gt; obj2</code> أو <code>obj == 5</code>. سندرس كيفية تحويل الكائنات قريبًا، لكن، في الحقيقة، مثل هذه الموازنات تكون نادرة الضرورة وتنتج غالبًا من خطأ في كتابة الشيفرة.
</p>

<h3>
	الكائنات الثابتة
</h3>

<p>
	يمكن تغيير الكائن المُعَرَّف على أنَّه ثابت (أي وسم المتغير الذي يحوي الكائن بالكلمة المفتاحية <code>const</code>) دون حصول أي أخطاء. إليك الشيفرة التالية مثلًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_86" style="">
<span class="kwd">const</span><span class="pln"> user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

user</span><span class="pun">.</span><span class="pln">age </span><span class="pun">=</span><span class="pln"> </span><span class="lit">25</span><span class="pun">;</span><span class="pln"> </span><span class="com">// (*)</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln">user</span><span class="pun">.</span><span class="pln">age</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 25</span></pre>

<p>
	قد يبدو أن السطر <code>(*)</code> سيسبب خطأ، لكن لا يوجد أي مشكلة البتة. ذلك لأنَّ <code>const</code> تحافظ على قيمة <code>user</code> ذاتها وتمنع تغييرها. ويُحزِّن <code>user</code> المرجع للكائن نفسه دائمًا ولا يتغيِّر بتعديل الكائن نفسه. يدخل السطر <code>(*)</code> إلى الكائن ولا يعيد تعيين قيمة المتغير <code>user</code>.
</p>

<p>
	يمكن أن يعطي <code>const</code> خطأ إن حاولنا تغيير قيمة المتغير <code>user</code> مثل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_88" style="">
<span class="kwd">const</span><span class="pln"> user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">// (user خطأ (لا يمكن تغيير قيمة المتغير</span><span class="pln">
user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Pete"</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لكن، ماذا إن أردنا إنشاء خاصيات ثابتة ضمن الكائن؟ سيُعطي <code>user.age = 25</code> آنذاك خطأ، وذلك ممكن أيضًا. سيتم شرحه في الفصل <a href="https://javascript.info/property-descriptors" rel="external nofollow">رايات الخاصيات وواصفاتها</a>.
</p>

<h2>
	الاستنساخ والدمج
</h2>

<p>
	إذًا، نسخ كائن يُنشِئ مرجعًا إضافيًّا له. لكن ماذا إن كنا نريد تكرار كائن فعليًّا أي إنشاء نسخة مستقلة منه؟ ذلك ممكن أيضًا، لكنه أصعب قليلًا لعدم وجود دالة تقوم بذلك في JavaScript ذلك لأنَّه لا حاجة لذلك بكثرة. النسخ بالمرجع كافٍ غالبًا.
</p>

<p>
	لكن إن أردنا ذلك فعلًا، فإننا نحتاج لإنشاء كائن وتكرار هيكل الكائن الموجود عبر التنقل خلال خاصياته ونسخها على المستوى الأولي. وإليك مثال على ذلك:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_90" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln">
  age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">30</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

let clone </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln"> </span><span class="com">// الكائن الجديد الفارغ</span><span class="pln">

</span><span class="com">// إليه user ننسخ جميع خاصيات المتغير</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let key in user</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  clone</span><span class="pun">[</span><span class="pln">key</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> user</span><span class="pun">[</span><span class="pln">key</span><span class="pun">];</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// الآن أصبحت النسخة مستقلة تماما</span><span class="pln">
clone</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Pete"</span><span class="pun">;</span><span class="pln"> </span><span class="com">// تغيير البيانات في النسخة</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> user</span><span class="pun">.</span><span class="pln">name </span><span class="pun">);</span><span class="pln"> </span><span class="com">//  في الكائن الأصلي John تظل</span></pre>

<p>
	يمكننا استخدام الدالة <a href="https://wiki.hsoub.com/JavaScript/Object/assign" rel="external">Object.assign</a> للغرض ذاته.
</p>

<p>
	الصياغة الدالة هي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_94" style="">
<span class="typ">Object</span><span class="pun">.</span><span class="pln">assign</span><span class="pun">(</span><span class="pln">dest</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">src1</span><span class="pun">,</span><span class="pln"> src2</span><span class="pun">,</span><span class="pln"> src3</span><span class="pun">...])</span></pre>

<ul>
<li>
		تُعد المُعاملات <code>dest</code>، و <code>src1</code>، وحتى <code>srcN</code> كائنات (يمكن أن تكون بالعدد المُراد).
	</li>
	<li>
		تنسخ الدالة خاصيات جميع الكائنات <code>src1, ..., srcN</code> إلى الكائن <code>dest</code>. بمعنى آخر، تُنسخ جميع الخاصيات لجميع المُعاملات بدءًا من المُعامل الثاني إلى المُعامل الأول. ثم يتم إرجاع <code>dest</code>.
	</li>
</ul>
<p>
	مثلا، يمكننا استخدام الدالة لدمج عدة كائنات إلى كائن واحد:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_96" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

let permissions1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> canView</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
let permissions2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> canEdit</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

</span><span class="com">// user إلى permissions2 و permissions1 تنسخ جميع الخاصيات من </span><span class="pln">
</span><span class="typ">Object</span><span class="pun">.</span><span class="pln">assign</span><span class="pun">(</span><span class="pln">user</span><span class="pun">,</span><span class="pln"> permissions1</span><span class="pun">,</span><span class="pln"> permissions2</span><span class="pun">);</span><span class="pln">

</span><span class="com">// now user = { name: "John", canView: true, canEdit: true }</span></pre>

<p>
	إن كان الكائن <code>user</code> يحوي أحد أسماء الخاصيات مسبقًا، فسيتم إعادة كتابة محتواها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_98" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

</span><span class="com">// isAdmin وإضافة name إعادة كتابة  </span><span class="pln">
</span><span class="typ">Object</span><span class="pun">.</span><span class="pln">assign</span><span class="pun">(</span><span class="pln">user</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Pete"</span><span class="pun">,</span><span class="pln"> isAdmin</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">});</span><span class="pln">

</span><span class="com">// now user = { name: "Pete", isAdmin: true }</span></pre>

<p>
	يمكننا أيضًا استخدام الدالة <code>Object.assign</code> بدلًا من الحلقة للاستنساخ البسيط:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_100" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln">
  age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">30</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

let clone </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">.</span><span class="pln">assign</span><span class="pun">({},</span><span class="pln"> user</span><span class="pun">);</span></pre>

<p>
	تنسخ الدالة جميع خاصيات الكائن <code>user</code> إلى الكائن الفارغ وتُرجِعه كما في الحلقة لكن بشكل أقصر. حتى الآن، عدَدْنا جميع خاصيات <code>user</code> أولية (أساسية)، لكن قد تكون بعض الخاصيات مرجعًا لكائن آخر مثل الشيفرة التالية فما العمل؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_102" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln">
  sizes</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    height</span><span class="pun">:</span><span class="pln"> </span><span class="lit">182</span><span class="pun">,</span><span class="pln">
    width</span><span class="pun">:</span><span class="pln"> </span><span class="lit">50</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> user</span><span class="pun">.</span><span class="pln">sizes</span><span class="pun">.</span><span class="pln">height </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 182</span></pre>

<p>
	في هذه الحالة نسخ <code>clone.sizes = user.sizes</code> ليس كافيًا لأنَّ <code>user.sizes</code> عبارة عن كائن، فسيُنسَخ على أنَّه مرجعٌ. هكذا، سيصبح لدى <code>clone</code> و <code>user</code> الحجم ذاته:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_104" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">,</span><span class="pln">
  sizes</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    height</span><span class="pun">:</span><span class="pln"> </span><span class="lit">182</span><span class="pun">,</span><span class="pln">
    width</span><span class="pun">:</span><span class="pln"> </span><span class="lit">50</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

let clone </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">.</span><span class="pln">assign</span><span class="pun">({},</span><span class="pln"> user</span><span class="pun">);</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> user</span><span class="pun">.</span><span class="pln">sizes </span><span class="pun">===</span><span class="pln"> clone</span><span class="pun">.</span><span class="pln">sizes </span><span class="pun">);</span><span class="pln"> </span><span class="com">// صحيح،  الكائن ذاته</span><span class="pln">

</span><span class="com">// sizes الكائن الفرعي clone و user يتشارك الكائنان</span><span class="pln">
user</span><span class="pun">.</span><span class="pln">sizes</span><span class="pun">.</span><span class="pln">width</span><span class="pun">++;</span><span class="pln">       </span><span class="com">// تغيير خاصية من مكان ما</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">clone</span><span class="pun">.</span><span class="pln">sizes</span><span class="pun">.</span><span class="pln">width</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 51, يعرض النتيجة من مكان آخر</span></pre>

<p>
	لإصلاح هذا، يجب استخدام حلقة الاستنساخ التي تفحص كل قيمة في <code>user[key]‎</code>، وإن كان كائنًا نستبدل الهيكل الخاص به أيضًا. هذه الطريقة تُسمى "استنساخ عميق" (deep cloning).
</p>

<p>
	يوجد خوارزمية عامة للاستنساخ العميق تنفِّذ الحالة السابقة بشكل صحيح، بالإضافة إلى حالات أكثر تعقيدًا. تُدعى هذه الخوارزمية <a href="http://w3c.github.io/html/infrastructure.html#safe-passing-of-structured-data" rel="external nofollow">خوارزمية الاستنساخ المُهيكلة</a>. حتى لا نُعيد اختراع العجلة مجدَّدًا، يمكننا استخدام تنفيذ جاهز للحالة من مكتبة JavaScript <a href="https://lodash.com/" rel="external nofollow">lodash</a>، تُدعى الدالة <a href="https://lodash.com/docs#cloneDeep" rel="external nofollow">_.cloneDeep(obj)</a>.
</p>

<h2>
	الخلاصة
</h2>

<p>
	الكائنات عبارة عن مصفوفات ترابطية بميزات خاصة عديدة. تُخزن الكائنات خاصيات (أزواج مفتاح-قيمة)، بشرط أنه:
</p>

<ul>
<li>
		يجب أن تكون مفاتيح الخاصيات نصوصًا أو رموزًا (غالبًا نصوص).
	</li>
	<li>
		يمكن أن تكون القيم من أي نوع.
	</li>
</ul>
<p>
	يمكننا استخدام ما يلي للوصول إلى خاصية:
</p>

<ul>
<li>
		الصيغة النُقَطِيَّة: <code>obj.property</code>.
	</li>
	<li>
		صيغة الأقواس المعقوفة <code>obj["property"]‎</code>. تتيح لنا الأقواس المعقوفة أخذ مفتاح من متغير، مثل <code>obj[varWithKey]‎</code>.
	</li>
</ul>
<p>
	عمليات أخرى:
</p>

<ul>
<li>
		لِحذف خاصية: <code>delete obj.prop</code>.
	</li>
	<li>
		لِفحص تواجد خاصية بمفتاح معين: <code>"key" in obj</code>.
	</li>
	<li>
		للتنقل خلال كائن: الحلقة <code>for (let key in obj)‎</code>.
	</li>
</ul>
<p>
	تُخَزَّن الكائنات وتُنسخ باستخدام المرجع. بمعنىً آخر، لا يُخزن المتغير قيمة الكائن (object value) لكنه يُخزن مرجعًا (reference) يمثِّل موقع قيمة الكائن في الذاكرة. لذا فإن نسخ هذا المتغير أو تمريره إلى دالة سَينسخ هذا المرجع وليس الكائن ككُل. جميع العمليات (مثل إضافة أو حذف خاصيات) المُنفَّذة على مرجع منسوخ تُنفَّذ على الكائن نفسه.
</p>

<p>
	لعمل نسخة حقيقية (الاستنساخ) يمكننا استخدام <code>Object.assign</code> أو <a href="https://lodash.com/docs#cloneDeep" rel="external nofollow">_.cloneDeep(obj)</a>.
</p>

<p>
	يُسمى ما درسناه في هذا الفصل "كائن بسيط" أو كائن فقط. يوجد العديد من أنواع الكائنات الأخرى في JavaScript:
</p>

<ul>
<li>
		الكائن <code>Array</code> (مصفوفة): لتخزين مجموعة البيانات المرتبة،
	</li>
	<li>
		الكائن <code>Date</code> (تاريخ): لتخزين معلومات عن الوقت والتاريخ،
	</li>
	<li>
		الكائن <code>Error</code> (خطأ): لتخزين معلومات عن خطأ ما.
	</li>
	<li>
		وغيرها من أنواع الكائنات.
	</li>
</ul>
<p>
	لدى هذه الأنواع ميزاتها الخاصة التي سيتم دراستها لاحقًا. يقول بعض الأشخاص أحيانًا شيئًا مثل "نوع مصفوفة" أو "نوع تاريخ" (الاسم الذي وضعته بين قوسين بجانب نوع الكائن)، لكن هذه الأنواع ليست أنواعًا مستقلة بحد ذاتها، إنما تنتمي إلى نوع البيانات <code>Object</code> (كائن) وتتفرع عنه بأشكال مختلفة.
</p>

<p>
	تُعد الكائنات في JavaScript قوية جدًا. درسنا في هذا الفصل جزءًا بسيطًا من موضوع هائل جدًا. سنتعامل مع الكائنات لاحقًا بصورة أقرب وسَنتعلم أكثر عنها في فصول أخرى.
</p>

<h2>
	تمارين
</h2>

<h3>
	مرحبًا، بالكائن
</h3>

<p class="task__importance">
	الأهمية: 5
</p>

<p>
	اكتب الشيفرة البرمجية، سطر لكل متطلب:
</p>

<ol>
<li>
		أنشئ كائنًا فارغًا باسم <code>user</code>.
	</li>
	<li>
		أضف الخاصية <code>name</code> بالقيمة <code>John</code>.
	</li>
	<li>
		أضف الخاصية <code>surname</code> بالقيمة <code>Smith</code>.
	</li>
	<li>
		غير قيمة الخاصية <code>name</code> إلى <code>Pete</code>.
	</li>
	<li>
		احذف الخاصية <code>name</code> من الكائن.
	</li>
</ol>
<h4>
	الحل
</h4>

<div class="task__answer">
	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_106" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
user</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">;</span><span class="pln">
user</span><span class="pun">.</span><span class="pln">surname </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Smith"</span><span class="pun">;</span><span class="pln">
user</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Pete"</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">delete</span><span class="pln"> user</span><span class="pun">.</span><span class="pln">name</span><span class="pun">;</span></pre>
</div>

<h3>
	التحقق من الفراغ
</h3>

<p>
	اكتب الدالة <code>isEmpty(obj)‎</code> التي تُرجع القيمة <code>true</code> إن كان الكائن فارغًا، وتُرجِع القيمة <code>false</code> في الحالات الأخرى. يجب أن تعمل كالتالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_108" style="">
<span class="pln">let schedule </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> isEmpty</span><span class="pun">(</span><span class="pln">schedule</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">

schedule</span><span class="pun">[</span><span class="str">"8:30"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"get up"</span><span class="pun">;</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> isEmpty</span><span class="pun">(</span><span class="pln">schedule</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// false</span></pre>

<p>
	إليك <a href="https://plnkr.co/edit/5UQxKiMcz7Vrp3EVu5KO?p=preview" rel="external nofollow">تجربة حية</a> للمثال.
</p>

<h4>
	الحل
</h4>

<div class="task__answer">
	<p>
		قم بالمرور خلال الكائن ونفذ الأمر <code>return false</code> مباشرة إن عثرت على أي خاصية:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_110" style="">
<span class="kwd">function</span><span class="pln"> isEmpty</span><span class="pun">(</span><span class="pln">obj</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let key in obj</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// إن بدأت الحلقة بالعمل، فهناك خاصية في الكائن</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>
</div>

<h3>
	كائنات ثابتة؟
</h3>

<p class="task__importance">
	الأهمية: 5
</p>

<p>
	هل من الممكن تغيير كائن صُرِّح عنه بالكلمة المفتاحية <code>const</code>؟ ما رأيك؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_112" style="">
<span class="kwd">const</span><span class="pln"> user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">// هل تعمل؟</span><span class="pln">
user</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Pete"</span><span class="pun">;</span></pre>

<h4>
	الحل
</h4>

<div class="task__answer">
	<p>
		بالفعل ستعمل بدون مشاكل. تحمي الكلمة المفتاحية <code>const</code> المتغير نفسه من التغيير فقط. بمعنى آخر، يخزن <code>user</code> مرجعًا للكائن ولا يمكن تغييره مع وجود التصريح عنه بالكلمة المفتاحية <code>const</code> لكن يمكن تغيير محتوى الكائن.
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_114" style="">
<span class="kwd">const</span><span class="pln"> user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">// تعمل</span><span class="pln">
user</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Pete"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// خطأ</span><span class="pln">
user </span><span class="pun">=</span><span class="pln"> </span><span class="lit">123</span><span class="pun">;</span></pre>
</div>

<h3>
	جمع خاصيات الكائن
</h3>

<p>
	لدينا كائن يُخزن رواتب الفريق:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_116" style="">
<span class="pln">let salaries </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="typ">John</span><span class="pun">:</span><span class="pln"> </span><span class="lit">100</span><span class="pun">,</span><span class="pln">
  </span><span class="typ">Ann</span><span class="pun">:</span><span class="pln"> </span><span class="lit">160</span><span class="pun">,</span><span class="pln">
  </span><span class="typ">Pete</span><span class="pun">:</span><span class="pln"> </span><span class="lit">130</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	اكتب الشيفرة التي تجمع الرواتب وتُخزنها في المتغير <code>sum</code>. يجب أن يكون مجموع المثال أعلاه <code>390</code>. إن كان <code>salaries</code> فارغًا، فإن الناتج سيكون <code>0</code>.
</p>

<h4>
	الحل
</h4>

<div class="task__answer">
	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_118" style="">
<span class="pln">let salaries </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="typ">John</span><span class="pun">:</span><span class="pln"> </span><span class="lit">100</span><span class="pun">,</span><span class="pln">
  </span><span class="typ">Ann</span><span class="pun">:</span><span class="pln"> </span><span class="lit">160</span><span class="pun">,</span><span class="pln">
  </span><span class="typ">Pete</span><span class="pun">:</span><span class="pln"> </span><span class="lit">130</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

let sum </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let key in salaries</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  sum </span><span class="pun">+=</span><span class="pln"> salaries</span><span class="pun">[</span><span class="pln">key</span><span class="pun">];</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln">sum</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 390</span></pre>
</div>

<h3>
	ضرب الخاصيات العددية بالقيمة 2
</h3>

<p class="task__importance">
	الأهمية: 3
</p>

<p>
	أنشئ دالةً باسم <code>multiplyNumeric(obj)‎</code> تضرب جميع الخاصيات العددية في الكائن <code>obj</code> في العدد 2.
</p>

<p>
	مثلا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_120" style="">
<span class="com">// قبل الاستدعاء</span><span class="pln">
let menu </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  width</span><span class="pun">:</span><span class="pln"> </span><span class="lit">200</span><span class="pun">,</span><span class="pln">
  height</span><span class="pun">:</span><span class="pln"> </span><span class="lit">300</span><span class="pun">,</span><span class="pln">
  title</span><span class="pun">:</span><span class="pln"> </span><span class="str">"My menu"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

multiplyNumeric</span><span class="pun">(</span><span class="pln">menu</span><span class="pun">);</span><span class="pln">

</span><span class="com">// بعد الاستدعاء</span><span class="pln">
menu </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  width</span><span class="pun">:</span><span class="pln"> </span><span class="lit">400</span><span class="pun">,</span><span class="pln">
  height</span><span class="pun">:</span><span class="pln"> </span><span class="lit">600</span><span class="pun">,</span><span class="pln">
  title</span><span class="pun">:</span><span class="pln"> </span><span class="str">"My menu"</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لاحظ أنَّ الدالة <code>multiplyNumeric</code> لا يجب أن تُرجِع أي شيء. يجب أن تُعدِّل القيم بداخل الكائن.
</p>

<p>
	<em>ملاحظة</em>: استخدام <code>typeof</code> لفحص الأعداد.
</p>

<p>
	إليك <a href="https://next.plnkr.co/edit/UtKOSHvCbQlQWHX0wLRj?p=preview&amp;utm_source=legacy&amp;utm_medium=worker&amp;utm_campaign=next&amp;preview" rel="external nofollow">تجربة حية</a> للتمرين.
</p>

<h4>
	الحل
</h4>

<div class="task__answer">
	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2760_122" style="">
<span class="kwd">function</span><span class="pln"> multiplyNumeric</span><span class="pun">(</span><span class="pln">obj</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let key in obj</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">typeof</span><span class="pln"> obj</span><span class="pun">[</span><span class="pln">key</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">'number'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      obj</span><span class="pun">[</span><span class="pln">key</span><span class="pun">]</span><span class="pln"> </span><span class="pun">*=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>
</div>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/object" rel="external nofollow">Objects</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D9%83%D9%86%D8%B3-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%87%D9%85%D9%84%D8%A9-r797/" rel="">كنس البيانات المهملة</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D8%AA%D8%B9%D9%88%D9%8A%D8%B6-%D9%86%D9%82%D8%B5-%D8%AF%D8%B9%D9%85-%D8%A7%D9%84%D9%85%D8%AA%D8%B5%D9%81%D8%AD%D8%A7%D8%AA-%D9%84%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r795/" rel="">تعويض نقص دعم المتصفحات لجافاسكربت</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">796</guid><pubDate>Sun, 09 Feb 2020 18:03:00 +0000</pubDate></item><item><title>&#x62A;&#x639;&#x648;&#x64A;&#x636; &#x646;&#x642;&#x635; &#x62F;&#x639;&#x645; &#x627;&#x644;&#x645;&#x62A;&#x635;&#x641;&#x62D;&#x627;&#x62A; &#x644;&#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A;</title><link>https://academy.hsoub.com/programming/javascript/%D8%AA%D8%B9%D9%88%D9%8A%D8%B6-%D9%86%D9%82%D8%B5-%D8%AF%D8%B9%D9%85-%D8%A7%D9%84%D9%85%D8%AA%D8%B5%D9%81%D8%AD%D8%A7%D8%AA-%D9%84%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r795/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/25.jpg.6a4809ac6f4fcfd49c2d3156ae66761f.jpg" /></p>

<p>
	تتطور لغة جافاسكربت باستمرار نتيجةً لوجود العديد من المقترحات المبنية على الحاجة إلى تطويرها دوريًا. تُحلَّل هذه المقترحات وتُضاف إن كانت جيدة إلى القائمة <a href="https://tc39.github.io/ecma262/" rel="external nofollow">https://tc39.github.io/ecma262/</a> ثم النظر في <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm" rel="external nofollow">وصفها</a>.
</p>

<p>
	لدى الفِرَق العاملة على محركات جافاسكربت أفكارها الخاصة حول ما يجب تنفيذه أولًا. قد تقرر هذه الفِرَق تنفيذ مقترح ما زال مسودة وتأجيل أشياء أصبح وصفها جاهزا لأنها قد تكون أقل أهمية أو صعبة التنفيذ. لذلك، نجد أن هذه المحركات تتضمن المعايير المتعارفة فقط.
</p>

<p>
	لترى الميزات التي تدعمها اللغة، انظر في هذه الصفحة <a href="https://kangax.github.io/compat-table/es6/" rel="external nofollow">https://kangax.github.io/compat-table/es6/</a> (يوجد الكثير من الميزات، فما زال لدينا الكثير لنتعلمه).
</p>

<h2>
	Babel
</h2>

<p>
	تفشل بعض المحركات في دعم بعض الشيفرات البرمجية عند استخدام ميزات اللغة الحديثة. فكما ذكرنا سابقا، ليست جميع الميزات مُضَمَّنة في كل مكان.
</p>

<p>
	هنا يأتي دور Babel لإصلاح الوضع.
</p>

<p>
	يُعد <a href="https://babeljs.io/" rel="external nofollow">Babel</a> مُفَسِّرًأ تحويليًا <a href="https://en.wikipedia.org/wiki/Source-to-source_compiler" rel="external nofollow">transpiler</a>، إذ يعيد كتابة شيفرة جافاسكربت حديثة بإصدار سابق.
</p>

<p>
	في الواقع، يوجد جزئين في Babel:
</p>

<ol>
<li>
		<strong>أولا: برنامج المُفَسِّر التحويلي (transpiler):</strong> يعيد كتابة الشيفرة. يُشَغله المطورون على أجهزتهم. يقوم يعيد البرنامج كتابة الشيفرة البرمجية كتابةً متوافقةً مع إصدار سابق للغة ثم يتم توصيل الكود للمستخدمين إلى الموقع. توفر مشاريع بناء الأنظمة الحديثة مثل <a href="http://webpack.github.io/" rel="external nofollow">webpack</a> الوسائل المناسبة لتشغيل المُفَسِّرالتحويلي (transpiler) تلقائيا مع كل تغيير ِللشيفرة البرمجية ما يجعل الاندماج في عملية التطوير أسهل.
	</li>
	<li>
		<strong>ثانيا: برنامج لتعويض نقص دعم المتصفحات (Polyfills)</strong>: قد تتضمن ميزات اللغة الجديدة بعض الوظائف المدمجة وهياكل الجُمَل. يعيد المُفَسِّر التحويلي كتابة الشيفرة البرمجية مُحولًا هياكل الجمل إلى إصدارات أقدم، لكن يجب تضمين الوظائف المُدمجة الجديدة. تُعد جافاسكربت لغة ديناميكية للغاية، وقد تضيف/تعدل السكريبتات أي دالة حتى تتعامل وفقا للمعايير الحديثة.
	</li>
</ol>
<p>
	السكريبت الذي يضيف/يحدث دالة جديدة يسمى "polyfill"، معوِّض نقص الدعم. فهو يغطي الفجوة وإضافة المحتوى المفقود.
</p>

<p>
	برامج تعويض نقص دعم المتصفحات التي قد تثير اهتمامك:
</p>

<ul>
<li>
		<a href="https://github.com/zloirock/core-js" rel="external nofollow">core js</a> تدعم الكثير وتصمح بتضمين الميزات المُرادة فقط.
	</li>
	<li>
		<a href="http://polyfill.io/" rel="external nofollow">polyfill.io</a> هي خدمة تزود السكريبت بوسائل تعويض نقص دعم المتصفحات وفقا للميزات والمتصفح.
	</li>
</ul>
<p>
	لذلك، إن احتجت استخدام ميزات اللغة الحديثة، فمن المهم استخدام مُفَسِّرتحويلي و برنامج دعم نقص المتصفحات.
</p>

<h2>
	أمثلة من الشرح
</h2>

<p>
	معظم الأمثلة قابلة للتشغيل في مكانها مثل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9829_7" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="str">'Press the "Play" button in the upper-right corner to run'</span><span class="pun">);</span></pre>

<p>
	لن تعمل الأمثلة التي تستخدم جافاسكربت حديثة إلا في المتصفحات التي تدعمها.
</p>

<p>
	يُعد متصفح جوجل كروم الأكثر حداثة دوما مع ميزات اللغة الحديثة، من الجيد تشغيل العروض الحديثة بدون أي مُفَسِّرتحويلي. تعمل العديد من المتصفحات الأخرى المُحدَّثة جيدا.
</p>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/polyfills" rel="external nofollow">Polyfills</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-r796/" rel="">الكائنات</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%A7%D9%84%D8%A2%D9%84%D9%8A-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-mocha-r794/" rel="">الاختبار الآلي باستخدام mocha</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">795</guid><pubDate>Thu, 30 Jan 2020 17:38:28 +0000</pubDate></item><item><title>&#x627;&#x644;&#x627;&#x62E;&#x62A;&#x628;&#x627;&#x631; &#x627;&#x644;&#x622;&#x644;&#x64A; &#x644;&#x634;&#x64A;&#x641;&#x631;&#x627;&#x62A; &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; mocha</title><link>https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%A7%D9%84%D8%A2%D9%84%D9%8A-%D9%84%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-mocha-r794/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/24.jpg.92ecbe91d675664c9dd1aac883ad2e7b.jpg" /></p>

<p>
	يُستخدَم الاختبار الآلي في الكثير من المهام، كما يستخدم بكثرة في المشاريع الحقيقية.
</p>

<h2>
	لم نحتاج الاختبارات؟
</h2>

<p>
	عند كتابة دالة، يمكننا تخيل ما يجب أن تقوم به: ما هي المعاملات التي تعطي نتائج معينة. يمكننا فحص الدالة أثناء التطوير من خلال تشغيلها وموازنة مخرجاتها مع ما هو متوقع. مثلا يمكننا القيام بذلك في الطرفية.
</p>

<p>
	إن كان هناك خطأ، فإننا نُصلِح الشيفرة البرمجية، ونُعيد تشغيلها، ونفحص النتائج. وهكذا حتى تصبح صحيحة. لكن هذه الطريقة «إعادة التشغيل» غير مثالية.
</p>

<p>
	<strong>عند اختبار شيفرة برمجية عن طريق إعادة التشغيل اليدوية، فمن السهل نسيان شيئٍ ما.</strong>
</p>

<p>
	على سبيل المثال، عند إنشاء الدالة <code>f</code>. نكتب فيها بعض الشيفرات البرمجية، ثم نَفحصها: "<code>f(1)‎</code>" تعمل لكن "<code>f(2)‎</code>" لا تعمل. صلِح الشيفرة حتى تعمل "<code>f(2)‎</code>". ثم تبدو الدالة كأنها مكتملة، لكننا ننسى إعادة اختبار "<code>f(1)‎</code>" مما قد يؤدي إلى خطأ.
</p>

<p>
	هذا الأمر وارد بكثرة. فعند تطوير أي شيء، نُبقِي العديد من الاحتمالات في الحسبان. لكنه من الصعب توقع أن يختبر المبرمج جميع هذه الحالات يدويا بعد كل تغيير، فيصبح من السهل إصلاح شيء ما وإفساد شيء آخر.
</p>

<p>
	<strong>يعني الاختبار الآلي أن الاختبارات تُكتب مستقلة، بالإضافة إلى الشيفرة البرمجية. تشغِّل هذه الاختبارات الدوال بعدة طرق وتوازنها مع النتائج المتوقعة.</strong>
</p>

<h2>
	التطوير المستند إلى السلوك
</h2>

<p>
	لنبدأ بتقنية تسمى <a href="http://en.wikipedia.org/wiki/Behavior-driven_development" rel="external nofollow">التطوير المستند إلى السلوك Behavior Driven Development</a> أو كاختصار BDD.
</p>

<p>
	<strong>هذه التقنية BDD هي 3 في 1: اختبارات وتوثيق وامثلة.</strong>
</p>

<p>
	سنجرب حالة تطوير عملية لفهم BDD.
</p>

<h2>
	تطوير الدالة "pow": الوصف
</h2>

<p>
	لنفترض أننا نريد إنشاء الدالة <code>pow(x, n)‎</code> التي ترفع الأساس <code>x</code> إلى القوة <code>n</code>. مع الأخذ بالحسبان أن <code>n≥0</code>. هذه المهمة هي مجرد مثال: المعامل <code>**</code> يقوم بهذه العملية في JavaScript، لكننا نركز هنا على تدفق التطوير الذي يمكن تطبيقه على مهام أكثر تعقيدا.
</p>

<p>
	يمكننا تخيل ووصف ما يجب أن تقوم به الدالة <code>pow</code> قبل إنشاء شيفرتِها البرمجية. هذا الوصف يُسمى "specification" أو باختصار "spec" ويحتوي على وصف حالات الاستخدام بالإضافة إلى اختبارات لهذه الحالات كالتالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_6" style="">
<span class="pln">describe</span><span class="pun">(</span><span class="str">"pow"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  it</span><span class="pun">(</span><span class="str">"raises to n-th power"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">),</span><span class="pln"> </span><span class="lit">8</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">

</span><span class="pun">});</span></pre>

<p>
	تحتوي المواصفات على 3 أجزاء رئيسية كما ترى في الأعلى:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_8" style="">
<span class="pln">describe</span><span class="pun">(</span><span class="str">"title"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">})</span></pre>

<p>
	ماهي الوظيفة التي نصفها، في هذه الحالة، نحن نصف الدالة <code>pow</code>. تستخدم بواسطة العاملين- أجزاء <code>it</code>.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_10" style="">
<span class="pln">it</span><span class="pun">(</span><span class="str">"use case description"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">})</span></pre>

<p>
	نصف (نحن بطريقة مقروءة للبشر) حالة الاستخدام المخصصة في عنوان <code>it</code>، والمعامل الآخر عبارة عن دالة تفحص هذه الدالة.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_14" style="">
<span class="pln">assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">value1</span><span class="pun">,</span><span class="pln"> value2</span><span class="pun">)</span></pre>

<p>
	الشيفرة البرمجية بداخل <code>it</code> يجب أن تُنَفَّذ بدون أخطاء في حال كان التنفيذ صحيحًا.
</p>

<p>
	تستخدم الدوال <code>assert.*</code> لِفحص ما إن كانت الدالة <code>pow</code> تعمل بالشكل المتوقع أم لا. تستخدم إحدى هذه الدوال في هذا المثال - <code>assert.equal</code>، والتي توازن معاملَين وتُرجِع خطأ في حال عدم تساويهما. في المثال تفحص هذه الدالة إن كانت نتيجة تنفيذ الدالة <code>pow(2, 3)‎</code> تساوي <code>8</code>. كما يوجد العديد من أنواع التحقق والمقارنة والتي سنُضيفها لاحقا.
</p>

<p>
	يمكن تنفيذ الوصف، وسينفِّذ الفحص الموجود بداخل <code>it</code> كما سنرى لاحقا.
</p>

<h2>
	تدفق التطوير
</h2>

<p>
	يبدو تدفق التطوير غالبا كما يلي:
</p>

<ol>
<li>
		يُكتب الوصف الأولي مع فحص للوظيفة الرئيسية.
	</li>
	<li>
		يُنشَئ تنفيذ أولي.
	</li>
	<li>
		للتأكد من صحة عمل التنفيذ، نُشَغِّل إطار التقييم <a href="http://mochajs.org/" rel="external nofollow">Mocha</a> الذي يُشَغِّل الوصف. ستظهر أخطاء في حال عدم اكتمال الوظائف. نُصحح الأخطاء حتى يصبح كل شيء صحيحًا.
	</li>
	<li>
		هكذا أصبح لدينا تنفيذ مبدئي يعمل كالمطلوب بالإضافة إلى فحصه.
	</li>
	<li>
		نضيف المزيد من حالات الاستخدام للوصف، ربما بعض هذه الميزات ليس مضمنا في التنفيذ بعد. حينها يبدأ الاختبار بالفشل.
	</li>
	<li>
		عُد للخطوة 3 وحدِّث التنفيذ إلى أن تختفي كل الأخطاء.
	</li>
	<li>
		كرر الخطوات 3-6 حتى تجهز كل الوظائف.
	</li>
</ol>
<p>
	إذا، تُعد عملية التطوير تكرارية. نكتب الوصف، ننفذه، نتأكد من اجتياز التنفيذ للفحص، ثم نكتب المزيد من الاختبارات، نتأكد من صحة عملها. حتى نحصل على تنفيذ صحيح مع اختباراته في الأخير.
</p>

<p>
	لنُجرب تدفق التطوير هذا على حالتنا العملية.
</p>

<p>
	الخطوة 1 أصبحت جاهزة: لدينا وصفًا مبدئيًّا للدالة <code>pow</code>. الآن وقبل التنفيذ، لِنستخدم بعض مكاتب جافاسكربت لتشغيل الاختبار حتى نتأكد من إن كانت تعمل (لن تعمل).
</p>

<h2>
	المواصفات أثناء التنفيذ
</h2>

<p>
	سنستخدم في هذا الشرح مكاتب جافاسكربت التالية للاختبار:
</p>

<ul>
<li>
		<a href="http://mochajs.org/" rel="external nofollow">Mocha</a> - الإطار الرئيسي: يوفر دوال الفحص الأكثر استخدامًا ما يشمل <code>describe</code> و <code>it</code> بالإضافة إلى الدوال الرئيسية التي تُشَغِّل الاختبار.
	</li>
	<li>
		<a href="http://chaijs.com/" rel="external nofollow">Chai</a> - المكتبة المحتوية على دوال تأكيدية. تتيح لنا استخدام العديد من هذه الدوال، نحتاج الآن <code>assert.equal</code> فقط.
	</li>
	<li>
		<a href="http://sinonjs.org/" rel="external nofollow">Sinon</a> - مكتبة للتجسس على الدوال، ومحاكاة الدوال المدمجة، والمزيد؛ سنحتاج هذه المكتبة لاحقا.
	</li>
</ul>
<p>
	تُعد هذه المكاتب مفيدة للاختبار في كل من المتصفح والخادم. سنأخذ بعين الاعتبار هنا جهة المتصفح. صفحة HTML كاملة مع هذه المكاتب ووصف الدالة <code>pow</code>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1877_16" style="">
<span class="pln">    </span><span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">
    </span><span class="tag">&lt;html&gt;</span><span class="pln">
    </span><span class="tag">&lt;head&gt;</span><span class="pln">
      </span><span class="com">&lt;!-- add mocha css, to show results --&gt;</span><span class="pln">
      </span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.css"</span><span class="tag">&gt;</span><span class="pln">
      </span><span class="com">&lt;!-- add mocha framework code --&gt;</span><span class="pln">
      </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
      </span><span class="tag">&lt;script&gt;</span><span class="pln">
    mocha</span><span class="pun">.</span><span class="pln">setup</span><span class="pun">(</span><span class="str">'bdd'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// minimal setup</span><span class="pln">
      </span><span class="tag">&lt;/script&gt;</span><span class="pln">
      </span><span class="com">&lt;!-- add chai --&gt;</span><span class="pln">
      </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
      </span><span class="tag">&lt;script&gt;</span><span class="pln">
    </span><span class="com">// chai has a lot of stuff, let's make assert global</span><span class="pln">
    let assert </span><span class="pun">=</span><span class="pln"> chai</span><span class="pun">.</span><span class="pln">assert</span><span class="pun">;</span><span class="pln">
      </span><span class="tag">&lt;/script&gt;</span><span class="pln">
    </span><span class="tag">&lt;/head&gt;</span><span class="pln">

    </span><span class="tag">&lt;body&gt;</span><span class="pln">

    </span><span class="tag">&lt;script&gt;</span><span class="pln">
    </span><span class="kwd">function</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">/* function code is to be written, empty now */</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="tag">&lt;/script&gt;</span><span class="pln">

    </span><span class="com">&lt;!-- the script with tests (describe, it...) --&gt;</span><span class="pln">
    </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"test.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">

    </span><span class="com">&lt;!-- the element with id="mocha" will contain test results --&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"mocha"</span><span class="tag">&gt;&lt;/div&gt;</span><span class="pln">

    </span><span class="com">&lt;!-- run tests! --&gt;</span><span class="pln">
    </span><span class="tag">&lt;script&gt;</span><span class="pln">
    mocha</span><span class="pun">.</span><span class="pln">run</span><span class="pun">();</span><span class="pln">
    </span><span class="tag">&lt;/script&gt;</span><span class="pln">
    </span><span class="tag">&lt;/body&gt;</span><span class="pln">

    </span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	يمكن تقسيم الصفحة إلى 5 أجزاء:
</p>

<ol>
<li>
		<code>&lt;head&gt;</code> - لإضافة مكاتب وأنماط للاختبارات.
	</li>
	<li>
		<code>&lt;script&gt;</code> يحتوي على الدالة التي سيتم اختبارها، في هذا المثال الشيفرة البرمجية للدالة <code>pow</code>.
	</li>
	<li>
		الاختبار - عبارة عن سكريبت خارجي في هذا المثال <code>test.js</code> يحتوي على <code>describe("pow", ...)‎</code> الموضح سابقا.
	</li>
	<li>
		عنصر HTML ‏<code>&lt;div id="mocha"‎&gt;</code> والذي سيُستخدم بواسطة Mocha لعرض النتائج.
	</li>
	<li>
		يتم بدء الاختبارات باستخدام الأمر <code>mocha.run()‎</code>.
	</li>
</ol>
<p>
	النتائج:
</p>

<p style="text-align: center;">
	<iframe class="code-result__iframe" data-trusted="1" style="height:250px" src="https://en.js.cx/article/testing-mocha/pow-1/"></iframe>
</p>

<p>
	يفشل الاختبار ويظهر خطأ في الوقت الحالي. يُعد هذا منطقيا: فالدالة <code>pow</code> ما زالت فارغة، فإن <code>pow(2,3)‎</code> تُرجع <code>undefined</code> بدلا من <code>8</code>.
</p>

<p>
	لاحظ أن بإمكانك تشغيل أكثر من اختبار مختلف مستقبلا، فهناك مُشغلات عالية المستوى مثل <a href="https://karma-runner.github.io/" rel="external nofollow">karma</a> وغيرها.
</p>

<h2>
	التنفيذ الأولي
</h2>

<p>
	لنقم بتنفيذ مبسط للدالة <code>pow</code> حتى تعمل الاختبارات:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_18" style="">
<span class="kwd">function</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">8</span><span class="pun">;</span><span class="pln"> </span><span class="com">// :) we cheat!</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الآن ستعمل…
</p>

<p style="text-align: center;">
	<iframe class="code-result__iframe" data-trusted="1" style="height:250px" src="https://en.js.cx/article/testing-mocha/pow-min/"></iframe>
</p>

<h2>
	تطوير الوصف
</h2>

<p>
	ما قمنا به هو غش فقط، لا تعمل الدالة كالمطلوب: إن قمنا بحساب <code>pow(3,4)‎</code> فسنحصل على قيمة غير صحيحة، لكنها ستجتاز الاختبارات.
</p>

<p>
	هذه الحالة غير عملية، وتحدث بكثرة. الدالة تتجاوز الاختبارات لكن آلية عملها خاطئة. هذا يعني أن الوصف غير مثالي. ونحتاج لإضافة المزيد من حالات استخدام الدالة إليه.
</p>

<p>
	لنضف اختبارًا آخر للتأكد ما إن كان <code>pow(3, 4) = 81</code>.
</p>

<p>
	يمكنُنا اختيار إحدى الطريقتين لتنظيم الاختبارات:
</p>

<ol>
<li>
		الخيار الأول - إضافة <code>assert</code> إلى <code>it</code>:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_20" style="">
<span class="pln">describe</span><span class="pun">(</span><span class="str">"pow"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  it</span><span class="pun">(</span><span class="str">"raises to n-th power"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">),</span><span class="pln"> </span><span class="lit">8</span><span class="pun">);</span><span class="pln">
    assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">),</span><span class="pln"> </span><span class="lit">81</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">

</span><span class="pun">});</span></pre>

<ol start="2">
<li>
		الخيار الآخر - عمل اختبارين:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_22" style="">
<span class="pln">describe</span><span class="pun">(</span><span class="str">"pow"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  it</span><span class="pun">(</span><span class="str">"2 raised to power 3 is 8"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">),</span><span class="pln"> </span><span class="lit">8</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">

  it</span><span class="pun">(</span><span class="str">"3 raised to power 3 is 27"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">),</span><span class="pln"> </span><span class="lit">27</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">

</span><span class="pun">});</span></pre>

<p>
	يختلف المبدئ في أنه عند وجود خطأ في <code>assert</code>، فإن <code>it</code> تتوقف عن العمل. لذا ففي الخيار الأول عند فشل <code>assert</code> الأولى فلن نرى مخرجات <code>assert</code> الأخرى. يُعد الخيار الثاني أفضل للحصول على المزيد من المعلومات حول ما يحدث بعمل اختبارين منفصلين. بالإضافة إلى وجود قاعدة أخرى من الجيد اتباعها.
</p>

<p>
	<strong>كل اختبار يفحص شيئًا واحدًا فقط.</strong>
</p>

<p>
	إن وجدنا اختبارًا يفحص شيئين مختلفين فمن الأفضل فصلُهما إلى اختبارين. لنكمل باستخدام الخيار الثاني.
</p>

<p>
	النتائج:
</p>

<p style="text-align: center;">
	<iframe class="code-result__iframe" data-trusted="1" style="height:250px" src="https://en.js.cx/article/testing-mocha/pow-2/"></iframe>
</p>

<p>
	سيفشل الاختبار الثاني كَالمتوقع. فَالدالة تُرجع دوما <code>8</code>، بينما تتوقع الدالة <code>assert</code> النتيجة <code>27</code>.
</p>

<h2>
	تطوير التنفيذ
</h2>

<p>
	لنكتب شيئا أكثر واقعية لاجتياز الاختبارات:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_24" style="">
<span class="kwd">function</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let result </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">

  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    result </span><span class="pun">*=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	للتأكد من صحة عمل الدالة K نختبرها لأكثر من قيمة. يمكننا القيام بذلك باستخدام الحلقة <code>for</code> بدلا من تكرار <code>it</code> يدويا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_26" style="">
<span class="pln">describe</span><span class="pun">(</span><span class="str">"pow"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  </span><span class="kwd">function</span><span class="pln"> makeTest</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    let expected </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">*</span><span class="pln"> x </span><span class="pun">*</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    it</span><span class="pun">(`</span><span class="pln">$</span><span class="pun">{</span><span class="pln">x</span><span class="pun">}</span><span class="pln"> in the power </span><span class="lit">3</span><span class="pln"> is $</span><span class="pun">{</span><span class="pln">expected</span><span class="pun">}`,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">),</span><span class="pln"> expected</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> x </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> x</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    makeTest</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">});</span></pre>

<p>
	النتيجة:
</p>

<p style="text-align: center;">
	<iframe class="code-result__iframe" data-trusted="1" style="height:250px" src="https://en.js.cx/article/testing-mocha/pow-3/"></iframe>
</p>

<h2>
	دالة describe متداخلة
</h2>

<p>
	سنضيف المزيد من الاختبارات، لكن، قبل ذلك لاحظ أنه يجب جمع الدالة المساعدة <code>makeTest</code> والدالة <code>for</code>. لن نَحتاج لاستخدام <code>makeTest</code> في باقي الاختبارات، نحتاجها فقط في <code>for</code>: لأن وظيفتهُما العامة هي فحص كيف ترفع الدالة <code>pow</code> قيمة ما إلى قوة معينة.
</p>

<p>
	يتم جمع الدالتين باستخدام الدالة <code>describe</code> المتداخلة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_28" style="">
<span class="pln">describe</span><span class="pun">(</span><span class="str">"pow"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  describe</span><span class="pun">(</span><span class="str">"raises x to power 3"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    </span><span class="kwd">function</span><span class="pln"> makeTest</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      let expected </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">*</span><span class="pln"> x </span><span class="pun">*</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
      it</span><span class="pun">(`</span><span class="pln">$</span><span class="pun">{</span><span class="pln">x</span><span class="pun">}</span><span class="pln"> in the power </span><span class="lit">3</span><span class="pln"> is $</span><span class="pun">{</span><span class="pln">expected</span><span class="pun">}`,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">),</span><span class="pln"> expected</span><span class="pun">);</span><span class="pln">
      </span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> x </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> x</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      makeTest</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

  </span><span class="pun">});</span><span class="pln">

  </span><span class="com">// ... more tests to follow here, both describe and it can be added</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	تُعرِّف <code>describe</code> الداخلية مجموعة فرعية جديدة من الاختبارات. يمكن ملاحظة الإزاحة في المخرجات:
</p>

<p style="text-align: center;">
	<iframe class="code-result__iframe" data-trusted="1" style="height:250px" src="https://en.js.cx/article/testing-mocha/pow-4/"></iframe>
</p>

<p>
	يمكننا إضافة المزيد من دوال <code>it</code> و <code>describe</code> في الطبقة العلوية مع دوال مساعدة لها، هذه الدوال لن ترى الدالة <code>makeTest</code>.
</p>

<p>
	<strong><code>before/after</code> و <code>beforeEach/afterEach</code></strong>
</p>

<p>
	يمكننا إعداد دوال <code>before/after</code> التي تُنَفَّذ قبل/بعد تنفيذ الاختبارات، كما يمكننا استخدام <code>beforeEach/afterEach</code> قبل/بعد كل <code>it</code>.
</p>

<p>
	على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_30" style="">
<span class="pln">describe</span><span class="pun">(</span><span class="str">"test"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  before</span><span class="pun">(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"Testing started – before all tests"</span><span class="pun">));</span><span class="pln">
  after</span><span class="pun">(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"Testing finished – after all tests"</span><span class="pun">));</span><span class="pln">

  beforeEach</span><span class="pun">(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"Before a test – enter a test"</span><span class="pun">));</span><span class="pln">
  afterEach</span><span class="pun">(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"After a test – exit a test"</span><span class="pun">));</span><span class="pln">

  it</span><span class="pun">(</span><span class="str">'test 1'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> alert</span><span class="pun">(</span><span class="lit">1</span><span class="pun">));</span><span class="pln">
  it</span><span class="pun">(</span><span class="str">'test 2'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> alert</span><span class="pun">(</span><span class="lit">2</span><span class="pun">));</span><span class="pln">

</span><span class="pun">});</span></pre>

<p>
	تسلسل التنفيذ سيكون كالتالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_32" style="">
<span class="typ">Testing</span><span class="pln"> started </span><span class="pun">–</span><span class="pln"> before all tests </span><span class="pun">(</span><span class="pln">before</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Before</span><span class="pln"> a test </span><span class="pun">–</span><span class="pln"> enter a test </span><span class="pun">(</span><span class="pln">beforeEach</span><span class="pun">)</span><span class="pln">
</span><span class="lit">1</span><span class="pln">
</span><span class="typ">After</span><span class="pln"> a test </span><span class="pun">–</span><span class="pln"> exit a test   </span><span class="pun">(</span><span class="pln">afterEach</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Before</span><span class="pln"> a test </span><span class="pun">–</span><span class="pln"> enter a test </span><span class="pun">(</span><span class="pln">beforeEach</span><span class="pun">)</span><span class="pln">
</span><span class="lit">2</span><span class="pln">
</span><span class="typ">After</span><span class="pln"> a test </span><span class="pun">–</span><span class="pln"> exit a test   </span><span class="pun">(</span><span class="pln">afterEach</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Testing</span><span class="pln"> finished </span><span class="pun">–</span><span class="pln"> after all tests </span><span class="pun">(</span><span class="pln">after</span><span class="pun">)</span></pre>

<p>
	تستخدم <code>beforeEach/afterEach</code> و <code>before/after</code> غالبا لتنفيذ الخطوات الأولية، العدادات التي تُخرج 0 أو للقيام بشيء ما بين الاختبارات أو مجموعة اختبارات.
</p>

<h2>
	توسيع الوصف
</h2>

<p>
	أصبحت الوظيفة الرئيسية للدالة <code>pow</code> مكتملة. تم تجهيز الدورة الأولى من التطوير. الآن يمكننا الاحتفال بالانتهاء من ذلك وبدء تطوير الدالة.
</p>

<p>
	كما ذكرنا مسبقا، فإن الدالة <code>pow(x, n)‎</code> ستتعامل مع أرقام موجبة فقط <code>n</code>. تُرجع دوال جافاسكربت دائما <code>NaN</code> عند وجود خطأ حسابي. لنقم بهذا الأمر مع قيم <code>n</code>.
</p>

<p>
	أولا، نضيف هذا إلى الوصف:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_34" style="">
<span class="pln">describe</span><span class="pun">(</span><span class="str">"pow"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  </span><span class="com">// ...</span><span class="pln">

  it</span><span class="pun">(</span><span class="str">"for negative n the result is NaN"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    assert</span><span class="pun">.</span><span class="pln">isNaN</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">));</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">

  it</span><span class="pun">(</span><span class="str">"for non-integer n the result is NaN"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    assert</span><span class="pun">.</span><span class="pln">isNaN</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1.5</span><span class="pun">));</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">

</span><span class="pun">});</span></pre>

<p>
	النتائج مع الاختبارات الجديدة:
</p>

<p style="text-align: center;">
	<iframe class="code-result__iframe" data-trusted="1" style="height:530px" src="https://en.js.cx/article/testing-mocha/pow-nan/"></iframe>
</p>

<p>
	تفشل الاختبارات المُضافة مؤخرا وذلك لأن التنفيذ لا يدعمها. هكذا هي الطريقة التي يعمل بها BDD: نبدأ بكتابة الاختبارات التي نعلم بأنها ستفشل ثم نكتب التنفيذ الخاص بها.
</p>

<p>
	<strong>دوال تأكيد أخرى</strong>
</p>

<p>
	لاحظ أن الدالة <code>assert.isNaN</code>: تفحص وجود القيمة <code>NaN</code>.
</p>

<p>
	يوجد المزيد من دوال التأكيد في <a href="http://chaijs.com/" rel="external nofollow">Chai</a>، مثلا:
</p>

<ul>
<li>
		<code>assert.equal(value1, value2)‎</code> - تفحص التساوي <code>value1 == value2</code>.
	</li>
	<li>
		<code>assert.strictEqual(value1, value2)‎</code> - تفحص التساوي التام <code>value1 === value2</code>.
	</li>
	<li>
		<code>assert.notEqual</code>، <code>assert.notStrictEqual</code> - تفحص عكس الدالتين أعلاه.
	</li>
	<li>
		<code>assert.isTrue(value)‎</code> - تفحص أن <code>value === true</code>.
	</li>
	<li>
		<code>assert.isFalse(value)‎</code> - تفحص أن <code>value === false</code>.
	</li>
	<li>
		يمكنك قراءة باقي الدوال في <a href="http://chaijs.com/api/assert/" rel="external nofollow">التوثيق</a>
	</li>
</ul>
<p>
	لذا، يجب أن نضيف بعض الأسطر للدالة <code>pow</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_36" style="">
<span class="kwd">function</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">NaN</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Math</span><span class="pun">.</span><span class="pln">round</span><span class="pun">(</span><span class="pln">n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">NaN</span><span class="pun">;</span><span class="pln">

  let result </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">

  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    result </span><span class="pun">*=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الآن أصبحت تعمل وتَجتاز جميع الاختبارات:
</p>

<p style="text-align: center;">
	<iframe class="code-result__iframe" data-trusted="1" style="height:300px" src="https://en.js.cx/article/testing-mocha/pow-full/"></iframe>
</p>

<h2>
	الخلاصة
</h2>

<p>
	يكون الوصف في البداية في BDD، ثم يأتي التنفيذ. فنحصل في الأخير على كل من الوصف والشيفرة البرمجية.
</p>

<p>
	يمكن استخدام الوصف بثلاث طرق:
</p>

<ol>
<li>
		<strong>اختبارات</strong> - تضمن صحة عمل الشيفرة البرمجية.
	</li>
	<li>
		<strong>توثيق</strong> - توضح العناوين في <code>describe</code> و<code>it</code> وظيفة الدالة.
	</li>
	<li>
		<strong>أمثلة</strong> - تُعد الاختبارات أمثلة فعالة تعرض كيف يمكن استخدام الدالة.
	</li>
</ol>
<p>
	يمكننا تطوير، تغيير، أو إعادة كتابة دالة من الصفر من خلال الوصف مع ضمان صحة عملها. يعد هذا الأمر مهمًا خاصة في المشاريع الكبيرة عند استخدام دالة في عدة أماكن. فعند تغيير هذه الدالة، يكون من الصعب التحقق من صحة عملها يدويًا في كل مكان.
</p>

<p>
	يوجد خيارين بدون اختبارات:
</p>

<ol>
<li>
		تنفيذ التغيير بغض النظر عن النتائج. هكذا قد نواجه الكثير من الأخطاء عند الفحص اليدوي.
	</li>
	<li>
		يتجنب المطورون تحديث الشيفرة عند توقع حدوث أخطاء فادحة وعدم وجود اختبارات لفحص هذه الأخطاء فتبقى الشيفرة البرمجية بدون تحديث.
	</li>
</ol>
<p>
	<strong>يساعد الفحص الآلي على تجنب هذه المشاكل!</strong>
</p>

<p>
	إن كان المشروع مليئا بالاختبارات، فلن يكون هناك أي مشكلة إطلاقا. فبعد أي تغيير يمكننا تنفيذ الاختبارات لنرى العديد من التحقيقات أجريت في غضون ثوانٍ.
</p>

<p>
	<strong>علاوة على ذلك، الشيفرة البرمجية المختبرة جيدا تكون بهيكل أفضل.</strong>
</p>

<p>
	منطقيا، لأن الشيفرة البرمجية المختبرة سهلة التعديل والتطوير. مع وجود سبب آخر أيضا. يجب أن تكون الشيفرة البرمجية منظمة من أجل كتابة اختبار بحيث يكون لدى كل دالة وظيفة رئيسية موصوفة، ومدخلات ومخرجات معروفة جيدا. ذلك يعني 1 هيكلة جيدة منذ البداية.
</p>

<p>
	لا يكون الأمر بهذه السهولة في الواقع. ففي بعض الأحيان يكون من الصعب كتابة وصف للدالة قبل شيفرتها البرمجية لأن سلوكها لا يكون واضحًا بعد. لكن عموما، كتابة الاختبارات يجعل التطوير أسرع وأكثر استقرارًا.
</p>

<p>
	ستواجه الكثير من المهام التي تتضمن ذلك لاحقا في الشرح. فسترى المزيد من الأمثلة العملية. يتطلب كتابة الاختبارات معرفة جيدة بِجافاسكربت. لكننا في بداية تعلمها. فلترتيب كل شيء، لست مطالبًا بكتابة الاختبارات في الوقت الحالي، لكن يجب أن تكون قادرًا على قرائتها حتى إن كانت معقدة أكثر قليلا مما تم شرحه هنا.
</p>

<h2>
	تمارين
</h2>

<h3>
	ما الخطأ في الاختبار التالي؟
</h3>

<p class="task__importance">
	الأهمية: 5
</p>

<p>
	ما الخطأ في الاختبار للدالة <code>pow</code> أدناه؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_38" style="">
<span class="pln">it</span><span class="pun">(</span><span class="str">"Raises x to the power n"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">

  let result </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
  assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">),</span><span class="pln"> result</span><span class="pun">);</span><span class="pln">

  result </span><span class="pun">*=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
  assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">),</span><span class="pln"> result</span><span class="pun">);</span><span class="pln">

  result </span><span class="pun">*=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
  assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">),</span><span class="pln"> result</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	الحل:
</p>

<div class="task__answer">
	<p>
		يوضح الاختبار أحد الإغراءات التي يواجهها المطور أثناء كتابة اختبار. ما لدينا الآن هو ثلاثة اختبارات، لكنها مرتبة كدالة واحدة تتضمن ثلاثة تأكيدات.
	</p>

	<p>
		تكون هذه الطريقة أسهل في بعض الأحيان، لكن إن وُجِد أي خطأ، فلن يكون من السهل معرفة سبب ذلك الخطأ. إن حدث خطأ ما أثناء تنفيذ شيفرة معقدة، فَسنحتاج لمعرفة قيم البيانات عند تلك النقطة. أي أننا سنحتاج لتنقيح الاختبار.
	</p>

	<p>
		من الأفضل تجزئة الاختبار إلى أجزاء <code>it</code> متعددة مع مدخلات ومخرجات محددة بوضوح كما يلي:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_40" style="">
<span class="pln">describe</span><span class="pun">(</span><span class="str">"Raises x to power n"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  it</span><span class="pun">(</span><span class="str">"5 in the power of 1 equals 5"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">),</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">

  it</span><span class="pun">(</span><span class="str">"5 in the power of 2 equals 25"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">),</span><span class="pln"> </span><span class="lit">25</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">

  it</span><span class="pun">(</span><span class="str">"5 in the power of 3 equals 125"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">),</span><span class="pln"> </span><span class="lit">125</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">
</span><span class="pun">});</span></pre>

	<p>
		بدلنا <code>it</code> مكان <code>describe</code> وبعدد من <code>it</code>. إن فشل شيء ما الآن فَسَنتمكن من رؤية البيانات. يمكننا أيضًا عزل اختبار واحد وتشغيلة في وضع مستقل باستخدام <code>it.only</code> بدلًا من <code>it</code>:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1877_42" style="">
<span class="pln">describe</span><span class="pun">(</span><span class="str">"Raises x to power n"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  it</span><span class="pun">(</span><span class="str">"5 in the power of 1 equals 5"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">),</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">

  </span><span class="com">// Mocha will run only this block</span><span class="pln">
  it</span><span class="pun">.</span><span class="pln">only</span><span class="pun">(</span><span class="str">"5 in the power of 2 equals 25"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">),</span><span class="pln"> </span><span class="lit">25</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">

  it</span><span class="pun">(</span><span class="str">"5 in the power of 3 equals 125"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    assert</span><span class="pun">.</span><span class="pln">equal</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">),</span><span class="pln"> </span><span class="lit">125</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">
</span><span class="pun">});</span></pre>
</div>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/testing-mocha" rel="external nofollow">Automated testing with mocha</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%AA%D8%B9%D9%88%D9%8A%D8%B6-%D9%86%D9%82%D8%B5-%D8%AF%D8%B9%D9%85-%D8%A7%D9%84%D9%85%D8%AA%D8%B5%D9%81%D8%AD%D8%A7%D8%AA-%D9%84%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r795/" rel="">تعويض نقص دعم المتصفحات لجافاسكربت</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D8%B4%D9%8A%D9%81%D8%B1%D8%A9-%D8%A7%D9%84%D9%86%D9%8A%D9%86%D8%AC%D8%A7-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r793/" rel="">شيفرة النينجا البرمجية</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">794</guid><pubDate>Tue, 04 Feb 2020 13:09:00 +0000</pubDate></item><item><title>&#x645;&#x641;&#x647;&#x648;&#x645; &#x634;&#x64A;&#x641;&#x631;&#x629; &#x627;&#x644;&#x646;&#x64A;&#x646;&#x62C;&#x627; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x64A;&#x629;</title><link>https://academy.hsoub.com/programming/javascript/%D9%85%D9%81%D9%87%D9%88%D9%85-%D8%B4%D9%8A%D9%81%D8%B1%D8%A9-%D8%A7%D9%84%D9%86%D9%8A%D9%86%D8%AC%D8%A7-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r793/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/23.jpg.860d8f47a5b17f2d4a19f8a41c906769.jpg" /></p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		التعلم بدون تفكير يضيع الجهد، والتفكير بدون تعلُّم مجرد مخاطرة
	</p>
</blockquote>

<p>
	استخدم مبرمجو النينجا القدماء هذه الحيل لشحذ عقول مراجعو الشيفرات البرمجية. يبحث معلمو مراجعة الشيفرات البرمجية عن هذه الحيل في مهام الاختبار. أحيانًا، يستخدم المبرمجون المبتدئون هذه الحيل بصورة أفضل من مبرمجي النينجا. اقرأها جيدا ثم حدد من أنت - نينجا، مبتدئ، أو مُراجِع شيفرات برمجية؟
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		موازنة تم اكتشافها
	</p>

	<p>
		يحاول الكثيرون اتباع طرق النينجا ولكن لا يفلح إلا القليل.
	</p>
</blockquote>

<h2>
	البلاغة في الإيجاز
</h2>

<p>
	اختصر الشيفرة البرمجية قدر الإمكان. أظهر مدى ذكائك. فلتَقُدكَ ميزات اللغة الخفية.
</p>

<p>
	مثال: ألق نظرة على العامل الثلاثي التالي <code>'?'</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8224_6" style="">
<span class="com">// مأخوذ من مكتبة جافاسكربت شهيرة</span><span class="pln">
i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">?</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="typ">Math</span><span class="pun">.</span><span class="pln">max</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> len </span><span class="pun">+</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> i </span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span></pre>

<p>
	إن كتبت بهذه الطريقة، فإن أي مطور آخر يقرأ هذا السطر ويحاول فهم ما هي قيمة <code>i</code> سيأتي إليك باحثًا عن الإجابة. أخبرهم في ذلك الحين أن الاختصار أفضل دومًا ودلهم على طريق النينجا.
</p>

<h2>
	المتغيرات ذات الحرف الواحد
</h2>

<p>
	استخدام المتغيرات ذات الحرف الواحد هي طريقة أخرى لكتابة الشيفرة البرمجية بصورة أسرع مثل <code>a</code>، أو <code>b</code>، أو <code>c</code>. يختبئ المتغير ذو الحرف الواحد داخل الشيفرة البرمجية كما يختبئ النينجا الحقيقي في الغابة. لن يتمكن أي شخص من العثور عليه بسهولة باستخدام "البحث" المُدمج مع المحرر. حتى إن عثر شخص ما علبه فلن يفهم ما معنى المتغير <code>a</code> أو <code>b</code>.
</p>

<p>
	لكن، يوجد استثناء. مبرمج النينجا الحقيقي لن يستخدم المتغير <code>i</code> كعداد للحلقة <code>"for"</code>. سيستخدمه في أي مكان عدا هنا. يوجد العديد من الأحرف الغريبة لاستخدامها كعداد الحلقة بدلا منه مثل <code>x</code> أو <code>y</code>.
</p>

<p>
	متغير بحرف غريب عدادًا للحلقة يُعد مناسبا إن كانت الحلقة تمتد إلى صفحة أو صفحتين. فإن أتى شخص ما للتعمق في هذه الحلقة فلن يعرف أن المتغير <code>x</code> هو عدَّاد هذه الحلقة.
</p>

<h2>
	استخدم الاختصارات
</h2>

<p>
	إن كانت قوانين الفريق تمنع استخدام المتغيرات ذات الحرف الواحد أو المتغيرات الغامضة، اختصر أسماء المتغيرات.
</p>

<ul>
<li>
		<code>list</code> ‏← <code>lst</code>
	</li>
	<li>
		<code>userAgent</code> ‏← <code>ua</code>
	</li>
	<li>
		<code>browser</code> ‏← <code>brsr</code>
	</li>
	<li>
		وهكذا…
	</li>
</ul>
<p>
	سيفهم شخص فطن فقط الأسماء المستخدمة. حاول اختصار كل شيء. فقط شخص مؤهل يجب أن يُكمل تطوير شيفرتك البرمجية.
</p>

<h2>
	حلق عاليا واستخدم التجريد
</h2>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		المربع العظيم لا يحوي أي زوايا السفينة الأعظم تكتمل أخيرا، النغمة العظيمة نادرة الصوت الصورة العظيمة لا تحوي أي شكل
	</p>

	<p>
		تاو تي تشينغ
	</p>
</blockquote>

<p>
	حاول اختيار الكلمة الأكثر تجريدا عند اختيار اسم ما مثل <code>obj</code>، و <code>data</code>، و <code>value</code>، و <code>item</code>، و <code>elem</code> وهكذا.
</p>

<ul>
<li>
		<p>
			<strong>الاسم الأمثل لمتغير هو <code>data</code></strong>. استخدمه حيثما استطعت. فبالحقيقة، كل متغير يحتوي على بيانات "data". لكن، ماذا إن كان هناك متغير بالاسم <code>data</code> بالفعل؟ جرب الاسم <code>value</code>، فهو عالمي أيضا، فكل متغير يحتوي على قيمة.
		</p>
	</li>
	<li>
		<p>
			<strong>سمِّ المتغير حسب نوعه:</strong> <code>str</code>، <code>num</code>… جرب هذه الطريقة. قد يتساءل أي شخص مبتدئ حول إن كانت مثل هذه الأسماء مفيدة لمبرمج النينجا؟ بالفعل هي مفيدة. اسم المتغير يُخبر عن شيء ما. يدل اسم المتغير في هذه الطريقة عن نوع البيانات التي يحويها: نص، رقم أو أي نوع آخر. لكن عندما يحاول شخص آخر فهم الشيفرة البرمجية، سيُصدَم بعدم توفر معلومات كافية لفهمها! وسيفشل تمامًا في تعديل شيفرتِك البرمجية.
		</p>
	</li>
</ul>
<p>
	يمكن معرفة قيمة المتغير عبر تتبع الشيفرة البرمجية. لكن ما معنى المتغير؟ وماهو النص أو الرقم الذي يخزنة؟ لا يوجد طريقة لمعرفة ذلك بدون تأمل جيد!
</p>

<ul>
<li>
		<strong>لكن ماذا إن لم يكن هناك المزيد من هذه الأسماء؟</strong> فقط أضف رقمًا إليها مثل: <code>data1، item2، elem5</code>…
	</li>
</ul>
<h2>
	اختبار الملاحظة
</h2>

<p>
	يمكن لِمبرمج قوي الملاحظة فقط فهم شيفرتُك البرمجية. لكن، كيف تختبر ذلك؟
</p>

<p>
	<strong>إحدى الطرق هي استخدام متغيرات بأسماء متشابهة مثل <code>date</code> و <code>data</code>.</strong>
</p>

<p>
	اخلُط ما بين المتغيرين حيث يمكن ذلك. ستصبح قراءة شيفرة برمجية بهذه الطريقة مستحيلة. وعند وجود خطأ كتابي فسيَعلق القارئ لوقت طويل.
</p>

<h2>
	مرادفات ذكية
</h2>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		أصعب شيء هو العثور على قطة سوداء في غرفة مظلمة، خاصةً عند عدم وجود قطة! استخدام أسماء متشابهة لنفس الأشياء يجعل الحياة أكثر تشويقا ويُظهِر مدى إبداعك للجمهور.
	</p>
</blockquote>

<p>
	على سبيل المثال، لنأخذ بالحسبان بوادِئ الدوال. إن كانت الدالة تعرض رسالة على الشاشة، ابدأها ب <code>display…‎</code> مثل <code>displayMessage</code>. وإن كانت دالة أخرى تعرض شيئًا آخر على الشاشة مثل اسم المستخدم ابدأها ب <code>show…‎</code> مثل <code>showName</code>.
</p>

<p>
	اجعل من يقرأ الشيفرة يظن أن هناك اختلاف خفي بين الدوال بينما لا يوجد أي اختلاف. اتفق مع فريق مبرمجي النينجا: إن بدأ أحمد دالة العرض ب <code>display...‎</code> في شيفرته البرمجية، فيمكن لمحمد استخدام <code>render...‎</code> ويمكن لِأمل استخدام <code>paint...‎</code>. لاحظ كيف ستصبح الشيفرة البرمجية أكثر اختلافًا وتشويقًا.
</p>

<p>
	الآن إلى خدعة القبعة!
</p>

<p>
	استخدم نفس البادئة ِلدالتين مهمتين بوظيفتين مختلفتين!
</p>

<p>
	مثلا، الدالة "<code>printPage(page)‎</code>" ستستخدم طابعة، بينما الدالة "<code>printText(text)‎</code>" ستضع النص على الشاشة. هكذا تجعل القارئ يفكر جيدا بالدالة المُسماة <code>printMessage</code>: "أين تضع هذه الدالة الرسالة؟ إلى الطابعة أو على الشاشة؟". لجعل الأمر أوضح، يجب أن تضع الدالة "<code>printMessage(message)‎</code>" الرسالة في النافذة الجديدة! (وظيفة مهمة بطريقة مختلفة).
</p>

<h2>
	أعد استخدام الأسماء
</h2>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		عند تقسيم الكل، تحتاج الأجزاء إلى أسماء. يوجد بالفعل أسماء كافية للجميع. يجب أن تعرف متى تتوقف.
	</p>

	<p>
		تاو تي تشينغ
	</p>
</blockquote>

<p>
	ضع متغيرًا جديدًا عند الحاجة فقط. عوضا عن ذلك، أعد استخدام الأسماء الموجودة. اكتب قيمًا جديدة إلى هذه المتغيرات. وفي الدوال، حاول استخدام المتغيرات المُمَرَّرة إلى الدالة كمُعاملات. ستُصعِّب بهذه الطريقة معرفة ما في المتغير الآن. ومن أين أتى هذا المتغير أيضا. الغرض من هذه الطريقة هو تطوير حدس وذاكرة قارِئ الشيفرة البرمجية. سيحتاج الشخص ذو الحدس الضعيف إلى تحليل الشيفرة البرمجية سطرًا تلو الاخر وتَعقَّب التغييرات في كل جزء من أجزاء الشيفرة البرمجية.
</p>

<p>
	<strong>إحدى الطرق المتقدمة هي باستبدال قيمة متغير ما بمحتوى آخر مختلف تماما عن السابق خفية داخل حلقة أو دالة.</strong>
</p>

<p>
	على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8224_8" style="">
<span class="kwd">function</span><span class="pln"> ninjaFunction</span><span class="pun">(</span><span class="pln">elem</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// elem عشرون سطرًا من الشيفرة يتعامل مع المتغير</span><span class="pln">

  elem </span><span class="pun">=</span><span class="pln"> clone</span><span class="pun">(</span><span class="pln">elem</span><span class="pun">);</span><span class="pln">

  </span><span class="com">// elem عشرون سطرًا إضافيًا يتعامل الآن مع نسخة من المتغير</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سيتفاجئ المبرمج الآخر الذي يريد التعامل مع <code>elem</code> في الجزء الثاني من الدالة لأنه سيكتشف فقط أثناء التنفيذ والتعقب وبعد تفحص الشيفرة بأنه يتعامل مع <code>elem</code> بعد استنساخه!
</p>

<h2>
	الشرطة السفلية للمتعة
</h2>

<p>
	ضع الشرطات السفلية <code>_</code> و <code>__</code> قبل أسماء المتغيرات. مثل "<code>‎_name</code>" أو "<code>‎__value</code>". سيكون جيدا إن كنت أنت فقط من تعرف معنى ذلك، أو استخدمها للمتعة فقط دون معنى معين. أو استخدم معانٍ مختلفة في أماكن مختلفة.
</p>

<p>
	بهذا ترمي عصفورين بحجر. أولا، تصبح الشيفرة البرمجية أطول وأصعب للقراءة. ثانيا، سيأخذ القارئ وقتا لمعرفة معنى الشرطات السفلية.
</p>

<p>
	يضع مبرمج النينجا الذكي الشرطات السفلية في مكان معين من الشيفرة البرمجية ويتجنبها في أماكن أخرى. هذا يجعل الشيفرة البرمجية أكثر هشاشة ويزيد من احتمالية الخطأ المستقبلي.
</p>

<h2>
	اظهر حبك
</h2>

<p>
	أظهر للجميع مدى روعة المكونات التي تستخدمها! ستُبهِر الأسماء مثل <code>superElement</code>، <code>megaFrame</code>، و <code>niceItem</code> القارئ.
</p>

<p>
	يمكن كتابة: "<code>super..‎</code>"، و "<code>mega..‎</code>"، و"<code>nice..‎</code>" لكن بطريقة لا تُظهِر تفاصيلًا حول المعنى. قد يبحث القارئ عن معانِ خفية ويتأمل لساعة أو اثنتين من وقته.
</p>

<h2>
	داخِل المتغيرات الخارجية
</h2>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		عندما تكون في الضوء، لا يمكنك رؤية شيء في الظلام. عندما تكون في الظلام، يمكنك رؤية كل شيء في الضوء
	</p>

	<p>
		غوان ين زي
	</p>
</blockquote>

<p>
	استخدم أسماء المتغيرات نفسها داخل وخارج الدوال. ببساطة، لا حاجة لاختراع أسماء جديدة.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8224_10" style="">
<span class="pln">let user </span><span class="pun">=</span><span class="pln"> authenticateUser</span><span class="pun">();</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let user </span><span class="pun">=</span><span class="pln"> anotherValue</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">many lines</span><span class="pun">...</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
  </span><span class="pun">...</span><span class="pln"> </span><span class="com">// &lt;-- هنا user يريد مبرمجٌ ما التعامل مع المتغير</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سيفشل المبرمج الذي يقفز بِداخل الدالة <code>render</code> في ملاحظة أن هناك متغير <code>user</code> محلي يغطي على المتغير الخارجي.
</p>

<p>
	سيتعامل مع <code>user</code> مُعتبِرًا أنه المتغير الخارجي نفسه، وبذلك ستكون نتائج الدالة "<code>authenticateUser()‎</code>" غير متوقعة وسينجح الفخ.
</p>

<h2>
	آثار جانبية في كل مكان
</h2>

<p>
	يوجد بعض الدوال التي تبدو كأنها لا تقوم بشيء مثل، "<code>isReady()‎</code>"، و "<code>checkPermission()‎</code>"، و "<code>findTags()‎</code>" …إلخ يُتَوَقَّع أنها تقوم بعمليات حسابية، تُوجِد وتٌرجِع قيم البيانات بدون تغيير شيء خارج نطاقها. بمعنى آخر، بدون آثار جانبية.
</p>

<p>
	<strong>إضافة حدث مفيد إليها سيكون خدعة جيدة، بجانب مهمتها الرئيسية.</strong>
</p>

<p>
	بالتأكيد، ستوسِّع نظرة الدهشة التي على وجه قارئ الشيفرة -عندما يرى دالة بالاسم "<code>is..‎</code>"، أو "<code>check..‎</code>"، أو "<code>find..‎</code>" وتُغَيِّر شيئا ما - آفاق المنطق لديك.
</p>

<p>
	<strong>طريقة أخرى هي إرجاع نتيجة غير قياسية.</strong>
</p>

<p>
	أظهر ذكائك! اجعل الدالة <code>checkPermission</code> تُرجِع كائنًا معقدًا يحتوي على نتيجة الفحص المُراد من الدالة.
</p>

<p>
	سَيتساءل المطورون الذين سيكتبون "<code>if (checkPermission(..))‎</code>" عن سبب عدم عملها. حينها أخبرهم أن يقرأوا التوثيق ووجههم لهذا المقال :).
</p>

<h2>
	دوال قوية!
</h2>

<p>
	لا تجعل الدالة محدودة بما يتضمنه اسمها. توسَّع أكثر. على سبيل المثال، يمكن للدالة "<code>validateEmail(email)‎</code>" (بالإضافة إلى فحص صحة البريد الالكتروني) عرض رسالة خطأ وطلب إعادة إدخال البريد الإلكتروني.
</p>

<p>
	لا يجب أن تكون باقي الوظائف واضحة من مسمى الدالة. مبرمج النينجا الحقيقي لن يجعل هذه الوظائف واضحة حتى في الشيفرة البرمجية.
</p>

<h2>
	الخلاصة
</h2>

<p>
	جميع الملاحظات السابقة هي من شيفرات برمجية حقيقية مكتوبة بواسطة مبرمجين محترفين، ربما أكثر احترافية منك <img alt=";)" data-emoticon="true" height="20" src="https://academy.hsoub.com/uploads/monthly_2015_02/wink.png.86fb0c4c33891464b9b6a55de3ffaa8d.png" srcset="https://academy.hsoub.com/uploads/emoticons/wink@2x.png 2x" title=";)" width="20"></p>

<ul>
<li>
		اتبع بعض الملاحظات وستكون شيفرتك البرمجية مليئة بالمفاجآت.
	</li>
	<li>
		اتَّبِع اغلبها وستكون شيفرتك البرمجية حقا ملك لك أنت فقط، لن يريد أي شخص تغييرها.
	</li>
	<li>
		اتَّبِع جميعها وستصبح شيفرتك البرمجية درسًا قيمَا للمطورين المبتدئين الباحثين عن إرشاد.
	</li>
</ul>
<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/ninja-code" rel="external nofollow">Ninja code</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%A7%D9%84%D8%A2%D9%84%D9%8A-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-mocha-r794/" rel="">الاختبار الآلي باستخدام mocha</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%8A%D9%82%D8%A7%D8%AA-r786/" rel="">التعليقات</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">793</guid><pubDate>Sun, 02 Feb 2020 18:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x639;&#x644;&#x64A;&#x642;&#x627;&#x62A; &#x641;&#x64A; &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A;</title><link>https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%8A%D9%82%D8%A7%D8%AA-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r786/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/22.jpg.de0e9d4016558fe91ebfe590f93fc9bb.jpg" /></p>

<p>
	كما نعلم من جزء <a href="https://academy.hsoub.com/programming/javascript/%D8%A8%D9%86%D9%8A%D8%A9-%D8%A7%D9%84%D8%B4%D9%8A%D9%81%D8%B1%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r669/" rel="">بنية الشيفرة البرمجية</a>، يمكن ان تكون التعليقات ذات سطر واحد: وتبدأ ب <code>//</code> أو متعددة الأسطر: <code>/* ... */</code>.
</p>

<p>
	تُستخدم التعليقات لوصف الغرض من الشيفرة البرمجية وآلية عملها. في أول مرة، قد تبدو التعليقات مهمة، لكن المبرمجين المبتدئين يستخدمونها بطريقة غير صحيحة.
</p>

<h2>
	التعليقات السيئة
</h2>

<p>
	يستخدم المبتدئون التعليقات لشرح "ماذا يحدث في الشيفرة البرمجية". كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6033_6" style="">
<span class="com">// ستقوم هذه الشيفرة البرمجية بهذا الأمر (...) وذلك الأمر (...)</span><span class="pln">
</span><span class="com">// وربما أشياء أخرى</span><span class="pln">
very</span><span class="pun">;</span><span class="pln">
complex</span><span class="pun">;</span><span class="pln">
code</span><span class="pun">;</span></pre>

<p>
	يجب أن يكون عدد التعليقات التوضيحية أقل في الشيفرات البرمجية الجيدة، لأن الشيفرة البرمجية يجب أن تكون مفهومة بدون تعليقات.
</p>

<p>
	يوجد قاعدة مهمة حول هذا الأمر:"إن كانت الشيفرة البرمجية غير مفهومة لدرجة أنها تحتاج إلى التعليقات لشرحها، يجب أن تُكتب من جديد بدلًا من التعليقات التوضيحية الكثيرة".
</p>

<h3>
	طريقة: أخرج الدوال
</h3>

<p>
	أحيانا، يكون استبدال جزء من الشيفرة البرمجية أمرًا مهمًا كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6033_8" style="">
<span class="kwd">function</span><span class="pln"> showPrimes</span><span class="pun">(</span><span class="pln">n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  nextPrime</span><span class="pun">:</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    </span><span class="com">// check if i is a prime number</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> j </span><span class="pun">&lt;</span><span class="pln"> i</span><span class="pun">;</span><span class="pln"> j</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">%</span><span class="pln"> j </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">continue</span><span class="pln"> nextPrime</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	البديل الأفضل هو إخراج دالة <code>isPrime</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6033_10" style="">
<span class="kwd">function</span><span class="pln"> showPrimes</span><span class="pun">(</span><span class="pln">n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">isPrime</span><span class="pun">(</span><span class="pln">i</span><span class="pun">))</span><span class="pln"> </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln">

    alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> isPrime</span><span class="pun">(</span><span class="pln">n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">%</span><span class="pln"> i </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بهذه الطريقة يمكننا فهم الشيفرة البرمجية بشكل أفضل لأن الدالة أصبحت بديلة عن التعليق. هذه الشيفرة البرمجية تسمى شيفرة برمجية موصوفة بحد ذاتها.
</p>

<h3>
	طريقة: أنشئ دوالًا
</h3>

<p>
	إن كان هناك شيفرة برمجية طويلة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6033_12" style="">
<span class="com">// here we add whiskey</span><span class="pln">
</span><span class="kwd">for</span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let drop </span><span class="pun">=</span><span class="pln"> getWhiskey</span><span class="pun">();</span><span class="pln">
  smell</span><span class="pun">(</span><span class="pln">drop</span><span class="pun">);</span><span class="pln">
  add</span><span class="pun">(</span><span class="pln">drop</span><span class="pun">,</span><span class="pln"> glass</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// here we add juice</span><span class="pln">
</span><span class="kwd">for</span><span class="pun">(</span><span class="pln">let t </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> t </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> t</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let tomato </span><span class="pun">=</span><span class="pln"> getTomato</span><span class="pun">();</span><span class="pln">
  examine</span><span class="pun">(</span><span class="pln">tomato</span><span class="pun">);</span><span class="pln">
  let juice </span><span class="pun">=</span><span class="pln"> press</span><span class="pun">(</span><span class="pln">tomato</span><span class="pun">);</span><span class="pln">
  add</span><span class="pun">(</span><span class="pln">juice</span><span class="pun">,</span><span class="pln"> glass</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// ...</span></pre>

<p>
	فيُفضل إخراجه إلى دالة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6033_14" style="">
<span class="pln">addWhiskey</span><span class="pun">(</span><span class="pln">glass</span><span class="pun">);</span><span class="pln">
addJuice</span><span class="pun">(</span><span class="pln">glass</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> addWhiskey</span><span class="pun">(</span><span class="pln">container</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">for</span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    let drop </span><span class="pun">=</span><span class="pln"> getWhiskey</span><span class="pun">();</span><span class="pln">
    </span><span class="com">//...</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> addJuice</span><span class="pun">(</span><span class="pln">container</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">for</span><span class="pun">(</span><span class="pln">let t </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> t </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> t</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    let tomato </span><span class="pun">=</span><span class="pln"> getTomato</span><span class="pun">();</span><span class="pln">
    </span><span class="com">//...</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مرة اخرى.. يجب أن يكون عمل الدالة واضحا من اسمها وموضعها. هكذا لن نحتاج إلى الكثير من التعليقات. وستكون بنية الشيفرة البرمجية أفضل عند تجزئتها. وسيصبح من الواضح ماهي آلية عمل الدالة، وماذا تستقبل وماذا تُخرِج.
</p>

<p>
	في الواقع لا يمكننا تجنب التعليقات التوضيحية. فهناك بعض الخوارزميات المعقدة وأدوات التعديل والتحسين الذكية (smart tweaks) للشيفرة البرمجية. لكن يجب أن نحاول أن نجعل الشيفرة البرمجية سهلا ويشرح نفسه.
</p>

<h2>
	التعليقات الجيدة
</h2>

<p>
	إن كانت التعليقات التوضيحية سيئة، فأي التعليقات هو الجيد؟
</p>

<p>
	<strong>وصف الهيكلة</strong>
</p>

<p>
	يُعطي نظرة عامة عن المكونات، وطريقة تفاعلها، وطريقة تدفق التحكم في مختلف الحالات، وما إلى ذلك. باختصار، ما يُسمى بالنظرة الشاملة. يوجد لغة خاصة <a href="http://wikipedia.org/wiki/Unified_Modeling_Language" rel="external nofollow">UML</a> لبناء رسوم هيكلية عالية المستوى لشرح الشيفرة البرمجية. هذه اللغة تستحق التعلم فعلا.
</p>

<p>
	<strong>توثيق مُعامِلات الدوال واستخدامها</strong>
</p>

<p>
	يوجد تركيب خاص بالجمل البرمجية يُسمَّى <a href="http://en.wikipedia.org/wiki/JSDoc" rel="external nofollow">JSDoc</a> لتوثيق الدوال: استخدامها، مُعامِلاتها، والقيم التي تُرجِعُها.
</p>

<p>
	إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6033_16" style="">
<span class="com">/**
 * Returns x raised to the n-th power.
 *
 * @param {number} x The number to raise.
 * @param {number} n The power, must be a natural number.
 * @return {number} x raised to the n-th power.
 */</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تتيح لنا هذه التعليقات فهم الغرض من هذه الدالة واستخدامها مباشرة دون الحاجة للنظر إلى تفاصيل الشيفرة البرمجية فيها.
</p>

<p>
	يمكن للعديد من المُحررات فهم هذه التعليقات أيضا واستخدامها في الإكمال التلقائي وبعض حالات فحص الشيفرة التلقائي.
</p>

<p>
	يوجد أيضا بعض الأدوات مثل <a href="https://github.com/jsdoc3/jsdoc" rel="external nofollow">JSDoc 3</a> والتي يمكنها توليد توثيق HTML من هذه التعليقات. للمزيد من المعلومات حول JSDoc اقرأ هنا <a href="http://usejsdoc.org/" rel="external nofollow">http://usejsdoc.org/</a>.
</p>

<p>
	<strong>لم تم حل هذه المهمة بهذه الطريقة؟</strong>
</p>

<p>
	ما هو مكتوب هو مهم، لكن قد يكون ما هو غير مكتوب أكثر أهمية لفهم ما يجري. لا تستطيع الشيفرة البرمجية الإجابة عن السؤال "لم تم حل هذه المهمة بهذه الطريقة؟".
</p>

<p>
	إن كان هناك العديد من الطرق لحل هذه المهمة. لم تم اختيار هذه الطريقة؟ خاصة عندما لا تكون هذه الطريقة هي الأفضل.
</p>

<p>
	بدون تعليقات توضح السبب يمكن حدوث التالي:
</p>

<ol>
<li>
		ستفتح الشيفرة البرمجية المكتوبة منذ وقت طويل (أنت أو أي شخص آخر) وسترى أنها "غير مناسبة".
	</li>
	<li>
		ستفكر: "كم كنت غبيا حينها، وكم أنا ذكي الآن"، ثم ستُعيد كتابة الشيفرة البرمجية باستخدام البديل الذي تراه أكثر صحة وملائمة.
	</li>
	<li>
		فكرة إعادة الكتابة تكون سهلة، لكن عند القيام بها تكتشف أن الحل "الأمثل" لا يتناسب مع الغرض المطلوب. حينها قد تتذكر السبب لأنك جربت الأمر ذاته مسبقا بالفعل ولم يفلح. ثم ستعود إلى الخيار السابق لكن بعد ضياع الوقت.
	</li>
</ol>
<p>
	التعليقات التي توضح سبب استخدام طريقة ما هي مهمة جدا. فهي تساعد على الاستمرار بالتطوير مباشرة.
</p>

<p>
	<strong>أي ميزات غير ملحوظة في الشيفرة البرمجية ومكان استخدامها</strong>
</p>

<p>
	إن احتوت الشيفرة البرمجية على شيء غير ملحوظ أو شيء يُدرَك حدسيا، فيجب تعليقه.
</p>

<h2>
	الخلاصة
</h2>

<p>
	التعليقات هي علامة مهمة عن المطوِّر الجيد: وجودها أو عدم وجودها، إذ تتيح التعليقات الجيدة صيانة الشيفرة البرمجية جيدا، عند العودة لها بعد مدة من الوقت واستخدامها بكفاءة.
</p>

<p>
	<strong>علِّق ما يلي:</strong>
</p>

<ul>
<li>
		الهيكلة العامة، النظرة عالية المستوى.
	</li>
	<li>
		استخدام الدوال.
	</li>
	<li>
		الحلول المهمة، خاصة تلك الغير ملحوظة مباشرة.
	</li>
</ul>
<p>
	<strong>تجنب التعليقات:</strong>
</p>

<ul>
<li>
		التي تشرح آلية عمل الشيفرة البرمجية والغرض منها.
	</li>
	<li>
		ضع مثل هذه التعليقات عندما يكون من المستحيل جعل الشيفرة البرمجية سهلة القراءة وتصف نفسها وتحتاج لتوضيح فقط
	</li>
</ul>
<p>
	تستخدم التعليقات أيضا للأدوات التي تقوم بالتوثيق تلقائيا مثل JSDoc3: تقرأ هذه الأدوات التعليقات وتولِّد ملفات HTML أو بأي صيغة أخرى.
</p>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/comments" rel="external nofollow">Comments</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%B4%D9%8A%D9%81%D8%B1%D8%A9-%D8%A7%D9%84%D9%86%D9%8A%D9%86%D8%AC%D8%A7-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r793/" rel="">شيفرة النينجا البرمجية</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D9%86%D9%85%D8%B7-%D9%83%D8%AA%D8%A7%D8%A8%D8%A9-%D8%A7%D9%84%D8%B4%D9%8A%D9%81%D8%B1%D8%A9-r785/" rel="">نمط كتابة الشيفرة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">786</guid><pubDate>Thu, 30 Jan 2020 13:04:00 +0000</pubDate></item><item><title>&#x646;&#x645;&#x637; &#x643;&#x62A;&#x627;&#x628;&#x629; &#x634;&#x64A;&#x641;&#x631;&#x629; &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A;</title><link>https://academy.hsoub.com/programming/javascript/%D9%86%D9%85%D8%B7-%D9%83%D8%AA%D8%A7%D8%A8%D8%A9-%D8%B4%D9%8A%D9%81%D8%B1%D8%A9-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r785/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/21.jpg.3147cdd8b4fe0e1596d84b99a08dbf3e.jpg" /></p>

<p>
	يجب أن تكون الشيفرة البرمجية مرتبة و<a href="https://wiki.hsoub.com/Refactoring/what_is_refactoring" rel="external">نظيفة</a> وسهلة القراءة قدر الإمكان.
</p>

<p>
	هذا ما يسمى بفن البرمجة وهو أخذ مهمة معقدة وبرمجتها بطريقة صحيحة ومقروءة في الوقت ذاته. يساعد نمط كتابة الشيفرة كثيرا في ذلك.
</p>

<h2>
	الصياغة
</h2>

<p>
	في الصورة أدناه يوجد صفحة تحوي بعض القواعد المهمة في تركيب الشيفرات البرمجية.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33278" href="https://academy.hsoub.com/uploads/monthly_2020_01/code-style.png.089961853f452e6cede131e26a2e6c3a.png" rel=""><img alt="code-style.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33278" data-unique="0u31buq9b" src="https://academy.hsoub.com/uploads/monthly_2020_01/code-style.png.089961853f452e6cede131e26a2e6c3a.png"></a>
</p>

<p>
	سنناقش هذه القواعد وأسبابها بالتفصيل.
</p>

<p>
	ملاحظة: <strong>لا يوجد قواعد الزامية</strong>. لا يوجد قاعدة إلزامية لنمط التكويد. هذه القواعد تعد تفضيلات وليست أساسيات برمجية.
</p>

<h3>
	الأقواس المعقوصة (Curly Braces)
</h3>

<p>
	تُكتب الأقواس المعقوصة في معظم مشاريع JavaScript المعقوصة بالطريقة "المصرية" بوضع قوس الفتح في نفس السطر الذي يحوي الكلمة المفتاحية - ليس في سطر جديد. يجب وضع مسافة قبل القوس الافتتاحي كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_7" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">condition</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// افعل هذا</span><span class="pln">
  </span><span class="com">//…. وذاك</span><span class="pln">
  </span><span class="com">//…. وذاك</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	التعليمة المكونة من سطر واحد مثل <code>if(condition) doSomething()‎</code> تعد حالة طرفية مهمة، فهل يجب استخدام الأقواس فيها؟
</p>

<p>
	فيما يلي بعض البدائل المشروحة. يمكنك قراءتها والحكم على درجة سهولة قراءتها بنفسك:
</p>

<p>
	1- يقوم بعض المبتدئون أحيانًا بما يلي. ما يعد ممارسة خاطئة. فلا حاجة لِلأقواس المعقوصة هنا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_11" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">alert</span><span class="pun">(`</span><span class="typ">Power</span><span class="pln"> $</span><span class="pun">{</span><span class="pln">n</span><span class="pun">}</span><span class="pln"> is not supported</span><span class="pun">`);}</span></pre>

<p>
	2- الانتقال إلى سطر جديد بدون استخدام أقواس. تجنب هذا الأمر لأنه يسبب بعض الأخطاء:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_13" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
  alert</span><span class="pun">(`</span><span class="typ">Power</span><span class="pln"> $</span><span class="pun">{</span><span class="pln">n</span><span class="pun">}</span><span class="pln"> is not supported</span><span class="pun">`);</span></pre>

<p>
	3- سطر واحد بدون أقواس يُعد مقبولا في حال كان السطر قصيرًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_15" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(`</span><span class="typ">Power</span><span class="pln"> $</span><span class="pun">{</span><span class="pln">n</span><span class="pun">}</span><span class="pln"> is not supported</span><span class="pun">`);</span></pre>

<p>
	4- أفضل الطرق:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_17" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(`</span><span class="typ">Power</span><span class="pln"> $</span><span class="pun">{</span><span class="pln">n</span><span class="pun">}</span><span class="pln"> is not supported</span><span class="pun">`);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن استخدام سطر واحد في حالة الشيفرات البرمجية المختصرة مثل: <code>if (cond) return null</code>. لكن استخدام شيفرة برمجية كتلية (كما في رقم 4) هو الأفضل من ناحية سهولة القراءة.
</p>

<h3>
	طول السطر
</h3>

<p>
	لا يحب أحدٌ قراءة سطر برمجي طويل. أصبح فصل الأسطر الطويلة ممارسة عامة لدى الجميع.
</p>

<p>
	إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_19" style="">
<span class="com">// تسمح أقواس الفاصلة العليا المائلة ` بتقسيم النص إلى عدة أسطر</span><span class="pln">
let str </span><span class="pun">=</span><span class="pln"> </span><span class="pun">`</span><span class="pln">
  </span><span class="typ">Ecma</span><span class="pln"> </span><span class="typ">International</span><span class="str">'</span><span class="pln">s TC39 is a group of </span><span class="typ">JavaScript</span><span class="pln"> developers</span><span class="pun">,</span><span class="pln">
  implementers</span><span class="pun">,</span><span class="pln"> academics</span><span class="pun">,</span><span class="pln"> and more</span><span class="pun">,</span><span class="pln"> collaborating </span><span class="kwd">with</span><span class="pln"> the community
  to maintain and evolve the definition of </span><span class="typ">JavaScript</span><span class="pun">.</span><span class="pln">
</span><span class="pun">`;</span></pre>

<p>
	بالنسبة للتعليمة البرمجية <code>if</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_21" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
  id </span><span class="pun">===</span><span class="pln"> </span><span class="lit">123</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">
  moonPhase </span><span class="pun">===</span><span class="pln"> </span><span class="str">'Waning Gibbous'</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">
  zodiacSign </span><span class="pun">===</span><span class="pln"> </span><span class="str">'Libra'</span><span class="pln">
</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  letTheSorceryBegin</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يتم الاتفاق على الحد الأقصى لطول السطر البرمجي على مستوى فريق العمل. يكون طول السطر البرمجي غالبا 80 أو 120 محرفَا.
</p>

<h3>
	مسافة البادئة
</h3>

<p>
	يوجد نوعان من البادئة "Indents":
</p>

<ul>
<li>
		<strong>البادئة الأفقية: 2 أو 4 مسافات:</strong>
	</li>
</ul>
<p>
	تُصنع البادئة الأفقية بوضع 2 أو 4 مسافات أو باستخدام رمز البادئة الأفقية (الزر <code>Tab</code>). وُجدت اختلافات قديمة حول أيهما أفضل، لكن المسافات هي الأكثر شيوعا هذه الأيام.
</p>

<p>
	تتميز المسافات عن الزر <code>Tab</code> بكونها أكثر مرونة أثناء التعديل. مثلًا، يمكننا إزاحة المتغيرات داخل قوس مفتوح كالتالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_23" style="">
<span class="pln">show</span><span class="pun">(</span><span class="pln">parameters</span><span class="pun">,</span><span class="pln">
     aligned</span><span class="pun">,</span><span class="pln"> </span><span class="com">// 5 spaces padding at the left</span><span class="pln">
     one</span><span class="pun">,</span><span class="pln">
     after</span><span class="pun">,</span><span class="pln">
     another
  </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		<strong>البادئة العمودية: الأسطر الفارغة لفصل الشيفرات البرمجية إلى أجزاء منطقية:</strong>
	</li>
</ul>
<p>
	يمكن تقسيم حتى دالة بحد ذاتها إلى أجزاء منطقية لتسهل قرائتها. في المثال أدناه، تم تقسيم تعريف المتغيرات وحلقة التكرار الرئيسية والنتيجة عموديا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_25" style="">
<span class="kwd">function</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let result </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
  </span><span class="com">//              &lt;--</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    result </span><span class="pun">*=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="com">//              &lt;--</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكنك وضع سطر فارغ حيثما تريد لجعل الشيفرة البرمجية مقروءة بسهولة. لا يجب أن يوجد أكثر من 9 أسطر بدون بادئة عمودية.
</p>

<h3>
	الفواصل المنقوطة ";"
</h3>

<p>
	يجب أن توضع فاصلة منقوطة بعد كل تعليمة برمجية، حتى وإن كان من الممكن عدم إضافتها.
</p>

<p>
	يوجد بعض اللغات حيث يكون استخدام الفاصلة المنقوطة اختياريا وتُستخدم نادرا. لكن في بعض الحالات في JavaScript لا يحل السطر الجديد محل الفاصلة المنقوطة مما يجعل الشيفرة البرمجية عرضة للخطأ. يمكنك الاطلاع أكثر عن ذلك في جزء <a href="https://academy.hsoub.com/programming/javascript/%D8%A8%D9%86%D9%8A%D8%A9-%D8%A7%D9%84%D8%B4%D9%8A%D9%81%D8%B1%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r669/" rel="">بنية الشيفرة البرمجية</a>.
</p>

<p>
	إن كنت مبرمجًا متمرسًا في JavaScriptK، يمكنك اختيار نمط تكويد بدون فاصلة منقوطة مثل <a href="https://standardjs.com/" rel="external nofollow">StandardJS</a>. أو يُفَضَّل استخدام فواصل منقوطة لتجنب الأخطاء. أغلب المبرمجين يضعون فواصل منقوطة.
</p>

<h3>
	مستويات التداخل
</h3>

<p>
	تجنب تداخل الشيفرة البرمجية للعديد من المستويات. مثلًا، في الحلقة المتكررة يُفَضَّل استخدام التعليمة <code>continue</code> لتجنب التداخل العميق.
</p>

<p>
	مثلا، بدلا من إضافة <code>if</code> شرطية داخلية كالتالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_27" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cond</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">...</span><span class="pln"> </span><span class="com">// &lt;- مستوى تشعيب إضافي</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكننا كتابة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_29" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">cond</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">  </span><span class="com">// &lt;- لا مزيد من التشعيبات</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن استخدام الأسلوب ذاته مع <code>if/else</code> و <code>return</code>. مثلًا، نحتاج لجزئين في المثال أدناه.
</p>

<p>
	خيار 1:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_31" style="">
<span class="kwd">function</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"Negative 'n' not supported"</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    let result </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      result </span><span class="pun">*=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	خيار 2:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_33" style="">
<span class="kwd">function</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"Negative 'n' not supported"</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  let result </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">

  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    result </span><span class="pun">*=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُعد الخيار 2 أسهل قراءةً من الخيار 1 لأن الحالة الخاصة <code>n &lt; 0</code> فُحصت مسبقًا. بعد فحص قيمتها يمكننا الانتقال إلى جزء الشيفرة البرمجية الرئيسية بدون الحاجة لتداخل أكثر.
</p>

<h2>
	موضِع الدوال
</h2>

<p>
	في حال كنت تكتب العديد من الدوال المساعدة والتي تستخدمها الشيفرة البرمجية، فإن هناك 3 طرق لتنظيم هذه الدوال.
</p>

<p>
	1- تعريف الدوال أعلى الشيفرة البرمجية التي تستخدمها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_35" style="">
<span class="com">// تعريفات الدوال</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> createElement</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> setHandler</span><span class="pun">(</span><span class="pln">elem</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> walkAround</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// الشيفرة التي تستخدمها</span><span class="pln">
let elem </span><span class="pun">=</span><span class="pln"> createElement</span><span class="pun">();</span><span class="pln">
setHandler</span><span class="pun">(</span><span class="pln">elem</span><span class="pun">);</span><span class="pln">
walkAround</span><span class="pun">();</span></pre>

<p>
	2- الشيفرة البرمجية أولا ثم الدوال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_37" style="">
<span class="com">// الشيفرة التي تستخدم الدوال</span><span class="pln">
let elem </span><span class="pun">=</span><span class="pln"> createElement</span><span class="pun">();</span><span class="pln">
setHandler</span><span class="pun">(</span><span class="pln">elem</span><span class="pun">);</span><span class="pln">
walkAround</span><span class="pun">();</span><span class="pln">

</span><span class="com">// --- دوال مساعدة ---</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> createElement</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> setHandler</span><span class="pun">(</span><span class="pln">elem</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> walkAround</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	3- الطريقة المختلطة: تُعرَّف الدالة في أول مكان تستخدم فيه.
</p>

<p>
	الخيار الثاني هو الأفضل غالبا. ذلك لأنه عند قراءة شيفرة برمجية، فإننا نريد معرفة ما تقوم به أولا. إن كانت الشيفرة البرمجية في البداية فإن غرضها يكون واضحا مباشرة. أيضا، قد لا نحتاج لقراءة الدوال، خاصة إن كانت وظائفها واضحة من مسمياتها.
</p>

<h2>
	شروحات لأنماط كتابة الشيفرة
</h2>

<p>
	يحتوي دليل أنماط التكويد قواعد عامة حول كيفية كتابة شيفرة برمجية. مثلًا، الأقواس المستخدمة، وعدد مسافات البادئة، وأقصى طول للسطر، …الخ. والعديد من التفاصيل الدقيقة.
</p>

<p>
	عندما يستخدم جميع أعضاء الفريق الدليل نفسه لنمط التكويد، ستبدو الشيفرة البرمجية موحدة بغض النظر عمن قام بكتابتها.
</p>

<p>
	يمكن لأي الفريق الكتابة بنمط تكويد خاص بهم، لكن لا حاجة لذلك لوجود العديد من المعايير العالمية للاختيار منها.
</p>

<p>
	بعض الخيارات الشهيرة:
</p>

<ul>
<li>
		<a href="https://google.github.io/styleguide/javascriptguide.xml" rel="external nofollow">Google JavaScript Style Guide</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/javascript/%D8%AF%D9%84%D9%8A%D9%84-airbnb-%D9%84%D9%86%D9%85%D8%B7-%D8%AC%D8%A7%D9%81%D8%A7-%D8%B3%D9%83%D8%B1%D9%8A%D8%A8%D8%AA-r632/" rel="">Airbnb JavaScript Style Guide</a>
	</li>
	<li>
		<a href="https://github.com/rwaldron/idiomatic.js" rel="external nofollow">Idiomatic.JS</a>
	</li>
	<li>
		<a href="https://standardjs.com/" rel="external nofollow">StandardJS</a>
	</li>
	<li>
		وغيرها
	</li>
</ul>
<p>
	في حال كنت مطورًا مبتدئًا، ابدأ بالشرح المزود هنا. ثم يمكنك الانتقال إلى دليل آخر مما ذكرناه لتتعرف على المزيد من التفاصيل وتختار الأسلوب الأنسب لك.
</p>

<h2>
	منقحات الصياغة التلقائية (Automated Linters)
</h2>

<p>
	منقحات الصياغة (Linters): هي عبارة عن أدوات يمكنها فحص نمط الشيفرة البرمجية تلقائيا واقتراح تعديلات لتحسينها.
</p>

<p>
	الأمر الذي يجعلها مفيدة أكثر هو قدرتها على العثور على بعض الأخطاء، مثل الخطأ باسم متغير أو دالة ما، لهذا فإنه من المستحسن استخدام منقح صياغة (Linter) حتى لو لم تُرد اتباع نمط تكويد معين.
</p>

<p>
	هنا بعض أدوات تنقيح الصياغة المعروفة مثل:
</p>

<ul>
<li>
		<a href="http://www.jslint.com/" rel="external nofollow">JSLint</a> – تُعد من أدوات تنقيح الصياغة الأولى.
	</li>
	<li>
		<a href="http://www.jshint.com/" rel="external nofollow">JSHint</a> – تحوي اعدادات أكثر من JSLint.
	</li>
	<li>
		<a href="http://eslint.org/" rel="external nofollow">ESLint</a> – الأحدث تقريبا.
	</li>
</ul>
<p>
	كلها تؤدي الغرض ذاته. الكاتب هنا يستخدم <a href="http://eslint.org/" rel="external nofollow">ESLint</a>. معظم هذه الأدوات تكون مدمجة مع العديد من المحررات الشهيرة: يجب عليك أن تُفَعِّل الإضافة في المحرر وتحدد نمط التكويد الذي تريده.
</p>

<p>
	مثلا، لاستخدام ESLint اتَّبع ما يلي:
</p>

<ol>
<li>
		ثبت <a href="https://nodejs.org/" rel="external nofollow">Node.js</a>.
	</li>
	<li>
		ثبت ESLint باستخدام الأمر <code>npm install -g eslint</code> (يُعد npm مُثَبِّت حزم JavaScript).
	</li>
	<li>
		أنشئ ملف إعداد وسمِّه "<code>‎.eslintrc</code>" في ملف مشروع JavaScript الرئيسي (الملف الذي يحتوي على جميع الملفات).
	</li>
	<li>
		ثبت/فعِّل الإضافة لمحررك الذي يدعم ESLint. معظم المحررات تدعم ESLint.
	</li>
</ol>
<p>
	هنا مثال على ملف "<code>‎.eslintrc</code>":
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_39" style="">
<span class="pun">{</span><span class="pln">
  </span><span class="str">"extends"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"eslint:recommended"</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"env"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="str">"browser"</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"node"</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"es6"</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
  </span><span class="pun">},</span><span class="pln">
  </span><span class="str">"rules"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="str">"no-console"</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"indent"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">"warning"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">]</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	التعليمة <code>"extends"</code> هنا تعني أن الإعداد يعتمد على مجموعة إعدادات ESLint الافتراضية "eslint:recommended". يُمكننا تعديل الإعدادات التي نريدها لاحقًا.
</p>

<p>
	يمكن أيضا تنزيل مجموعة قواعد نمط التكويد وتوسيعها بدلا من ذلك. انظر في الرابط <a href="http://eslint.org/docs/user-guide/getting-started" rel="external nofollow">http://eslint.org/docs/user-guide/getting-started</a> للمزيد من التفاصيل حول كيفية التثبيت.
</p>

<p>
	تحتوي بعض المحررات على منقح صياغة مدمج فيها إلا أنها ليست بدقة ESLint.
</p>

<h2>
	الخلاصة
</h2>

<p>
	تهدف جميع قواعد بناء الجمل في هذا الفصل (وفي باقي مراجع أنماط التكويد) لرفع مستوى سهولة قراءة الأكواد. وجميع القواعد قابلة للنقاش.
</p>

<p>
	عند التفكير في كتابة شيفرة برمجية بشكل أفضل، يجب أن نسأل أنفسنا: "ما الذي يجعل الشيفرة البرمجية أسهل للقراءة والفهم؟" و "ما الذي قد يساعدنا لتجنب الأخطاء؟" يوجد العديد من الأشياء التي يجب الانتباه لها أثناء اختيار نمط تكويد معين.
</p>

<p>
	سيتيح لك قراءة العديد من أنماط التكويد معرفة أحدث الأفكار عن أنماط التكويد وأفضل الممارسات.
</p>

<h2>
	تمارين
</h2>

<h3>
	نمط تكويد سيء
</h3>

<p class="task__importance">
	الأهمية: 4
</p>

<p>
	ما الخطأ في نمط التكويد أدناه؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_41" style="">
<span class="kwd">function</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln">n</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  let result</span><span class="pun">=</span><span class="lit">1</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">for</span><span class="pun">(</span><span class="pln">let i</span><span class="pun">=</span><span class="lit">0</span><span class="pun">;</span><span class="pln">i</span><span class="pun">&lt;</span><span class="pln">n</span><span class="pun">;</span><span class="pln">i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">result</span><span class="pun">*=</span><span class="pln">x</span><span class="pun">;}</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

let x</span><span class="pun">=</span><span class="pln">prompt</span><span class="pun">(</span><span class="str">"x?"</span><span class="pun">,</span><span class="str">''</span><span class="pun">),</span><span class="pln"> n</span><span class="pun">=</span><span class="pln">prompt</span><span class="pun">(</span><span class="str">"n?"</span><span class="pun">,</span><span class="str">''</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n</span><span class="pun">&lt;=</span><span class="lit">0</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(`</span><span class="typ">Power</span><span class="pln"> $</span><span class="pun">{</span><span class="pln">n</span><span class="pun">}</span><span class="pln"> is not supported</span><span class="pun">,</span><span class="pln"> please enter an integer number greater than zero</span><span class="pun">`);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln">n</span><span class="pun">))</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	قم بإصلاحه.
</p>

<p>
	الحل
</p>

<div class="task__answer">
	<p>
		يمكنك ملاحظة ما يلي:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_43" style="">
<span class="kwd">function</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln">n</span><span class="pun">)</span><span class="pln">  </span><span class="com">// &lt;- لا يوجد مسافات بين المُعاملات</span><span class="pln">
</span><span class="pun">{</span><span class="pln">  </span><span class="com">// &lt;- قوس الفتح في سطر مستقل</span><span class="pln">
  let result</span><span class="pun">=</span><span class="lit">1</span><span class="pun">;</span><span class="pln">   </span><span class="com">// &lt;- عدم وجود مسافات قبل أو بعد =</span><span class="pln">
  </span><span class="kwd">for</span><span class="pun">(</span><span class="pln">let i</span><span class="pun">=</span><span class="lit">0</span><span class="pun">;</span><span class="pln">i</span><span class="pun">&lt;</span><span class="pln">n</span><span class="pun">;</span><span class="pln">i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">result</span><span class="pun">*=</span><span class="pln">x</span><span class="pun">;}</span><span class="pln">   </span><span class="com">// &lt;- لا يوجد مسافات</span><span class="pln">
  </span><span class="com">// يجب أن يكون محتوى { ... } في سطر جديد</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

let x</span><span class="pun">=</span><span class="pln">prompt</span><span class="pun">(</span><span class="str">"x?"</span><span class="pun">,</span><span class="str">''</span><span class="pun">),</span><span class="pln"> n</span><span class="pun">=</span><span class="pln">prompt</span><span class="pun">(</span><span class="str">"n?"</span><span class="pun">,</span><span class="str">''</span><span class="pun">)</span><span class="pln"> </span><span class="com">// &lt;-- ممكنة تقنيا، </span><span class="pln">
</span><span class="com">// لكن يُفَضَّل جعلها في سطرين، بالإضافة إلى عدم وجود مسافات وعدم وجود ;</span><span class="pln">
</span><span class="com">// </span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n</span><span class="pun">&lt;</span><span class="lit">0</span><span class="pun">)</span><span class="pln">  </span><span class="com">// &lt;- لا يوجد مسافات بين (n &lt; 0), ويجب وجود سطر فارغ قبلها</span><span class="pln">
</span><span class="pun">{</span><span class="pln">   </span><span class="com">// &lt;- قوس الفتح في سطر مستقل</span><span class="pln">
  </span><span class="com">// يمكن فصل الأسطر الطويلة في الأسفل حتى تصبح سهلة القراءة</span><span class="pln">
  alert</span><span class="pun">(`</span><span class="typ">Power</span><span class="pln"> $</span><span class="pun">{</span><span class="pln">n</span><span class="pun">}</span><span class="pln"> is not supported</span><span class="pun">,</span><span class="pln"> please enter an integer number greater than zero</span><span class="pun">`);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pln"> </span><span class="com">// &lt;- يمكن كتابتها في سطر واحد هكذا: "} else {"</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln">pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln">n</span><span class="pun">))</span><span class="pln">  </span><span class="com">// لا يوجد مسافات ولا يوجد ;</span><span class="pln">
</span><span class="pun">}</span></pre>

	<p>
		بعد تصحيح الأخطاء تصبح الشيفرة البرمجية كما يلي:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5680_45" style="">
<span class="kwd">function</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let result </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">

  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    result </span><span class="pun">*=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

let x </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"x?"</span><span class="pun">,</span><span class="pln"> </span><span class="str">""</span><span class="pun">);</span><span class="pln">
let n </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"n?"</span><span class="pun">,</span><span class="pln"> </span><span class="str">""</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(`</span><span class="typ">Power</span><span class="pln"> $</span><span class="pun">{</span><span class="pln">n</span><span class="pun">}</span><span class="pln"> is not supported</span><span class="pun">,</span><span class="pln">
    please enter an integer number greater than zero</span><span class="pun">`);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>
</div>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/coding-style" rel="external nofollow">Coding Style</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%8A%D9%82%D8%A7%D8%AA-r786/" rel="">التعليقات</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D8%AA%D9%86%D9%82%D9%8A%D8%AD-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-chrome-r784/" rel="">تنقيح الأخطاء في Chrome</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">785</guid><pubDate>Tue, 28 Jan 2020 13:04:00 +0000</pubDate></item><item><title>&#x62A;&#x646;&#x642;&#x64A;&#x62D; &#x623;&#x62E;&#x637;&#x627;&#x621; &#x634;&#x64A;&#x641;&#x631;&#x629; &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A; &#x641;&#x64A; Chrome</title><link>https://academy.hsoub.com/programming/javascript/%D8%AA%D9%86%D9%82%D9%8A%D8%AD-%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%B4%D9%8A%D9%81%D8%B1%D8%A9-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-%D9%81%D9%8A-chrome-r784/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/20.jpg.c26b0f635114dec6ea489a7bc7f5f22a.jpg" /></p>

<p>
	قبل كتابة شيفرات برمجية أكثر تعقيدا، لنتطرَّق إلى تنقيح الأخطاء.
</p>

<p>
	<a href="https://en.wikipedia.org/wiki/Debugging" rel="external nofollow">تنقيح الأخطاء</a> هي عملية إيجاد الأخطاء في السكريبت وإصلاحها. تدعم جميع المتصفحات الحديثة وبعض البيئات الأخرى "تنقيح الأخطاء" -واجهة مستخدم خاصة في أدوات المطور والتي تجعل العثور على الأخطاء وتصحيحها أمرا سهلا. تُتيح هذه الواجهة أيضا تَتَبُّع الأكواد خطوة بخطوة لمعرفة ما يحدث فيها بالتفصيل.
</p>

<p>
	سنستخدم Chrome لأن لديه ميزات كافية لذلك، كما تتوفر هذه الميزات في معظم المتصفحات الأخرى.
</p>

<h2>
	جزء الموارد "sources"
</h2>

<p>
	قد يبدو إصدار Chrome لديك مختلفًا بعض الشيء، إلا أن المحتوى هو ذاته.
</p>

<ul>
<li>
		افتح صفحة <a href="https://javascript.info/article/debugging-chrome/debugging/index.html" rel="external nofollow">example</a> في Chrome.
	</li>
	<li>
		شغِّل أدوات المطور بالضغط على <code>F12</code> (على أجهزة Mac، استعمل الاختصار <code>Cmd+Opt+I</code>).
	</li>
	<li>
		اختر الجزء <code>sources</code>.
	</li>
</ul>
<p>
	إن كانت هذه هي مرتك الأولى للدخول إلى جزء <code>sources</code>، فهذا ما ستراه:
</p>

<p style="text-align: center;">
	<img alt="chrome-open-sources.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33268" data-unique="gydg1z73h" src="https://academy.hsoub.com/uploads/monthly_2020_01/chrome-open-sources.png.d5ce1429dcb3e9f4ec2aeb86f7c2860d.png"></p>

<p>
	يفتح هذا الزر علامة تبويب تحوي الملفات.
</p>

<p>
	اضغط عليها واختر <code>hello.js</code> من العرض الشجري "tree view". يجب أن ترى التالي:
</p>

<p style="text-align: center;">
	<img alt="chrome-tabs.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33273" data-unique="6owhjn7e6" src="https://academy.hsoub.com/uploads/monthly_2020_01/chrome-tabs.png.9d6d42b59f33e7138f7e0ac5756f2677.png"></p>

<p>
	هنا يمكننا رؤية ثلاث مناطق:
</p>

<ul>
<li>
		<strong>منطقة الموارد "Resources zone"</strong> والتي تعرض ملفات HTML، و JavaScritp، و CSS، وغيرها من الملفات بما في ذلك الصور المُلحقة بالصفحة. قد تظهر إضافات Chrome هنا أيضًا.
	</li>
	<li>
		<strong>منطقة المصدَر "Source zone"</strong> والتي تعرض الشيفرة البرمجية المصدرية.
	</li>
	<li>
		<strong>منطقة المعلومات والتحكم "Information and control zone"</strong> لتنقيح الأخطاء، سَنكتشفها أكثر فيما يلي
	</li>
</ul>
<p>
	يمكنك الضغط على الزر مُجددًا لِإخفاء قائمة الموارد وإعطاء الشيفرة البرمجية مساحة كافية.
</p>

<h2>
	شاشة التحكم (Console)
</h2>

<p>
	تظهر شاشة تحكم عند الضغط على <code>Esc</code>. يمكن كتابة الأوامر في شاشة التحكم ثم الضغط على <code>Enter</code> لتنفيذها.
</p>

<p>
	تظهر مخرجات تنفيذ أمر ما أسفله مباشرة في شاشة التحكم.
</p>

<p>
	مثال: كما في الصورة بالأسفل <code>1+2</code> ينتج <code>3</code>، بينما <code>hello("debugger")‎</code> لا يُظهِر أي نتائج، لذلك فإننا نرى <code>undefined</code>:
</p>

<p style="text-align: center;">
	<img alt="chrome-sources-console.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33270" data-unique="j753fotxj" src="https://academy.hsoub.com/uploads/monthly_2020_01/chrome-sources-console.png.4d9de2d87f32d54fc9070eeedbdb41ea.png"></p>

<h2>
	نقاط التوقف (Breakpoints)
</h2>

<p>
	لنختبر ما يحدُث أثناء تنفيذ الشيفرة البرمجية في <a href="https://javascript.info/article/debugging-chrome/debugging/index.html" rel="external nofollow">صفحة example</a>. في الصفحة <code>hello.js</code>، اضغط على السطر رقم <code>4</code>؛ نضغط على الرقم ذاته وليس السطر.
</p>

<p>
	هكذا تكون قد أنشأت نقطة توقف. اضغط على الرقم 8 أيضًا. يجب أن يبدو الشكل كما في الصورة التالية:
</p>

<p style="text-align: center;">
	<img alt="chrome-sources-breakpoint.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33269" data-unique="7iviv025s" src="https://academy.hsoub.com/uploads/monthly_2020_01/chrome-sources-breakpoint.png.a7c2e42c0eb8c205b8148ac8e3bfeaaf.png"></p>

<p>
	نقطة التوقف هي نقطة يتوقف فيها مصحح الأخطاء عن تنفيذ JavaScript تلقائيًا.
</p>

<p>
	يمكننا فحص المتغيرات الحالية وتنفيذ الأوامر أو أي شيء آخر في لوحة التحكم أثناء توقف عمل الشيفرة البرمجية. أي أنه يمكننا تتبع الشيفرة البرمجية عند نقطة معينة عبر ايقافها والتأكد من أي شيء فيها كما نريد.
</p>

<p>
	يمكننا رؤية قائمة بالعديد من نقاط التوقف في الجزء الأيمن من الشاشة. يكون الأمر مفيدًا عند وجود عدة نقاط توقف في أكثر من ملف، وذلك يتيح لنا:
</p>

<ul>
<li>
		التنقل بسرعة إلى نقاط التوقف في الشيفرة البرمجية (بالضغط عليها من الجزء الأيمن).
	</li>
	<li>
		إلغاء تفعيل نقاط التوقف مؤقتا بإلغاء تحديدها.
	</li>
	<li>
		حذف نقطة التوقف بالضغط عليها باليمين واختيار حذف "remove".
	</li>
	<li>
		وهكذا …
	</li>
</ul>
<h3>
	نقاط التوقف الشرطية
</h3>

<p>
	يتيح لك الضغط يمينَا على رقم السطر إنشاء نقطة توقف شرطية تُنَفَّذ عند تحقق الشرط المحدد فقط.
</p>

<p>
	يكون ذلك مفيدَا عندما تريد إيقاف التنفيذ لمعرفة قيمة أي متغير أو قيمة أي معامل في دالة.
</p>

<h2>
	أمر Debugger
</h2>

<p>
	يمكن أيضا إيقاف تنفيذ الشيفرة البرمجية بوضع الأمر <code>debugger</code> فيه كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5392_7" style="">
<span class="kwd">function</span><span class="pln"> hello</span><span class="pun">(</span><span class="pln">name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let phrase </span><span class="pun">=</span><span class="pln"> </span><span class="pun">`</span><span class="typ">Hello</span><span class="pun">,</span><span class="pln"> $</span><span class="pun">{</span><span class="pln">name</span><span class="pun">}!`;</span><span class="pln">

  </span><span class="kwd">debugger</span><span class="pun">;</span><span class="pln">  </span><span class="com">// &lt;-- يتوقف المنقح هنا</span><span class="pln">

  say</span><span class="pun">(</span><span class="pln">phrase</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذه الطريقة سهلة عندما نُعدِّل الشيفرة البرمجية باستخدم محرر الشيفرات البرمجية ولا نريد الانتقال إلى المتصفح وتشغيل السكربت في وضع أدوات المطور لإنشاء نقاط توقف.
</p>

<h2>
	توقف وتحقق
</h2>

<p>
	في المثال، يتم استدعاء الدالة <code>hello()‎</code> أثناء تحميل الصفحة، لذلك فإن أسهل طريقة لتفعيل مُنقِّح الأخطاء (بعد إعداد نقاط التوقف) هي إعادة تحميل الصفحة. اضغط على <code>F5</code> (لمستخدمي ويندوز أو لينكس)، أو اضغط على <code>Cmd+R</code> (لمستخدمي Mac).
</p>

<p>
	سيتوقف تنفيذ الشيفرة البرمجية في السطر الرابع حيث تم إنشاء نقطة التوقف:
</p>

<p style="text-align: center;">
	<img alt="chrome-sources-debugger-pause.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33271" data-unique="je659wgzx" src="https://academy.hsoub.com/uploads/monthly_2020_01/chrome-sources-debugger-pause.png.68a11e1cb08cf628deb386e146d9d221.png"></p>

<p style="text-align: center;">
	افتح قوائم المعلومات المنسدلة على اليمين (موضحة بأسهم). تتيح هذه القوائم التحقق من حالة السكريبت الحالية:
</p>

<p>
	1- <code>Watch</code> - <strong>تعرض القيم الحالية لأي تعابير</strong>.
</p>

<p>
	يمكنك الضغط على <code>+</code> وإدخال أي تعبير تريده. سيعرض المعالج قيمته في أي وقت وحساب قيمته تلقائيا أثناء التنفيذ.
</p>

<p>
	2- <code>Call Stack</code> - <strong>تعرض سلسلة الاستدعاءات المتداخلة</strong>.
</p>

<p>
	في الوقت الحالي، المعالج وصل حتى استدعاء الدالة <code>hello()‎</code>، المُستدعاة من خلال السكريبت <code>index.html</code> (لا يوجد دوال أخرى لذلك سُمِّيَت "anonymous").
</p>

<p>
	إن ضَغَطت على عنصر من الحزمة (stack) مثلا "anonymous"، فسينتقل المعالج مباشرة إلى الشيفرة البرمجية المُمَثِّل لهذا العنصر وستتمكن من فحص جميع متغيراته أيضا.
</p>

<p>
	3- <code>Scope</code> - <strong>تعرض المتغيرات الحالية</strong>.
</p>

<p>
	<code>Local</code> تعرض متغيرات الدالة المحلية. يمكنك أيضا رؤية قيم هذه المتغيرات موضحة على اليمين.
</p>

<p>
	<code>Global</code> تعرض المتغيرات الخارجية (خارج نطاق أي دالة).
</p>

<p>
	يوجد أيضا الكلمة المفتاحية <code>this</code> والتي لم تُشرح بعد، لكن سيتم شرحها قريبا.
</p>

<h2>
	تتبع التنفيذ
</h2>

<p>
	يوجد بعض الأزرار لِتتبع التنفيذ أعلى يمين اللوحة. لِنتطرق إليها.
</p>

<p>
	<strong>- زر استمرار التنفيذ</strong> <code>F8</code>.
</p>

<p>
	يستأنف التنفيذ. إن لم توجد أي نقاط توقف، فإن التنفيذ سيستمر بعد الضغط على هذا الزر وسَيفقد مصحح الأخطاء السيطرة على السكريبت.
</p>

<p>
	هذا ما سنراه بعد الضغط عليه:
</p>

<p style="text-align: center;">
	<img alt="chrome-sources-debugger-trace-1.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33272" data-unique="20xr5l3b4" src="https://academy.hsoub.com/uploads/monthly_2020_01/chrome-sources-debugger-trace-1.png.82e63f9b504063ee99244497ea658417.png"></p>

<p>
	تم استئناف التنفيذ، ووصل لنقطة توقف أخرى داخل الدالة <code>say()‎</code> وتوقف هناك. انظر في <code>Call stack</code> على اليمين. تم تنفيذ استدعاء آخر. وصل التنفيذ الآن حتى الدالة <code>say()‎</code>.
</p>

<p>
	<strong>- نفِّذ خطوة (نفّذ الأمر التالي)، لكن لا تنتقل إلى الدالة الأخرى، الوصول السريع</strong> <code>F10</code>.
</p>

<p>
	سيظهر <code>alert</code> إذا ضغطنا على هذا الزر الآن. الأمر المهم هنا هو أن <code>alert</code> قد يحوي على أي دالة، لذلك فإن التنفيذ سيتخطاها.
</p>

<p>
	<strong>- نفِّذ خطوة، الوصول السريع</strong> <code>F11</code>.
</p>

<p>
	يقوم بنفس آلية عمل الأمر السابق بالإضافة إلى تنفيذ الدوال المتداخلة. سَتتنفذ أوامر السكريبت بالضغط عليه خطوة بخطوة.
</p>

<p>
	<strong>- استمر بالتنفيذ حتى نهاية الدالة الحالية، باستخدام الزر</strong> <code>Shift+F11</code>.
</p>

<p>
	سيتوقف التنفيذ عند آخر سطر للدالة الحالية. يكون هذا الأمر مفيدا عند الدخول إلى استدعاء دالة مصادفةَ باستخدام الزر ، لكن تتبع هذه الدالة ليس أمرا مهما، لذلك نقوم بتخطي تتبعها.
</p>

<p>
	<strong>- تفعيل/تعطيل جميع نقاط التوقف.</strong>
</p>

<p>
	لا يقوم هذا الزر بمتابعة التنفيذ، إنما يُفَعِّل/يُعطِّل كمَا كبيرا من نقاط التوقف.
</p>

<p>
	<strong>- تفعيل/تعطيل التوقف التلقائي في حال حدوث خطأ.</strong>
</p>

<p>
	عند تفعيله في وضع أدوات المطور، فإن الشيفرة البرمجية تتوقف عن التنفيذ تلقائيا عند أي خطأ في السكريبت. ثم يمكننا تحليل المتغيرات لمعرفة سبب الخطأ. لذلك، إن أوقف خطأ مَا متابعة تنفيذ الشيفرة البرمجية، يمكننا فتح مصحح الأخطاء وتفعيل هذا الخيار وإعادة تحميل الصفحة لرؤية مكان توقف الشيفرة البرمجية وما هو المحتوى عند تلك النقطة.
</p>

<h3>
	الاستمرار حتى هنا "Continue to here"
</h3>

<p>
	الضغط يمينا على سطر من الشيفرة البرمجية يفتح قائمة السياق المحتوية على خيار مفيد يُدعى "Continue to here".
</p>

<p>
	يكون هذا الخيار مُفيدا عندما نريد التقدم بضع خطوات للأمام بدون وضع نقطة توقف.
</p>

<h2>
	التسجيل (Logging)
</h2>

<p>
	يمكن استخدام الدالة <code>console.log</code> لِعرض شيء على الشاشة كمُخرج من الشيفرة البرمجية. مثلا، يعرض الأمر التالي القيم من <code>0</code> حتى <code>4</code> إلى الشاشة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5392_9" style="">
<span class="com">// open console to see</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"значение"</span><span class="pun">,</span><span class="pln"> i</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا يرى المستخدم العادي هذه المخرجات. لرؤيتها، افتح علامة التبويب <code>Console</code> أو اضغط على <code>Esc</code> إن كنت في علامة تبويب أخرى هكذا تُفتًح الشاشة في الأسفل.
</p>

<p>
	إن كانت الشيفرة البرمجية تحتوي على أوامر <code>console.log</code>، فسنرى ما يحدث من خلال سجلات التتبع بدون الدخول إلى المُصحح.
</p>

<h2>
	الخلاصة
</h2>

<p>
	كما رأينا، فإن هناك ثلاث طرائق رئيسية لإيقاف السكريبت:
</p>

<ol>
<li>
		باستخدام نقطة توقف.
	</li>
	<li>
		الأمر <code>debugger</code>.
	</li>
	<li>
		وجود خطأ (في حال كانت أداوت المطور مفتوحة وكان الزر مُفَعًّلَأ).
	</li>
</ol>
<p>
	عند توقف السكريبت، يمكننا فحص المتغيرات وتتبع الشيفرة البرمجية لرؤية أي أخطاء.
</p>

<p>
	يوجد العديد من الخيارات الأخرى في أدوات المطور أكثر مما تم شرحه سابقا. تجد الدليل كاملا على <a href="https://developers.google.com/web/tools/chrome-devtools" rel="external nofollow">https://developers.google.com/web/tools/chrome-devtools</a>.
</p>

<p>
	تُعَد المعلومات التي وُضِعَت كافية لبدء تتبع أي شيفرة برمجية وتنقيحها، لكنك ستحتاج للاطلاع على الدليل لاحقا لتعلم ميزات متقدمة في أدوات المطور، خاصة إن كنت تتعامل كثيرا مع المتصفح.
</p>

<p>
	يمكنك الضغط على عدة أماكن في أدوات المطور ورؤية ما يحدث. تُعد هذه أفضل طريقة لتعلم أدوات المطور. لا تنسَ الضغط يمينا وتجريب قوائم السياق.
</p>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/debugging-chrome" rel="external nofollow">Debugging in Chrome</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>.
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D9%86%D9%85%D8%B7-%D9%83%D8%AA%D8%A7%D8%A8%D8%A9-%D8%A7%D9%84%D8%B4%D9%8A%D9%81%D8%B1%D8%A9-r785/" rel="">نمط كتابة الشيفرة</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D9%85%D8%B1%D8%A7%D8%AC%D8%B9%D8%A9-%D9%84%D9%85%D8%A7-%D8%B3%D8%A8%D9%82-r783/" rel="">مراجعة لما سبق</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">784</guid><pubDate>Sun, 26 Jan 2020 13:04:00 +0000</pubDate></item><item><title>&#x645;&#x631;&#x627;&#x62C;&#x639;&#x629; &#x644;&#x645;&#x627; &#x633;&#x628;&#x642; &#x62D;&#x648;&#x644; &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A;</title><link>https://academy.hsoub.com/programming/javascript/%D9%85%D8%B1%D8%A7%D8%AC%D8%B9%D8%A9-%D9%84%D9%85%D8%A7-%D8%B3%D8%A8%D9%82-%D8%AD%D9%88%D9%84-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r783/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/19.jpg.15939d47e6b731fe36e5f6261f9cd8c5.jpg" /></p>

<p>
	يلخِّص هذا الدرس مُميِّزات JavaScript التي تعرَّفنا عليها باختصار في الدروس السابقة مع إيلاء اهتمام خاص لأدق المواضيع.
</p>

<h2>
	صياغة الشيفرة
</h2>

<p>
	تنتهي التعليمات البرمجية في JavaScript بفاصلة منقوطة <code>;</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_7" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="str">'مرحبًا'</span><span class="pun">);</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">'بالعالم'</span><span class="pun">);</span></pre>

<p>
	يمكنك إنهاء تعليمة برمجية ببدء سطر جديد، إذ يعد محرف السطر الجديد على أنَّه فاصل للتعليمات:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_9" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="str">'مرحبًا'</span><span class="pun">)</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">'بالعالم'</span><span class="pun">)</span></pre>

<p>
	هذا ما يسمى «الإدراج التلقائي للفاصلة المنقوطة» (automatic semicolon insertion)، لكن يعمل كما هو متوقع في بعض الأحيان مثل الحالة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_11" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="str">"سيحدث خطأ هنا بعد الرسالة"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">].</span><span class="pln">forEach</span><span class="pun">(</span><span class="pln">alert</span><span class="pun">)</span></pre>

<p>
	تخبرك أغلب أدلة الصياغة بضرورة وضع فاصلة منقوطة بعد كل تعليمة برمجية (statement). انتبه إلى أنَّ الفاصلة المنقوطة غير مطلوبة بعد الكتل البرمجية <code>{...}</code> مثل كل الدوال وحلقات التكرار وغيرها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_13" style="">
<span class="kwd">function</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// لا حاجة لفاصلة منقوطة بعد التصريح عن دالة</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">for</span><span class="pun">(;;)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// لا حاجة لفاصلة منقوطة بعد حلقة تكرار</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ولكن إذا وضعت فاصلة منقوطة «زائدة» في مكان ما داخل الشيفرة، لن تعدها JavaScript خطأ وستتجاهلها ببساطة.
</p>

<p>
	تجد المزيد في فصل «بنية الشيفرة».
</p>

<h2>
	الوضع الصارم
</h2>

<p>
	إن أردت تمكين جميع ميزات JavaScript الحديثة كاملًا، يجب أن تستفتح السكربت بالموجه <code>"use strict"</code> مثل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_15" style="">
<span class="str">'use strict'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">...</span></pre>

<p>
	يجب أن يُكتَب هذا الموجِّه في بداية السكربت أو في بداية جسم الدالة.
</p>

<p>
	تعمل الشيفرة بدون الموجه <code>"use strict"</code>، لكن هناك بعض الميزات تبقى على صورتها القديمة «المتوافقة» (compatible way). عمومًا، يُفضَّل العمل بالوضع الحديث دومًا.
</p>

<p>
	تُفعِّل بعض مميزات JavaScript الحديثة، مثل الأصناف التي ستتعرف عليها لاحقًا، الوضع الصارم ضمنيًّا.
</p>

<p>
	تجد المزيد في فصل «الوضع الصارم: ».
</p>

<h2>
	المتغيرات
</h2>

<p>
	يمكنك تعريف المتغيرات عبر:
</p>

<ul>
<li>
		<code>let</code>
	</li>
	<li>
		<code>const</code> (متغير ثابت لا يمكن تغيير قيمته)
	</li>
	<li>
		<code>var</code> (نمط قديم سوف تتعرف عليه لاحقًا)
	</li>
</ul>
<p>
	يمكن أن يحتوي اسم المتغير على:
</p>

<ul>
<li>
		حروف وأعداد، لكن الحرف الأول لا يجب أن يكون عددًا.
	</li>
	<li>
		الرمزان <code>_</code> و <code>$</code>.
	</li>
	<li>
		يُسمَح أيضًا باستخدام الحروف الهجائية غير اللاتينية والحروف الهيروغليفية، ولكنها غير شائعة الاستخدام.
	</li>
</ul>
<p>
	يمكنك تخزين أي قيمة داخل المتغير مثل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_17" style="">
<span class="pln">let x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
x </span><span class="pun">=</span><span class="pln"> </span><span class="str">"عبد الله"</span><span class="pun">;</span></pre>

<p>
	إليك سبعة أنواع من البيانات:
</p>

<ul>
<li>
		<code>number</code>: يمثِّل الأعداد العشرية والأعداد الصحيحة.
	</li>
	<li>
		<code>string</code>: يمثِّل السلاسل النصية.
	</li>
	<li>
		<code>boolean</code>: يمثِّل القيم المنطقية: <code>true/false</code>.
	</li>
	<li>
		<code>null</code>: هذا النوع يعني أن القيمة «فارغة» أو «غير موجودة».
	</li>
	<li>
		<code>undefined</code>: هذا النوع يعني أن القيمة «غير معرّفة».
	</li>
	<li>
		<code>object</code> و <code>symbol</code>: يمثِّل الأول بنية معقدة من البيانات والثاني مُعرِّفًا فريدًا، لم نسلط الضوء عليهما بعد.
	</li>
</ul>
<p>
	يرجع المعامل <code>typeof</code> نوع القيمة، مع استثناءين:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_19" style="">
<span class="kwd">typeof</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">"object"</span><span class="pln"> </span><span class="com">// خطأ من أصل اللغة</span><span class="pln">
</span><span class="kwd">typeof</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(){}</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">"function"</span><span class="pln"> </span><span class="com">// تعامل الدوال معاملةً خاصة</span></pre>

<p>
	تجد المزيد في فصل «المتغيرات وأنواع البيانات».
</p>

<h2>
	الدوال التفاعلية
</h2>

<p>
	لمَّا كنا نستعمل المتصفح بيئة عمل لنا، فستكون دوال واجهة المستخدم الأساسية هي:
</p>

<ul>
<li>
		<code>prompt(question, [default])‎</code>: هي دالة تطرح السؤال <code>question</code>، ثم ترجع ما أدخله المستخدم أو تُرجع القيمة <code>null</code> في حال ألغى المستخدم عملية الإدخال (بالضغط على الزر "cancel").
	</li>
	<li>
		confirm(question)‎: هي دالة تطرح السؤال <code>question</code> ثم تُتيح لك الاختيار بين «موافق» (Ok) أو «إلغاء» (Cancel) ثم تعاد قيمة منطقية، <code>true/false</code>، تمثِّل هذا الاختيار.
	</li>
	<li>
		alert(message)‎: دالةٌ تُظهِر لك الرسالة <code>message</code> المُمرَّرة إليها فقط.
	</li>
</ul>
<p>
	تظهر جميع هذه الدوال نافذة صغيرة تدعى «النافذة المنبثقة الشرطية» (modal window، وهي عنصر تحكم رسومي)، فهي توقف تنفيذ الشيفرة وتمنع المستخدم من التفاعل مع صفحة الويب حتى يتفاعل معها.
</p>

<p>
	جرب تنفيذ المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_21" style="">
<span class="pln">let userName </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"ما اسمك؟‎"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"محمد"</span><span class="pun">);</span><span class="pln">
let isTeaWanted </span><span class="pun">=</span><span class="pln"> confirm</span><span class="pun">(</span><span class="str">"هل تريد كوبًا من الشاي؟"</span><span class="pun">);</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"الزائر: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> userName </span><span class="pun">);</span><span class="pln"> </span><span class="com">// محمد</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"أيريد كوبًا من الشاي؟"</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> isTeaWanted </span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span></pre>

<p>
	تجد المزيد في فصل «الدوال التفاعلية».
</p>

<h2>
	المعاملات
</h2>

<p>
	تدعم JavaScript المعاملات التالية:
</p>

<h3>
	المعاملات الحسابية
</h3>

<p>
	معاملات الحساب الأساسية وهي <code>* + - /</code> بالإضافة إلى المعامل <code>%</code> لإيجاد باقي القسمة، و أيضًا معامل القوة <code>**</code>.
</p>

<p>
	يدمج معامل الجمع الثنائي <code>+</code> السلاسل النصية. إذا كان أحد العاملين عبارة عن سلسلة نصية، فسيُحوَّل الآخر إلى سلسلة نصية أيضًا مثل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_23" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'1'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// '12', سلسلة نصية</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'2'</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// '12', سلسلة نصية</span></pre>

<h3>
	معاملات الإسناد
</h3>

<p>
	هنالك معامل إسناد بسيط وهو <code>a = b</code> ومعامل إسناد مركَّب مثل <code>a *= 2</code>.
</p>

<h3>
	المعاملات الثنائية
</h3>

<p>
	تعمل المعاملات الثنائية في المستوى المنخفض للبيانات أي في مستوى البتات، لذا ارجع إلى <a href="https://wiki.hsoub.com/JavaScript/Bitwise_Operators" rel="external">توثيقها</a> في موسوعة حسوب إن لزمتك.
</p>

<h3>
	المعاملات الشرطية
</h3>

<p>
	المعامل الوحيد الذي يحوي ثلاث عوامل هو معامل علامة استفهام <code>?</code> أو كما يسمى «المعامل الثلاثي»:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_27" style="">
<span class="pln">cond </span><span class="pun">?</span><span class="pln"> resultA </span><span class="pun">:</span><span class="pln"> resultB</span></pre>

<p>
	إذا تحقق الشرط <code>cond</code>، يُرجع المعامل القيمة <code>resultA</code>؛ خلا ذلك، يُرجع القيمة <code>resultB</code>.
</p>

<h3>
	المعاملات المنطقية
</h3>

<p>
	ينفِّذ المعاملان المنطقيان AND <code>&amp;&amp;</code> و OR <code>||</code> «دارة تقييم قصيرة» (short-circuit evaluation) ثمَّ يرجعان القيمة المُقيَّمة الناتجة. يُحوِّل المعامل المنطقي NOT <code>!</code> العامل الذي استدعي معه لقيمة منطقية ثم يُرجع القيمة المعاكسة له.
</p>

<ul>
<li>
		معاملات الموازنة يُحوّل معامل المساواة <code>==</code> القيم المختلفة إلى أعداد ثم يتحقق من المساواة (ما عدا القيمة الفارغة <code>null</code> والقيمة غير المُعرَّفة <code>undefined</code> التي تساوي بعضها بعضًا). إليك المثال التالي:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_29" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">''</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span></pre>

<p>
	وكذلك تفعل معاملات الموازنة الأخرى.
</p>

<p>
	فيما يخص معامل المساواة الصارمة <code>===</code> لا يُوحَّد نوع القيم المراد التحقق من تساويها، إذ تعد عملية التحقق من نوعين مختلفين بالنسبة لهذا المعامل عملية غير محققة دومًا (أي النوعان غير متساويين).
</p>

<p>
	تعدُّ القيمة الفارغة <code>null</code> والقيمة غير المحددة <code>undefined</code> حالة خاصة، إذ تساوي إحداهما الأخرى (عبر المعامل <code>==</code>) ولا تساويان أي شيء آخر.
</p>

<p>
	توازن إشارة الأكبر وإشارة الأصغر <code>&gt;/&lt;</code> بين كل محرفين متقابلين من السلسلتين النصيّتين المراد موازنتها مع بعضهما، وأما بالنسبة لموازنة أنواع البيانات الأخرى، فتُحوَّل أولًا إلى أعداد ثم توازن.
</p>

<h3>
	معاملات أخرى
</h3>

<p>
	هنالك معاملات أخرى غير شائعة الاستخدام مثل معامل الفاصلة.
</p>

<p>
	تجد المزيد في الفصول التالية: فصل «المعاملات في JavaScript» وفصل «معاملات الموازنة» وفصل «المعاملات المنطقية».
</p>

<h2>
	حلقات التكرار
</h2>

<p>
	لقد غطينا ثلاثة أنواع من حلقات التكرار هي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_31" style="">
<span class="com">// 1</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">condition</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// 2</span><span class="pln">
</span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">condition</span><span class="pun">);</span><span class="pln">
</span><span class="com">// 3</span><span class="pln">
</span><span class="kwd">for</span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	المتغير الذي يُعرَّف داخل حلقة التكرار <code>for(let...)‎</code> مرئيٌّ داخلها فقط، ولكن يمكنك حذف <code>let</code> وإعادة استخدام المتغير.
</p>

<p>
	يأمر الموجهان <code>break/continue</code> بإنهاء التكرار الحالي والعودة للحلقة (<code>continue</code>) أو الخروج من الحلقة بأكملها (<code>break</code>). يمكن استخدام اللافتات (labels) للتحكم بالحلقات المتداخلة وإنهائها مثلًا.
</p>

<p>
	تجد المزيد في فصل «حلقتي التكرار <code>while</code> و <code>for</code>». وسوف نتعرف لاحقًا على المزيد من حلقات التكرار.
</p>

<h2>
	التعبير <code>switch</code>
</h2>

<p>
	يمكن للتعبير <code>switch</code> أن يحل محل التعبير الشرطي <code>if</code>، إذ يمنحك طريقة وصفية أكثر لموازنة قيمة ما مع عدَّة قيم. ويستخدم معامل المساواة الصارمة <code>===</code> في عملية الموازنة. إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_33" style="">
<span class="pln">let age </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">'كم عمرك؟‎'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">18</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">18</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"لن يعمل"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// ‎الناتج سلسلة نصية وليس عدد</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="str">"18"</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"يعمل"</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"أي قيمة غير مساوية للقيمتين السابقتين"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تجد المزيد في فصل «التعبير switch».
</p>

<h2>
	الدوال
</h2>

<p>
	إليك ثلاث طرائق لإنشاء دالة في JavaScript: 1- التصريح عن دالة: تُعَّرف الدالة في سياق الشيفرة الرئيسية (ضمن النطاق العام) بشكل منفصل عن بقية التعليمات:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_35" style="">
<span class="kwd">function</span><span class="pln"> sum</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let result </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	2- تعبير دالة: تُنشَأ الدالة داخل تعبير برمجي أو داخل كتلة برمجية أخرى:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_37" style="">
<span class="pln">let sum </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let result </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	3- الدوال السهمية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7250_39" style="">
<span class="com">// التعبير في الطرف الأيمن</span><span class="pln">
let sum </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="com">// يمكن أن تمتد على عدة أسطر باستعمال الأقواس المعقوصة شرط إعادة شيء</span><span class="pln">
let sum </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// ...</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// دون معاملات</span><span class="pln">
let sayHi </span><span class="pun">=</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"مرحبًا"</span><span class="pun">);</span><span class="pln">
</span><span class="com">// مع معامل وحيد</span><span class="pln">
let </span><span class="kwd">double</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> n </span><span class="pun">=&gt;</span><span class="pln"> n </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span></pre>

<ul>
<li>
		قد تحتوي الدوال على متغيرات محلية، إذ تُعرَّف تلك المتغيرات داخل جسم الدالة وتبقى مرئيًّة داخل الدالة فقط.
	</li>
	<li>
		يمكن أن تملك المعاملات قيمًا افتراضية مثل: <code>function sum(a = 1, b = 2) {...}‎</code>.
	</li>
	<li>
		تُرجع الدوال قيمة ما دائمًا. وإذا لم يكن هناك الموجه <code>return</code>، فستكون تلك القيمة المعادة القيمة <code>undefined</code>. تجد المزيد في فصل «الدوال».
	</li>
</ul>
<h2>
	المزيد قادم
</h2>

<p>
	كان ما سبق قائمةً مختصرةً بميزات JavaScript. لقد تعرّفت إلى الآن على الأساسيات في JavaScript. أمَّا في الدروس القادمة، فستتعرف على المزيد من المميزات والمواضيع المتقدمة، لذا خذ استراحة وتهيَّأ جيدًا لما هو قادم.
</p>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/javascript-specials" rel="external nofollow">JavaScript specials</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%AA%D9%86%D9%82%D9%8A%D8%AD-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-chrome-r784/" rel="">تنقيح الأخطاء في Chrome</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%88%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D8%B3%D9%87%D9%85%D9%8A%D8%A9-r782/" rel="">تعابير الدوال والدوال السهمية</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">783</guid><pubDate>Wed, 22 Jan 2020 13:00:00 +0000</pubDate></item><item><title>&#x62A;&#x639;&#x627;&#x628;&#x64A;&#x631; &#x627;&#x644;&#x62F;&#x648;&#x627;&#x644; &#x648;&#x627;&#x644;&#x62F;&#x648;&#x627;&#x644; &#x627;&#x644;&#x633;&#x647;&#x645;&#x64A;&#x629; &#x641;&#x64A; &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A;</title><link>https://academy.hsoub.com/programming/javascript/%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%88%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D8%B3%D9%87%D9%85%D9%8A%D8%A9-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r782/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/18.jpg.d9e90c10841513ed56729f8c1b4568d5.jpg" /></p>

<p>
	الدالة ليست بنية سحرية تُبنَى بها الشيفرة في JavaScript، وإنما هي نوع خاص من القيم. يُطلق على الصياغة التي تُستخدم في بناء الدوال «التصريح عن دالة» (Function Declaration):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_7" style="">
<span class="kwd">function</span><span class="pln"> sayHi</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"مرحبًا"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هناك صياغة أخرى لبناء دالة تسمى «تعبير دالة» (function expression) وتبدو بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_9" style="">
<span class="pln">let sayHi </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"مرحبًا"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	تُعامل الدالة في هذه الصياغة مثل أي قيمة، إذ تُنشَأ ثم تُسنَد للمتغير <code>sayHi</code> كما توضح الشيفرة. بغض النظر عن الصياغة التي تُعرَّف بها الدالة، فهي مُجرَّد قيمة مُخزَّنة في المتغير <code>sayHi</code>. المراد من هذه الشيفرة هو نفسه في الشيفرة التي تسبقها: «إنشاء دالة ووضعها في المتغير <code>sayHi</code>».
</p>

<p>
	يمكن عرض الدالة ككل باستخدام <code>alert</code> دون الأقواس:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_11" style="">
<span class="kwd">function</span><span class="pln"> sayHi</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"Hello"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> sayHi </span><span class="pun">);</span><span class="pln"> </span><span class="com">// إظهار شيفرة الدالة</span></pre>

<p>
	لاحظ أنَّ السطر الأخير في الشيفرة لا يستدعي الدالة لتنفيذها، وذلك بسبب عدم وجود الأقواس بعد اسمها <code>sayHi</code>. العديد من لغات البرمجة لا تتأثر بذلك (أي لا تهتم بوجود هذه الأقواس)، ولكن JavaScript ليست منها.
</p>

<p>
	الدالة في JavaScript عبارة عن قيمة، لذا يمكن التعامل معها على أنها قيمة. يُظهِر الاستدعاء <code>alert( sayHi );‎</code> سلسلة نصية تمثِّل شيفرة الدالة المُعرَّفة بأكملها، أي الشيفرة المصدرية للدالة.
</p>

<p>
	الدالة عبارة عن قيمة خاصة، وأحد الأمور الخاصَّة التي تنفرد بها عن القيم العادية هي إمكانية استدعائها وتنفيذها وذلك بوضع الأقواس بعد اسمها بالشكل <code>sayHi()‎</code> في أي مكان داخل الشيفرة. على أي حال، الدالة تبقى قيمة ولا مشكلة في معاملتها مثل أنواع القيم الأخرى. فيمكنك مثلًا إسناد دالة إلى متغير آخر:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_13" style="">
<span class="kwd">function</span><span class="pln"> sayHi</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">   </span><span class="com">// (1) إنشاء</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"مرحبًا"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
let func </span><span class="pun">=</span><span class="pln"> sayHi</span><span class="pun">;</span><span class="pln">    </span><span class="com">// (2) نسخ</span><span class="pln">
func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// مرحبًا‎     // (3) تنفيذ النسخة المنسوخة عن الدالة</span><span class="pln">
sayHi</span><span class="pun">();</span><span class="pln"> </span><span class="com">// مرحبًا‎    //     !وهذا يعمل أيضًا ولمَ لا</span></pre>

<p>
	إليك تفصيلٌ لما تنفِّذه الشيفرة السابقة:
</p>

<ol>
<li>
		ينشئ التصريح عن الدالة في السطر <code>(1)</code>الدالة ثمَّ يضعها في المتغير <code>sayHi</code>.
	</li>
	<li>
		تُنسَخ الدالة في السطر <code>(2)</code> إلى المتغير <code>func</code>. لاحظ هنا عدم وجود أقواس استدعاء الدالة بعد <code>sayHi</code>. إذا أُضيفَت هذه الأقواس فإنَّ الاستدعاء <code>func = sayHi()‎</code> سوف يُسنِد الناتج الذي تعيده الدالة إلى المتغير <code>func</code> وليس الدالة <code>sayHi</code> نفسها.
	</li>
	<li>
		يمكنك الآن استدعاء الدالة عبر استدعاء <code>sayHi()‎</code> أو <code>func()‎</code>.
	</li>
</ol>
<p>
	يمكنك أيضًا استخدم تعبير الدالة للتصريح عن الدالة <code>sayHi</code> في السطر الأول:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_15" style="">
<span class="pln">let sayHi </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
let func </span><span class="pun">=</span><span class="pln"> sayHi</span><span class="pun">;</span><span class="pln">
</span><span class="com">// ...</span></pre>

<p>
	كلا التعبيرين يعطيان النتيجة نفسها.
</p>

<h3>
	ملاحظة حول وجود الفاصلة المنقوطة في نهاية تعبير الدالة
</h3>

<p>
	قد تتساءل عن سبب وجود الفاصلة المنقوطة في نهاية «تعبير الدالة»، وعدم وجودها في نهاية «تعريف الدالة»:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_17" style="">
<span class="kwd">function</span><span class="pln"> sayHi</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
let sayHi </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	الجواب بسيط:
</p>

<ul>
<li>
		ليس هناك حاجة للفاصلة المنقوطة <code>;</code> في نهاية كتل التعليمات البرمجية والصِيغ التي تستخدمها مثل <code>if { ... }‎</code>، و <code>function f { }‎</code>، و <code>for { }‎</code> …إلخ.
	</li>
	<li>
		يُعدُّ تعبير الدالة، <code>let sayHi = ...;‎</code>، تعليمة برمجية (statement) ويُستخدَم على أنَّه قيمة أي هو ليس كتلة برمجية (code block) ولكنه عملية إسنادٍ لقيمة. تكتب الفاصلة المنقوطة <code>;</code> في نهاية التعليمات البرمجية، بغض النظر عن ماهية هذه التعليمات؛ لذلك، لا ترتبط الفاصلة المنقوطة بتعبير الدالة نفسه إطلاقًا، وإنها فقط تُنهِي التعليمة البرمجية.
	</li>
</ul>
<h2>
	دوال رد النداء
</h2>

<p>
	إليك مزيدًا من الأمثلة حول تمرير الدوال على أنَّها قيم واستخدام تعابير الدوال.
</p>

<p>
	سنكتب الدالة <code>ask(question, yes, no)‎</code> التي تقبل تمرير ثلاثة معاملات إليها:
</p>

<ul>
<li>
		المعامل <code>question</code>: يمثِّل نص السؤال.
	</li>
	<li>
		المعامل <code>yes</code>: يُمثِّل دالة يراد تنفيذها إذا كانت إجابة المعامل <code>question</code> هي <code>yes</code>.
	</li>
	<li>
		المعامل <code>no</code>: يمثِّل دالة يراد تنفيذها إذا كانت إجابة المعامل <code>question</code> هي <code>no</code>.
	</li>
</ul>
<p>
	تطرح الدالة السؤال <code>question</code>، وبناءً على إجابة المستخدم، تُستدعى الدالة <code>yes()‎</code> أو الدالة <code>no()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_19" style="">
<span class="kwd">function</span><span class="pln"> ask</span><span class="pun">(</span><span class="pln">question</span><span class="pun">,</span><span class="pln"> yes</span><span class="pun">,</span><span class="pln"> no</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">confirm</span><span class="pun">(</span><span class="pln">question</span><span class="pun">))</span><span class="pln"> yes</span><span class="pun">()</span><span class="pln">
  </span><span class="kwd">else</span><span class="pln"> no</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> showOk</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"لقد وافقت!"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> showCancel</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"لقد ألغيت التنفيذ."</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// ask على أنها وسائط إلى الدالة showOk و showCancel تمرر الدالتين</span><span class="pln">
ask</span><span class="pun">(</span><span class="str">"Do you agree?"</span><span class="pun">,</span><span class="pln"> showOk</span><span class="pun">,</span><span class="pln"> showCancel</span><span class="pun">);</span></pre>

<p>
	مثل هذه الدوال مفيدةٌ للغاية في الحياة العملية. ويتمثَّل الاختلاف الرئيسي بين التنفيذ الواقعي العملي والمثال النظري أعلاه في أنَّ الأولى تستخدم طرائقًا أكثر تعقيدًا للتفاعل مع المستخدم من مجرد دالة <code>confirm</code> بسيطة. تُظهِر مثل هذه الدالة نافذة أسئلة مُعدَّلة جميلة المظهر في المتصفح لكن هذا موضوع آخر متقدم.
</p>

<p>
	يسمى الوسيطين <code>showOk</code> و <code>showCancel</code> للدالة <code>ask</code> «<strong>بدوال ردود النداء</strong>» (callback functions) أو «<strong>ردود النداء</strong>» (callbacks) فقط.
</p>

<p>
	الفكرة القابعة خلف «رد النداء» هي تمرير دالة ثم توقُّع إعادة استدعائها لاحقًا إذا لزم الأمر. أي مثلها كَمَثِل ارتداد صدى الصوت وعودته للمنادي أو مناداة أحدهم بطلبِ تنفيذ أمرٍ وتوقع إجابة النداء (رد النداء) بنتيجة الفعل وغيرها من الأمثلة المستقاة من الواقع.
</p>

<p>
	في المثال السابق، تصبح الدالة <code>showOk</code> رد نداء للإجابة "نعم" (<code>yes</code>)، والدالة <code>showCancel</code> رد نداء للإجابة "لا" (<code>no</code>). يمكن استخدام تعبير دالة لكتابة الدالة نفسها بشكل أقصر:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_21" style="">
<span class="kwd">function</span><span class="pln"> ask</span><span class="pun">(</span><span class="pln">question</span><span class="pun">,</span><span class="pln"> yes</span><span class="pun">,</span><span class="pln"> no</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">confirm</span><span class="pun">(</span><span class="pln">question</span><span class="pun">))</span><span class="pln"> yes</span><span class="pun">()</span><span class="pln">
  </span><span class="kwd">else</span><span class="pln"> no</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
ask</span><span class="pun">(</span><span class="pln">
  </span><span class="str">"هل تقبل؟"</span><span class="pun">,</span><span class="pln">
  </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"لقد قبلت."</span><span class="pun">);</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"لقد ألغيت التنفيذ."</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">);</span></pre>

<p>
	تُعرَّف الدوال هنا مباشرةً داخل الدالة <code>ask(...)‎</code> ولا تملك اسمًا في هذه الحالة، لذا يُطلَّق عليها «دوال مجهولة» (anonymous). لا يمكن الوصول إلى مثل هذه الدوال من خارج الدالة <code>ask(...)‎</code> (لعدم إسنادها إلى متغيرات) ولا يهمنا هذا الأمر هنا.
</p>

<h3>
	ملاحظة: الدالة عبارة عن قيمة تمثل «إجراء»
</h3>

<p>
	القيم العادية مثل السلاسل النصية أو الأعداد تمثِّل البيانات ولكن يمكن اعتبار الدالة -بما أنها قيمة خاصة- على أنَّها إجراء، لذا يمكنك تمريرها بين المتغيرات وتنفيذها عند الحاجة.
</p>

<h2>
	تعبير الدوال مقابل التصريح عن الدوال
</h2>

<p>
	يسلط هذا القسم الضوء على الاختلافات الرئيسية بين تعبير الدوال (Function Expressions) والتصريح عن الدوال (Function Declarations).
</p>

<p>
	أولًا، الصياغة: كيف نفرِّق بينهما في الشيفرة.
</p>

<ul>
<li>
		التصريح عن دالة: يُصرَّح عن الدالة في سياق الشيفرة الرئيسية بشكل منفصل عن بقية التعليمات البرمجية.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_23" style="">
<span class="com">// التصريح عن دالة</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> sum</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		تعبير دالة: تُنشَأ الدالة داخل تعبير برمجي (expression) أو داخل صياغة بانية أخرى. هنا، أُنشئَت الدالة في الجانب الأيمن من «تعبير الإسناد» (الإشارة <code>=</code>):
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_25" style="">
<span class="com">// تعبير دالة</span><span class="pln">
let sum </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يظهر الفرق جليًّا عندما يُنشِئ محرك JavaScript كلتا الدالتين.
</p>

<p>
	<strong>يُنشَأ تعبير الدالة عندما يصل تنفيذ الشيفرة إليه ويصبح جاهزًا للاستخدام من تلك اللحظة فقط</strong>.
</p>

<p>
	بمجرد أن ينتقل تنفيذ الشيفرة إلى الجانب الأيمن من معامل الإسناد، <code>let sum = function…‎</code>، تُنشَأ الدالة وتستطيع استخدامها بدءًا من تلك اللحظة (إسناد، استدعاء، …إلخ).
</p>

<p>
	التصريح عند الدوال مختلف بعض الشيء.
</p>

<p>
	<strong>يمكن استدعاء الدالة المُصرَّح عنها قبل أن يصل تنفيذ الشيفرة إليها</strong>. فمثلًا تبقى الدالة المُصرَّح عنها في المجال العام مرئيَّةً لجميع أجزاء السكربت كله (أي يمكن أي يمكن استدعاؤها من أي مكان)، بغض النظر عن مكان وجودها في الشيفرة.
</p>

<p>
	ذلك الأمر عائدٌ لخوارزميات داخلية تنفِّذها JavaScript قبل تنفيذ الشيفرة. فعندما تستعد JavaScript لتنفيذ سكربت ما، فإنَّها تبحث أولًا عن الدوال المصرَّح عنها في النطاق العام فيه وتنشئها. الأمر مشابه «لمرحلة التهيئة» (initialization stage). وبعد أن تعالج جميع تلك الدوال، تبدأ عملية تنفيذ الشيفرة، لذلك يمكن الوصول إليها من أي جزء من السكربت وتنفيذها. إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_27" style="">
<span class="pln">sayHi</span><span class="pun">(</span><span class="str">"جعفر"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// ‎مرحبًا، جعفر</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> sayHi</span><span class="pun">(</span><span class="pln">name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="pun">`مرحبًا،</span><span class="pln"> $</span><span class="pun">{</span><span class="pln">name</span><span class="pun">}`</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تُنشَأ الدالة <code>sayHi</code> المُصرَّح عنها في المجال العام عندما تستعد JavaScript لتنفيذ السكربت، وتصبح مرئية في كامل أرجائه. لاحظ هنا أن السكربت لن يعمل كما سبق في حال استخدمت تعبير دالة بدلًا من عملية التصريح:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_29" style="">
<span class="pln">sayHi</span><span class="pun">(</span><span class="str">"جعفر"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// ‎!خطأ</span><span class="pln">
let sayHi </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">  </span><span class="com">// (*) ;-) بَطُل مفعول السحر هنا </span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="pun">`</span><span class="typ">Hello</span><span class="pun">,</span><span class="pln"> $</span><span class="pun">{</span><span class="pln">name</span><span class="pun">}`</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	تُنشَأ الدالة هنا عند وصول التنفيذ إليها، يحدث ذلك في السطر <code>(*)</code>، لتعريفها بتعبيرٍ ويكون ذلك أي بعد فوات الأوان.
</p>

<p>
	ميزة أخرى خاصة بعملية التصريح عن الدوال هي نطاق الكتلة الخاصة بها (block scope). <strong>فإن طُبِّق الوضع الصارم (strict mode) في السكربت، تُرَى الدالة المُعرَّفة داخل كتلة برمجية ضمنها فقط ولا يمكن الوصول إليها من خارجها</strong>.
</p>

<p>
	على سبيل المثال، لنفترض أننا نريد تعريف الدالة <code>welcome()‎</code> بناءً على قيمة المتغير <code>age</code> التي نحصل عليها أثناء تنفيذ السكربت من المستخدم. نلاحظ أن التنفيذ لن يسير على ما هو مخطط له إن صرحنا عن الدالة بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_31" style="">
<span class="pln">let age </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"كم عمرك؟‎"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">18</span><span class="pun">);</span><span class="pln">
</span><span class="com">// welcome التصريح الشرطي عن الدالة </span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">function</span><span class="pln"> welcome</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"مرحبًا!"</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">function</span><span class="pln"> welcome</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"السلام عليكم!"</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// ثم استعمالها لاحقًا</span><span class="pln">
welcome</span><span class="pun">();</span><span class="pln"> </span><span class="com">// غير معرّفة welcome خطأ: الدالة</span></pre>

<p>
	حصلنا على ذلك الخطأ لأن الدالة المُصرَّح عنها داخل كتلة تبقى مرئية فقط ضمن نطاقها.دعنا نعدِّل على المثال السابق في محاولة لحل المشكلة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_33" style="">
<span class="pln">let age </span><span class="pun">=</span><span class="pln"> </span><span class="lit">16</span><span class="pun">;</span><span class="pln"> </span><span class="com">// لنعتمد العمر 16 مثلًا</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  welcome</span><span class="pun">();</span><span class="pln">              </span><span class="com">// \   (تنفيذ)</span><span class="pln">
                          </span><span class="com">//  |</span><span class="pln">
  </span><span class="kwd">function</span><span class="pln"> welcome</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">    </span><span class="com">//  |</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"مرحبًا!"</span><span class="pun">);</span><span class="pln">         </span><span class="com">//‎  |  تعريف الدالة موجود داخل النطاق حيث استدعيت</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">                       </span><span class="com">//  |  </span><span class="pln">
                          </span><span class="com">//  |</span><span class="pln">
  welcome</span><span class="pun">();</span><span class="pln">              </span><span class="com">// /   (تنفيذ)</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">function</span><span class="pln"> welcome</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">    </span><span class="com">// لمَّا كان العمر 16، لن تُنشَأ هذه الدالة</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"السلام عليكم!"</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// لم يعد هنالك نطاق (مجال) لأي كتلة هنا لعدم وجود أقواس معقوصة</span><span class="pln">
</span><span class="com">// لذا، لن نستطيع رؤية الدالتين المنشأتين داخل الكتلتين السابقتين</span><span class="pln">
welcome</span><span class="pun">();</span><span class="pln"> </span><span class="com">// غير معرّفة welcome خطأ: الدالة</span></pre>

<p>
	ما الذي يمكن فعله لجعل الدالة <code>welcome</code> مرئية خارج نطاق الكتلة <code>if</code> الشرطية؟ تتمثَّل الطريقة الصحيحة في استخدام تعبير الدوال وذلك بإسناد تنفيذ الدالة <code>welcome</code> لمتغير يُعرَّف في النطاق العام لتصبح مرئية خارج الشرط <code>if</code>. لاحظ أنَّ الشيفرة تعمل على النحو المطلوب بهذه الطريقة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_35" style="">
<span class="pln">let age </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"كم عمرك؟‎"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">18</span><span class="pun">);</span><span class="pln">
let welcome</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  welcome </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"مرحبًا!"</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  welcome </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"السلام عليكم!"</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
welcome</span><span class="pun">();</span><span class="pln"> </span><span class="com">// تمام، لا يوجد أي خطأ</span></pre>

<p>
	بإمكانك ببساطة استخدام معامل علامة الاستفهام <code>?</code> بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_37" style="">
<span class="pln">let age </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"كم عمرك؟‎"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">18</span><span class="pun">);</span><span class="pln">
let welcome </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln">
  </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"مرحبًا!"</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">:</span><span class="pln">
  </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"السلام عليكم!"</span><span class="pun">);</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
welcome</span><span class="pun">();</span><span class="pln"> </span><span class="com">// تمام، لا يوجد أي خطأ</span></pre>

<h3>
	متى عليك التصريح عن الدالة ومتى تستعمل تعبير الدالة؟
</h3>

<p>
	تمنح عملية التصريح عن الدوال حريةً أكبر في تنظيم الشيفرة، لتوفير إمكانية استدعاء هذه الدوال قبل تعريفها وهذه أهم نقطة تُؤخذ في الحسبان عند المفاضلة بين التصريح والتعبير. أضف إلى ذلك أنَّ صياغة التصريح تُسهِّل قراءة الشيفرة أيضًا، إذ من الأسهل البحث عن <code>function f(…) {…}‎</code> في الشيفرة بدلًا من <code>let f = function(…) {…}‎</code>. فالتصريح ملفت للنظر أكثر من التعبير.
</p>

<p>
	وإذا كان التصريح غير مناسب لسبب ما، أو احتجت إلى تعريف مشروط لدالة (مثل المثال السابق)، فيجب عليك استخدام التعبير عوضًا عن التصريح.
</p>

<h2>
	الدوال السهمية
</h2>

<p>
	هناك صياغة بسيطة وموجزة لإنشاء الدوال تسمى «<a href="https://wiki.hsoub.com/JavaScript/Arrow_Functions" rel="external">الدوال السهمية</a>» (Arrow functions)، وغالبًا ما تكون أفضل من تعبير الدوال. سُمي هذا النوع من الدوال بالدوال السهمية لأنها تشبه السهم ببساطة، وإليك صياغتها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_41" style="">
<span class="pln">let func </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">arg1</span><span class="pun">,</span><span class="pln"> arg2</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...</span><span class="pln">argN</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> expression</span></pre>

<p>
	يُنشِئ هذا دالة <code>func</code> تملك الوسائط <code>arg1..argN</code>، وتُقيِّم التعبير <code>expression</code> على الجانب الأيمن ثم تُرجِع قيمته.
</p>

<p>
	لاحظ أنَّ السطر السابق يقابل الشيفرة التالية بالضبط:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_43" style="">
<span class="pln">let func </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">arg1</span><span class="pun">,</span><span class="pln"> arg2</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...</span><span class="pln">argN</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> expression</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	ولكنه أكثر إيجازًا. إليك مثال آخر:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_45" style="">
<span class="pln">let sum </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="com">/* صياغة الدالة السهمية أصغر من الصياغة العادية التالية
let sum = function(a, b) {
  return a + b;
};
*/</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> sum</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 3</span></pre>

<p>
	يمكن حذف الأقواس في حال كان لديك وسيط واحد فقط:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_47" style="">
<span class="com">// الصياغتان التاليتان متماثلتان</span><span class="pln">
</span><span class="com">// let double = function(n) { return n * 2 }</span><span class="pln">
let </span><span class="kwd">double</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> n </span><span class="pun">=&gt;</span><span class="pln"> n </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 6</span></pre>

<p>
	إذا لم يكن هناك أي وسيط، توضع أقواس فارغة بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_49" style="">
<span class="pln">let sayHi </span><span class="pun">=</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"مرحبًا!"</span><span class="pun">);</span><span class="pln">
sayHi</span><span class="pun">();</span></pre>

<p>
	يمكن استخدام الدوال السهمية كما يُستخدَم تعبير الدوال. فإليك مثال الدالة <code>welcome()‎</code> السابق باستعمال الدوال السهمية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_51" style="">
<span class="pln">let age </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"كم عمرك؟‎"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">18</span><span class="pun">);</span><span class="pln">
let welcome </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln">
  </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">'مرحبًا!'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln">
  </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"السلام عليكم!"</span><span class="pun">);</span><span class="pln">
welcome</span><span class="pun">();</span><span class="pln"> </span><span class="com">// تمام، الدالة تعمل</span></pre>

<p>
	تبدو الدوال السهمية للوهلة الاولى غير مألوفة وصعبة القراءة، لكن هذا سرعان ما يتغير عند اعتياد العينين على صيغة وهيكل تلك الدوال.
</p>

<p>
	الدوال السهمية مناسبة جدًا لكتابة إجراءات بسيطة بسطر واحد فقط وستحبها كثيرًا إن كنت كسولًا (ميزة الكسل في المبرمج إيجابية جدًا :-D ) وتستثقل كتابة كلمات كثيرة.
</p>

<h3>
	ملاحظة: الدوال السهمية متعددة الأسطر
</h3>

<p>
	الأمثلة أعلاه أخذت الوسائط الموجودة على يسار المعامل <code>&lt;=</code>، ومررتها إلى التعبير <code>expression</code> الموجود على جانبها الأيمن لتقييمه.
</p>

<p>
	نحتاج في بعض الأحيان إلى شيء أكثر تعقيدًا، مثل التعابير والجمل البرمجية المتعددة، إذ في هذه الحالة استخدام الأقواس المعقوصة ثم استخدام الموجه <code>return</code> داخلها. إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_53" style="">
<span class="pln">let sum </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">  </span><span class="com">// يفتتح القوس المعقوص دالة متعددة الأسطر</span><span class="pln">
  let result </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln"> </span><span class="com">// للحصول على نتائج return إن استعملت الأقواس المعقوصة، فاستعمل</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> sum</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 3</span></pre>

<h3>
	ملاحظة: ما زال هنالك المزيد!
</h3>

<p>
	تناول هذا الدرس الدوال السهمية بإيجاز، لكن هذا ليس كل شيء! الدوال السهمية لها ميزات أخرى مثيرة للاهتمام، لذا سنعود إليها لاحقًا في الفصل «زيارة الدوال السهمية مجدَّدًا». يمكننا في الوقت الحالي استخدامها مع إجراءات السطر الواحد وردود النداء.
</p>

<h2>
	الخلاصة
</h2>

<ul>
<li>
		الدالة عبارة عن قيمة يمكن إسنادها أو نسخها أو تعريفها في أي مكان في الشيفرة.
	</li>
	<li>
		إن صُرِّح عن دالة في تعليمة برمجية (statement) منفصلة في سياق الشيفرة الرئيسية (النطاق العام)، فذلك يدعى «التصريح عن دالة».
	</li>
	<li>
		إن أُنشئت دالة في تعبير برمجي (expression)، فذلك يدعى «تعبير دالة».
	</li>
	<li>
		تعالج الدوال المُصرَّح عنها قبل تنفيذ الكتلة البرمجية (السكربت) الحاوية لها، وتصبح - نتيجةً لذاك - مرئيةً في أي مكان داخل الكتلة.
	</li>
	<li>
		تُنشَأ الدالة المُعرَّفة بوساطة تعبير عندما يحين دورها في التنفيذ بحسب مكان وجودها في السكربت.
	</li>
</ul>
<p>
	التصريح هو الخيار المفضل والشائع في إنشاء الدوال، لتوفير إمكانية رؤية الدالة قبل أن يحين دورها في التنفيذ حيثما كان موضعها في السكربت. أضف إلى ذلك أنه يساعد على تنظيم الشيفرة ويُسهِّل من قراءتها.
</p>

<p>
	من جهة أخرى، يُفضَّل تجنب استخدام تعبير الدوال إلا في الحالات التي لا يكون الصريح فيها ملائمًا. لقد تعرفت على مثالين في هذا الدرس يشرحان هذه النقطة، وسترى المزيد من الأمثلة في الدروس القادمة.
</p>

<p>
	أخيرًا، وجدنا أن الدوال السهمية مفيدةٌ جدًا خصوصًا في كتابة إجراءات بسطر واحد، وتأتي بشكلين:
</p>

<ol>
<li>
		بدون أقواس معقوصة: <code>‎(...args) =&gt; expression</code>، الجانب الأيمن عبارة عن تعبير، إذ تقيِّمه وترجع الناتج.
	</li>
	<li>
		مع أقواس معقوصة: <code>‎(...args) =&gt; { body }‎</code>، تساعدك الأقواس في كتابة تعليمات برمجية متعددة داخل الدالة الواحدة، لكننا بحاجة إلى الموجه <code>return</code> لإرجاع شيء ما.
	</li>
</ol>
<h2>
	تمارين
</h2>

<h3>
	اكتب الشيفرة التالية مجدَّدًا باستعمال الدوال السهمية
</h3>

<p>
	ضع دوالًا سهمية مقابلة لتعابير الدوال الموجودة في الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_55" style="">
<span class="kwd">function</span><span class="pln"> ask</span><span class="pun">(</span><span class="pln">question</span><span class="pun">,</span><span class="pln"> yes</span><span class="pun">,</span><span class="pln"> no</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">confirm</span><span class="pun">(</span><span class="pln">question</span><span class="pun">))</span><span class="pln"> yes</span><span class="pun">()</span><span class="pln">
  </span><span class="kwd">else</span><span class="pln"> no</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
ask</span><span class="pun">(</span><span class="pln">
  </span><span class="str">"هل تقبل؟"</span><span class="pun">,</span><span class="pln">
  </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"لقد قبلت."</span><span class="pun">);</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
  </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"لقد ألغيت التنفيذ."</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">);</span></pre>

<p>
	<strong>الحل</strong>
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8313_57" style="">
<span class="kwd">function</span><span class="pln"> ask</span><span class="pun">(</span><span class="pln">question</span><span class="pun">,</span><span class="pln"> yes</span><span class="pun">,</span><span class="pln"> no</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">confirm</span><span class="pun">(</span><span class="pln">question</span><span class="pun">))</span><span class="pln"> yes</span><span class="pun">()</span><span class="pln">
  </span><span class="kwd">else</span><span class="pln"> no</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
ask</span><span class="pun">(</span><span class="pln">
  </span><span class="str">"هل قبلت؟"</span><span class="pun">,</span><span class="pln">
  </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"لقد قبلت."</span><span class="pun">),</span><span class="pln">
  </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">"لقد ألغيت التنفيذ."</span><span class="pun">)</span><span class="pln">
</span><span class="pun">);</span></pre>

<p>
	تبدو الشيفرة واضحة وقصيرة، أليس كذلك؟
</p>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/function-expressions" rel="external nofollow">Function expressions</a> والفصل <a href="https://javascript.info/arrow-functions-basics" rel="external nofollow">Arrow functions, the basics</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D9%85%D8%B1%D8%A7%D8%AC%D8%B9%D8%A9-%D9%84%D9%85%D8%A7-%D8%B3%D8%A8%D9%82-r783/" rel="">مراجعة لما سبق</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-javascript-r781/" rel="">الدوال في JavaScript</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">782</guid><pubDate>Tue, 21 Jan 2020 13:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62F;&#x648;&#x627;&#x644; &#x641;&#x64A; &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A;</title><link>https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r781/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/17.jpg.17032e1f653c038898705f79c93a798b.jpg" /></p>

<p>
	قد تحتاج أحيانًا إلى تنفيذ إجراء مماثل في أكثر من موضع في السكربت مثل عرض رسالةٍ جميلةٍ للمستخدم عند تسجيل الدخول وتسجيل الخروج وربما في مكان آخر أيضًا.
</p>

<p>
	الدوال (Functions) عبارةٌ عن كتل برمجيَّة تُنفِّذ مجموعة من المهام وفق تسلسل مُحدَّد، فهي بذلك تُشكل «اللبنات الأساسية» للبرنامج. تسمح الدوال باستدعاء شيفرة ما عدَّة مرات دون الحاجة لكتابتها من جديد.
</p>

<p>
	لقد رأيت خلال الدروس السابقة أمثلةً على دوال مبنيَّة مسبقًا (built-in functions)، مثل <code>alert(message)‎</code>، و <code>prompt(message, default)‎</code>، و <code>confirm(question)‎</code>، ويمكنك أيضًا إنشاء دوال خاصَّة بك.
</p>

<h2>
	تعريف الدوال
</h2>

<p>
	تُعرَّف الدالة بالصياغة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_13" style="">
<span class="kwd">function</span><span class="pln"> showMessage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'مرحبًا بالجميع!'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تأتي الكلمة المفتاحية <code>function</code> أولًا، يليها اسم الدالة (<code>showMessage</code> في حالتنا)، ثم المعاملات (parameters) التي هي مجموعة من متغيرات تفصل فيما بينها بفاصلة لاتينية <code>,</code> (غير موجودة في المثال أعلاه لأنَّها اختياريَّة)، وأخيرًا جسم الدالة (function body) بين الأقواس المعقوصة وهو الإجراء المراد تنفيذه.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_15" style="">
<span class="kwd">function</span><span class="pln"> name</span><span class="pun">(</span><span class="pln">parameters</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// جسم الدالة</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تُستدعَى الدالة بكتابة اسمها متبوعًا بقوسين هلاليين () مثل <code>showMessage()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_17" style="">
<span class="kwd">function</span><span class="pln"> showMessage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="pun">مرحبًا</span><span class="pln"> </span><span class="pun">جميعًا!</span><span class="str">'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
showMessage</span><span class="pun">();</span><span class="pln">
showMessage</span><span class="pun">();</span></pre>

<p>
	يُنفِّذ الاستدعاء <code>showMessage()‎</code> جسم الدالة أي أنك سترى الرسالة مرتين.
</p>

<p>
	يوضِّح هذا المثال أحد أسباب استخدام الدوال، وهو تجنب تكرار الجمل البرمجية ذاتها. وفي حال أحتجت لتغيير الرسالة أو الطريقة التي تُعرَض بها، يكفي أن تُعدِّل الشيفرة من مكان واحد أي من الدالة فقط.
</p>

<h2>
	المتغيرات المحلية
</h2>

<p>
	المتغير الذي عُرِّف (صُرِّح عنه) داخل حدود دالةٍ ما مرئيٌّ فقط داخل هذه الدالة ويدعى أنذاك «متغيِّرًا محليًّا» (Local variable). إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_19" style="">
<span class="kwd">function</span><span class="pln"> showMessage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let message </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello, I'm JavaScript!"</span><span class="pun">;</span><span class="pln"> </span><span class="com">// متغِّير محلي</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> message </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
showMessage</span><span class="pun">();</span><span class="pln"> </span><span class="com">// Hello, I'm JavaScript!</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> message </span><span class="pun">);</span><span class="pln"> </span><span class="com">// &lt;-- خطأ! المتغيِّر محلي وموجود ضمن نطاق الدالة فقط</span></pre>

<h2>
	المتغيرات العامة
</h2>

<p>
	يُعرَّف المتغير العام (outer variable، ويدعى أيضًا global variable) خارج حدود الدالة ويمكنها الوصول إليه أيضًا مثل المتغيِّر <code>userName</code> في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_21" style="">
<span class="pln">let userName </span><span class="pun">=</span><span class="pln"> </span><span class="str">'محمد'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> showMessage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'مرحبًا، '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> userName</span><span class="pun">;</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln">message</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
showMessage</span><span class="pun">();</span><span class="pln"> </span><span class="com">// مرحبًا، محمد</span></pre>

<p>
	تملك الدالة الوصول الكامل إلى المتغير العام، إذ يمكنها التعديل عليه. فيمكننا مثلًا تعديل قيمة المتغيِّر <code>userName</code> العام من داخل الدالة قبل استعماله مثلًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_23" style="">
<span class="pln">let userName </span><span class="pun">=</span><span class="pln"> </span><span class="str">'محمد'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> showMessage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  userName </span><span class="pun">=</span><span class="pln"> </span><span class="str">"أحمد‎"</span><span class="pun">;</span><span class="pln"> </span><span class="com">// (1) تغيير قيمة المتغير العام</span><span class="pln">
  let message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'مرحبًا، '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> userName</span><span class="pun">;</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln">message</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> userName </span><span class="pun">);</span><span class="pln"> </span><span class="com">// محمد، قبل استدعاء الدالة</span><span class="pln">
showMessage</span><span class="pun">();</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> userName </span><span class="pun">);</span><span class="pln"> </span><span class="com">// أحمد، بعد تعديل الدالة قيمته</span></pre>

<p>
	تستخدم الدالة المتغير العام في حالة واحدة وهي عدم وجود متغير محلي.
</p>

<p>
	إذا عُرِّف متغير محلي داخل دالة يحمل اسم المتغير العام نفسه، يغطي المتغيرالمحلي على العام ضمن حدود الدالة ويطغى عليه. في الشيفرة أدناه مثلًا، تستخدم الدالة <code>showMessage()‎</code> المتغير <code>userName</code> الذي أنشئ محليًّا وتتجاهل المتغير الخارجي العام:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_25" style="">
<span class="pln">let userName </span><span class="pun">=</span><span class="pln"> </span><span class="str">'محمد'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> showMessage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let userName </span><span class="pun">=</span><span class="pln"> </span><span class="str">"أحمد‎"</span><span class="pun">;</span><span class="pln"> </span><span class="com">// التصريح عن متغيِّر محلي</span><span class="pln">
  let message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'مرحبًا، '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> userName</span><span class="pun">;</span><span class="pln"> </span><span class="com">// أحمد</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln">message</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// ستنشئ الدالة المتغيّر المحلي الخاص بها وتستعمله</span><span class="pln">
showMessage</span><span class="pun">();</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> userName </span><span class="pun">);</span><span class="pln"> </span><span class="com">// محمد، لم تغير الدالة المتغير العام أو تصل إليه</span></pre>

<p>
	ملاحظة: المتغيرات العامة هي المتغيرات التي تُعرَّف خارج حدود الدالة وتكون مرئيةً من أي دالة (إلا إن حُجِبَت [shadowed] بمتغيِّر محلي يحمل الاسم نفسه). يعدُّ الحد من استخدام المتغيرات العامة سلوكًا جيدًا، إذ تحوي الشيفرة الحديثة عددًا قليلًا من المتغيرات العامة أو لا تحتوي عليها إطلاقًا. ومعظم المتغيرات مُعرَّفةٌ داخل دوالها (أي الاقتصار على المتغيرات المحلية). تفيد المتغيرات العامة أحيانًا في تخزين بيانات على مستوى المشروع ككل (project-level data).
</p>

<h2>
	المعاملات
</h2>

<p>
	يمكنك تمرير أية بيانات إلى الدوال باستخدام «المعاملات» (Parameters، وتسمى أيضًا وسائط الدالة [function arguments]).
</p>

<p>
	فتملك الدالة في المثال التالي على معاملين هما: <code>from</code> و <code>text</code>.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_27" style="">
<span class="kwd">function</span><span class="pln"> showMessage</span><span class="pun">(</span><span class="pln">from</span><span class="pun">,</span><span class="pln"> text</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// text و from :الوسائط هي</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln">from </span><span class="pun">+</span><span class="pln"> </span><span class="str">': '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> text</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
showMessage</span><span class="pun">(</span><span class="str">'مريم'</span><span class="pun">,‎</span><span class="pln"> </span><span class="str">'مرحبًا!'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// ‎مريم: مرحبًا (*)</span><span class="pln">
showMessage</span><span class="pun">(</span><span class="str">'مريم'</span><span class="pun">,‎</span><span class="pln"> </span><span class="str">"كيف الحال؟"</span><span class="pun">);</span><span class="pln"> </span><span class="pun">‎</span><span class="com">// مريم: كيف الحال؟ (**)</span></pre>

<p>
	عندما تُستدعَى الدالة في السطر <code>(*)</code> والسطر <code>(**)</code>، تُنسَخ القيم المُعطاة إلى متغير محلي باسم <code>from</code> ومتغير محلي آخر باسم <code>text</code> ثم تستخدمها الدالة آن ذاك.
</p>

<p>
	إليك مثال آخر مهم أرجو التركيز عليه؛ لدينا متغيّر باسم <code>from</code> مرَّرناه إلى الدالة <code>showMessage()‎</code>. لاحظ أن التعديل على المتغير <code>from</code> مرئيٌّ فقط داخل الدالة ولا ينعكس خارجها، وذلك لأنَّ الدالة تحصل دائمًا على نسخة من قيمة المتغيِّر ثم تتركه وشأنه:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_29" style="">
<span class="kwd">function</span><span class="pln"> showMessage</span><span class="pun">(</span><span class="pln">from</span><span class="pun">,</span><span class="pln"> text</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  from </span><span class="pun">=</span><span class="pln"> </span><span class="str">'*'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> from </span><span class="pun">+</span><span class="pln"> </span><span class="str">'*'</span><span class="pun">;</span><span class="pln"> </span><span class="com">// بمظهر مختلف "from" إظهار</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> from </span><span class="pun">+</span><span class="pln"> </span><span class="str">': '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> text </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
let from </span><span class="pun">=</span><span class="pln"> </span><span class="str">"مريم"</span><span class="pun">;</span><span class="pln">
showMessage</span><span class="pun">(</span><span class="pln">from</span><span class="pun">,</span><span class="pln"> </span><span class="str">"مرحبًا"</span><span class="pun">);</span><span class="pln"> </span><span class="pun">‎</span><span class="com">// *مريم*: مرحبًا</span><span class="pln">
</span><span class="com">// لأن الدالة عدّلت على متغير محلي مسمًى باسمه "from" لا تتغير قيمة</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> from </span><span class="pun">);</span><span class="pln"> </span><span class="com">// مريم</span></pre>

<h2>
	القيم الافتراضية
</h2>

<p>
	إن لم تُمرَّر أية قيمة لمعاملات دالةٍ، تُصبِح قيمها آنذاك غير مُعرَّفة <code>undefined</code>. فيمكن استدعاء الدالة <code>showMessage(from, text)‎</code> التي ذكرناها مسبقًا مع تمرير قيمةٍ واحدةٍ لها مثل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_31" style="">
<span class="pln">showMessage</span><span class="pun">(</span><span class="str">"مريم"</span><span class="pun">);</span></pre>

<p>
	لا يُعدُّ هذا خطأً بل يُظهِر القيمة <code>"مريم: undefined"</code>. لمَّا لم تُعطَ قيمةٌ للمعامل <code>text</code>، فسيُفترَّض أن <code>text === undefined</code> (أي يُعطَى القيمة <code>showMessage</code>).
</p>

<p>
	إذا أردت إسناد قيمة افتراضية للمعامل <code>text</code>، فيمكنك تحديدها عبر معامل الإسناد <code>=</code> أثناء تعريف الدالة بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_33" style="">
<span class="kwd">function</span><span class="pln"> showMessage</span><span class="pun">(</span><span class="pln">from</span><span class="pun">,</span><span class="pln"> text </span><span class="pun">=</span><span class="pln"> </span><span class="str">"لم تُعطَ قيمة لـ text"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> from </span><span class="pun">+</span><span class="pln"> </span><span class="str">": "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> text </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
showMessage</span><span class="pun">(</span><span class="str">"مريم"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// text مريم: لم تُعطَ قيمة لـ </span></pre>

<p>
	إن لم تُمرَّر الآن قيمةٌ للمعامل <code>text</code>عند استدعاء الدالة، فستُسنَد له القيمة <code>"لم تُعطَ قيمة لـ text"</code> التي هي عبارة عن سلسلة نصية. ويمكن أيضًا أن تكون القيمة الافتراضية تعبيرًا معقَّدًا يُقيَّيم ثم تُسنَد القيمة الناتجة إليه إذا، وفقط إذا، لم تُعطَ قيمة لذلك المعامل؛ لذلك، الشيفرة التالية صحيحةٌ أيضًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_35" style="">
<span class="kwd">function</span><span class="pln"> showMessage</span><span class="pun">(</span><span class="pln">from</span><span class="pun">,</span><span class="pln"> text </span><span class="pun">=</span><span class="pln"> anotherFunction</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// text إذا لم تُمرَّر قيمة للمعامل anotherFunction() تُنفَّذ الدالة</span><span class="pln">
  </span><span class="com">// الحالية آنذاك text وتصبح القيمة التي تعيدها هي قيمة المعامل</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	ملاحظة حول تقييم المعاملات الافتراضية
</h3>

<p>
	يُقيّم المعامل الافتراضي في JavaScript في كل مرة تُستدعَى فيها الدالة دون المعامل المقابل له. ففي المثال أعلاه، تُستدعَى الدالة <code>anotherFunction()‎</code> في كل مرة تُستدعَى فيها الدالة <code>showMessage()‎</code> دون المعامل <code>text</code>.
</p>

<h3>
	ملاحظة حول الطراز القديم للمعاملات الافتراضية
</h3>

<p>
	لم تكن الإصدارات القديمة من JavaScript تدعم المعاملات الافتراضية، ولكن كان هناك طرائق بديلة لدعمها، قد تمر معك عند مراجعتك لسكربتات قديمة مثل التحقق الصريح من كون المعامل غير مُعرَّف بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_37" style="">
<span class="kwd">function</span><span class="pln"> showMessage</span><span class="pun">(</span><span class="pln">from</span><span class="pun">,</span><span class="pln"> text</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">text </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">undefined</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    text </span><span class="pun">=</span><span class="pln"> </span><span class="str">'no text given'</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> from </span><span class="pun">+</span><span class="pln"> </span><span class="str">": "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> text </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أو عن طريق استعمال المعامل <code>||</code> بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_39" style="">
<span class="kwd">function</span><span class="pln"> showMessage</span><span class="pun">(</span><span class="pln">from</span><span class="pun">,</span><span class="pln"> text</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// غير معطاة (أي غير معرفة)، فستُستعمَل القيمة الافتراضية text إن كانت قيمة المعامل</span><span class="pln">
  text </span><span class="pun">=</span><span class="pln"> text </span><span class="pun">||</span><span class="pln"> </span><span class="str">'لم تُعطَ أية قيمة'</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	إرجاع قيمة
</h2>

<p>
	يمكن للدالة إرجاع قيمة معنيَّة إلى من استدعاها. وأبسط مثال على ذلك دالةٌ تجمع قيمتين ثم تعيد القيمة الناتجة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_41" style="">
<span class="kwd">function</span><span class="pln"> sum</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
let result </span><span class="pun">=</span><span class="pln"> sum</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> result </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 3</span></pre>

<p>
	يمكن أن يقع الموجه <code>return</code> في أي مكان داخل الدالة، ولكن انتبه لأن تنفيذ الدالة يتوقف عند الوصول إليه، وتُعَاد القيمة (أو ناتج تقييم تعبير برمجي) التي تليه إلى من استدعاها (<code>result</code> أعلاه).
</p>

<p>
	قد تحوي دالةٌ واحدةٌ عدَّة موجهات <code>return</code> مثل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_43" style="">
<span class="kwd">function</span><span class="pln"> checkAge</span><span class="pun">(</span><span class="pln">age</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> confirm</span><span class="pun">(</span><span class="str">'هل تملك إذنًا من والديك؟'</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
let age </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">'كم عمرك؟‎'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">18</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> checkAge</span><span class="pun">(</span><span class="pln">age</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'سُمِح له/ا بالوصول'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'مُنِعـ/ت من الوصول'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن إنهاء تنفيذ الدالة فورًا عن طريق استخدام <code>return</code> دون قيمة مثل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_45" style="">
<span class="kwd">function</span><span class="pln"> showMovie</span><span class="pun">(</span><span class="pln">age</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> </span><span class="pun">!</span><span class="pln">checkAge</span><span class="pun">(</span><span class="pln">age</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"يبدأ عرض الفلم"</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// (*)</span><span class="pln">
  </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الشيفرة أعلاه، إذا كان التعبير <code>checkAge(age)‎</code> يُرجع القيمة <code>false</code>، فلن تُظهر عندئذٍ الدالة <code>alert</code> السلسلة النصية <code>showMovie</code>.
</p>

<h3>
	ملاحظة حول إرجاع قيمة غير مُعرَّفة
</h3>

<p>
	تُرجع دالةٌ القيمة <code>undefined</code> إن لم يلي الموجه <code>return</code> أية قيمة أو تعبير أو لم يكن موجودًا (أي لا تعيد الدالة أي شيء):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_47" style="">
<span class="kwd">function</span><span class="pln"> doNothing</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">/*  */</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> doNothing</span><span class="pun">()</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">undefined</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span></pre>

<p>
	بعبارة أخرى، حالة عدم إرجاع الدالة أي شيء وحالة استعمال <code>return;‎</code> فقط وحالة استعمال <code>return undefined;‎</code> كلها سواسية وهي أنَّ الدالة تعيد القيمة <code>undefined</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_49" style="">
<span class="kwd">function</span><span class="pln"> doNothing</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> doNothing</span><span class="pun">()</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">undefined</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span></pre>

<h3>
	تنبيه بخصوص إضافة سطر جديد بين الموجه <code>return</code> والقيمة المعادة
</h3>

<p>
	لا تضف سطرًا جديدًا بين الموجه <code>return</code> والقيمة (أو التعبير) التي يفترض أن تعيدها الدالة. فعند وجود تعبير طويل يلي <code>return</code>، قد تضعه في سطر منفصل مثل السطر التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_51" style="">
<span class="kwd">return</span><span class="pln">
 </span><span class="pun">(</span><span class="pln">some </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> expression </span><span class="pun">+</span><span class="pln"> or </span><span class="pun">+</span><span class="pln"> whatever </span><span class="pun">*</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">b</span><span class="pun">))</span></pre>

<p>
	ولكنَّ هذه الشيفرة لا تعمل، لأنَّ JavaScript تفترض من تلقاء نفسها وجود الفاصلة المنقوطة بعد <code>return</code>. أي أن هذه الشيفرة ستُقيَّم كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_53" style="">
<span class="kwd">return</span><span class="pun">;</span><span class="pln">
 </span><span class="pun">(</span><span class="pln">some </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> expression </span><span class="pun">+</span><span class="pln"> or </span><span class="pun">+</span><span class="pln"> whatever </span><span class="pun">*</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">b</span><span class="pun">))</span></pre>

<p>
	كما ترى، تصبح <code>return</code> فعليًّا فارغة ولا تُرجع الدالة أية قيمة؛ لذلك، يجب أن تكون القيمة المراد إرجاعها والموجه <code>return</code> على السطر نفسه. أي إن أردت وضع التعبير المراد إعادته على عدة أسطر، فيجب كتابة بدايته على السطر نفسه الموجود عليه الموجه <code>return</code> أو وضع قوس هلالي افتتاحي على أقل تقدير كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_55" style="">
<span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
  some </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> expression
  </span><span class="pun">+</span><span class="pln"> or </span><span class="pun">+</span><span class="pln">
  whatever </span><span class="pun">*</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">)</span></pre>

<p>
	وستعمل الشيفرة بالشكل المتوقع لها.
</p>

<h2>
	تسمية الدوال
</h2>

<p>
	الدوال عبارة عن إجراءات، لذلك من الأفضل تسميتها بفعل مختصر ودقيق قدر الإمكان يصف ما تقوم به ليسهل على قارئ الشيفرة الغريب فهم عملها.
</p>

<p>
	أحد ممارسات التسمية الشائعة استعمال فعل مصدري ابتدائي في بداية اسم الدالة لوصف الإجراء الرئيسي الذي تُنفِّذه باختصار. ومن الأفضل أن يتفق أعضاء الفريق على معنى أسماء هذه الأفعال البادئة المستخدمة. فالدوال التي تبدأ تسميتها بالفعل <code>"show"</code> مثلًا عادةً ما تُظهِر شيئًا ما.
</p>

<p>
	الدوال التي تبدأ عادةً بالفعل:
</p>

<ul>
<li>
		<code>"get…‎"</code> تجلب قيمة.
	</li>
	<li>
		<code>"calc…‎"</code> تحسب شيئًا ما.
	</li>
	<li>
		<code>"create…‎"</code> تنشئ شيئًا ما.
	</li>
	<li>
		<code>"check…‎"</code> تفحص شيئًا ما وتُرجع قيمة منطقية وهلم جرًّا.
	</li>
</ul>
<p>
	وإليك أمثلة على هذه الأسماء:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_57" style="">
<span class="pln">showMessage</span><span class="pun">(..)</span><span class="pln">     </span><span class="com">// إظهار رسالة</span><span class="pln">
getAge</span><span class="pun">(..)</span><span class="pln">          </span><span class="com">// (جلب العمر (بطريقة ما</span><span class="pln">
calcSum</span><span class="pun">(..)</span><span class="pln">         </span><span class="com">// حساب المجموع وإعادة الناتج</span><span class="pln">
createForm</span><span class="pun">(..)</span><span class="pln">      </span><span class="com">// (إنشاء إستمارة (وإعادتها غالبًا</span><span class="pln">
checkPermission</span><span class="pun">(..)</span><span class="pln"> </span><span class="com">// التحقق من إذنٍ وإعادة قيمة منطقية</span></pre>

<p>
	يتبادر لذهنك سريعًا ماهية العمل الذي تنفِّذه الدالة ونوع القيمة التي تُرجعها عند استخدام البادئات في تسمية الدوال استخدامًا ملائمًا وصحيحًا.
</p>

<h3>
	دالة واحدة مقابل إجراء واحد
</h3>

<p>
	يجب أن تُنفذ الدالة ما أشار لها اسمها بالضبط، لا أكثر ولا أقل. فعندما تُريد تنفيذ إجراءين مستقلين، يجب عليك تعريف دالتيّن مستقلتين، حتى لو جرى استدعاؤهما معًا (يمكنك في هذه الحالة تعريف دالة ثالثة تستدعي هاتين الدالتين).
</p>

<p>
	بعض الأمثلة لكسر هذه القاعدة:
</p>

<ul>
<li>
		<code>getAge</code> سيكون سيئًا إذا أظهرت الدالة العمر بتنبيه (يجب أن تجلب العمر وتعيده فقط).
	</li>
	<li>
		<code>createForm</code> سيكون سيئًا إذا عدَّلت الصفحة وأضافت الإستمارة إليها (يجب أن تنشئه وأن تعيده فقط).
	</li>
	<li>
		<code>checkPermission</code> سيكون سيئًا إذا عرضت رسالةً تشرح حالة الوصول (يجب أن تفحص الإذن وأن تعيد النتيجة فقط).
	</li>
</ul>
<p>
	تعتمد هذه الأمثلة على المعاني الشائعة لتلك البادئات. ولك مطلق الحرية أنت وفريقك في الاتفاق على معانٍ أخرى، لكن عادةً لا تختلف كثيرًا عما هو شائع لها. على أي حال، يجب أن يترسخ لديك فهمٌ لما تعنيه كل بادئة وما الأشياء التي يمكن أو لا يمكن للدوال الملحق اسمها ببادئة القيام بها. وأخيرًا، ينبغي للفريق تبادل هذا العُرف الموضوع.
</p>

<h3>
	أسماء دوال قصيرة جدًا
</h3>

<p>
	الدوال التي تُستخدَم بكثرة تملك أحيانًا أسماءً قصيرة جدًا مثل الدالة <a href="https://wiki.hsoub.com/jQuery/jQuery" rel="external"><code>$</code></a> المُعرَّفة في المكتبة <a href="https://wiki.hsoub.com/jQuery" rel="external">jQuery</a> والدالة <code>_</code> الأساسية الخاصة بالمكتبة <a href="http://lodash.com/" rel="external nofollow">Lodash</a>.
</p>

<p>
	تعد تلك الحالات استثنائية، ولكن يجب عمومًا أن تكون أسماء الدوال وصفية وموجزة.
</p>

<h2>
	الدوال == التعليقات
</h2>

<p>
	يجب أن تكون الدوال قصيرة وتُنفذ إجراءً واحدًا فقط. إذا كان هذا الإجراء معقد، فيفضَّل تقسيم الدالة إلى عدد من الدوال البسيطة. قد لا يكون اتباع هذه القاعدة في بعض الأحيان سهل، لكنه بالتأكيد أمر جيد.
</p>

<p>
	الدالة المنفصلة ليست سهلة الاختبار والتنقيح فقط بل تُعدُّ تعليقًا عظيم الشأن! فمثلًا وازن بين الدالتين <code>showPrimes(n)‎</code> أدناه، إذ تخرج كل واحدة منهما <a href="https://ar.wikipedia.org/wiki/%D8%B9%D8%AF%D8%AF_%D8%A3%D9%88%D9%84%D9%8A" rel="external nofollow">الأعداد الأولية</a> حتى العدد <code>n</code> المعطى.
</p>

<p>
	الدالة في المثال الأول تستخدم لافتة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_59" style="">
<span class="kwd">function</span><span class="pln"> showPrimes</span><span class="pun">(</span><span class="pln">n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  nextPrime</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> j </span><span class="pun">&lt;</span><span class="pln"> i</span><span class="pun">;</span><span class="pln"> j</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">%</span><span class="pln"> j </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">continue</span><span class="pln"> nextPrime</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span><span class="pln"> </span><span class="com">// عدد أولي</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الدالة في المثال الثاني تستخدم الدالة الإضافية <code>isPrime(n)‎</code> لاختبار الأعداد إذا كانت أولية أم لا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_61" style="">
<span class="kwd">function</span><span class="pln"> showPrimes</span><span class="pun">(</span><span class="pln">n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">isPrime</span><span class="pun">(</span><span class="pln">i</span><span class="pun">))</span><span class="pln"> </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">  </span><span class="com">// a prime</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> isPrime</span><span class="pun">(</span><span class="pln">n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> n </span><span class="pun">%</span><span class="pln"> i </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ أن المثال الثاني سهل الفهم، أليس كذلك؟ فنرى بدلًا من قطعة مبعثرة من الشيفرة اسم إجراءٍ (الذي هو <code>isPrime</code> في مثالنا). يشير الأشخاص أحيانًا إلى هذه الشيفرة بأنها «ذاتية الوصف» أي تصف نفسها بنفسها.
</p>

<p>
	بناءً على ذلك، يمكنك إنشاء الدوال حتى إذا لم ترد إعادة استخدامها وذلك لتنظيم الشيفرة وتسهيل قراءتها.
</p>

<h2>
	الخلاصة
</h2>

<p>
	صياغة تعريف دالة ما يبدو بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_63" style="">
<span class="kwd">function</span><span class="pln"> name</span><span class="pun">(</span><span class="pln">parameters</span><span class="pun">,</span><span class="pln"> delimited</span><span class="pun">,</span><span class="pln"> by</span><span class="pun">,</span><span class="pln"> comma</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">/* الإجراء الذي تنفذه الدالة */</span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		تُنسَخ القيم التي تُمرَّر إلى الدالة على أنها معاملات إلى متغيرات محلية تستخدمها الدالة.
	</li>
	<li>
		تستطيع أي دالة الوصول إلى المتغيرات العامة الخارجية، لكن أولوية الاستخدام تكون للمتغيرات المحلية ثم المتغيرات العامة (إن لم تتوفر المحلية). لا تملك الشيفرة التي تقع خارج حدود الدالة وصولًا إلى متغيراتها المحلية.
	</li>
	<li>
		يمكن للدالة إرجاع أي قيمة، أو القيمة <code>undefined</code> إن لم تُرجع أي شيء.
	</li>
</ul>
<p>
	يوصى باستخدام المتغيرات المحلية والمعاملات بشكل أساسي في الدالة وذلك لجعل الشيفرة واضحة وسهلة الفهم، وتجنب استخدام المتغيرات العامة قدر الإمكان.
</p>

<p>
	فهم عمل دالة تحتوي على معاملات وتستعملها ثم تُرجع قيمةً أسهل من فهم دالة لا تحتوي على أي معاملات، ولكنها تستعمل المتغيرات العامة وتعدل عليها.
</p>

<p>
	تسمية الدالة:
</p>

<ul>
<li>
		يجب أن يصف اسم الدالة الإجراء الذي تُنفِّذه بوضوح. عندما ترى استدعاءً لدالة في شيفرةٍ ما، فإن الاسم الجيد يساعدك على فهم ما ستُنفذه وما ستُرجعه على الفور.
	</li>
	<li>
		الدالة عبارة عن إجراء (فعل)، لذلك عادة ما تستعمل الأفعال المصدرية في تسمية الدوال.
	</li>
	<li>
		يوجد العديد من البادئات المشهورة في إلحاقها بأسماء الدوال مثل <code>create…‎</code>، و <code>show…‎</code>، و <code>get…‎</code>، و <code>check…‎</code> تُستخدَم للإشارة لما ستُنفذه هذه الدوال.
	</li>
</ul>
<p>
	الدوال هي اللبنات الأساسية في بناء الشيفرة. أصبحت الآن تملك فهمًا جيدًا للأساسيات ويمكنك البدء في إنشائها واستخدامها. سنطبق في الدروس القادمة كل ما تعملناه ونعود له مرارًا وتكرارًا والغوص أكثر في مواضيع متقدمة.
</p>

<h2>
	التمارين
</h2>

<h3>
	هل وجود التعبير البرمجي <code>else</code> مهم في الشيفرة؟
</h3>

<p class="task__importance">
	الأهمية: 4
</p>

<p>
	ترجع الدالة التالية القيمة <code>true</code> إذا كانت قيمة المعامل <code>age</code> أكبر من <code>18</code> وإلا فإنها تطلب تأكيدًا ثم ترجع نتيجته:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_65" style="">
<span class="kwd">function</span><span class="pln"> checkAge</span><span class="pun">(</span><span class="pln">age</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> confirm</span><span class="pun">(</span><span class="str">'هل أخذت إذن والديك؟'</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هل سيتغير عمل الدالة إذا حُذف التعبير <code>else</code>؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_67" style="">
<span class="kwd">function</span><span class="pln"> checkAge</span><span class="pun">(</span><span class="pln">age</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="com">// ...</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> confirm</span><span class="pun">(</span><span class="str">'Did parents allow you?'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هل يوجد اختلاف في سلوك هذين المثالين؟
</p>

<p>
	<strong>الحل</strong>
</p>

<div class="task__answer">
	<p>
		لا يوجد أي اختلاف.
	</p>
</div>

<h3>
	أعد كتابة الدالة باستخدام المعامل <code>?</code> أو المعامل <code>||</code>
</h3>

<p class="task__importance">
	الأهمية: 4
</p>

<p>
	ترجع الدالة التالية القيمة <code>true</code> إذا كانت قيمة المعامل <code>age</code> أكبر من <code>18</code> وإلا فإنها تطلب تأكيدًا وتُرجع نتيجته:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_69" style="">
<span class="kwd">function</span><span class="pln"> checkAge</span><span class="pun">(</span><span class="pln">age</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> confirm</span><span class="pun">(</span><span class="str">'هل يأذن لك والديك؟'</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أعد كتابة الدالة السابقة بدون استخدام التعبير الشرطي <code>if</code> لتنفيذ الإجراء نفسه الموضح أعلاه في سطر واحد.
</p>

<p>
	اكتب نموذجين مختلفين للدالة <code>checkAge</code>، وليكن النموذج الأول باستخدام المعامل الشرطي علامة الاستفهام <code>?</code>، والثاني باستخدام المعامل <code>||</code>.
</p>

<p>
	<strong>الحل</strong>
</p>

<div class="task__answer">
	<p>
		النموذج الأول باستخدام المعامل الشرطي علامة الاستفهام <code>?</code>:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_71" style="">
<span class="kwd">function</span><span class="pln"> checkAge</span><span class="pun">(</span><span class="pln">age</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> confirm</span><span class="pun">(</span><span class="str">'هل يأذن لك والديك؟'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

	<p>
		النموذج الثاني باستخدام المعامل <code>||</code> (النموذج الأبسط):
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_73" style="">
<span class="kwd">function</span><span class="pln"> checkAge</span><span class="pun">(</span><span class="pln">age</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> confirm</span><span class="pun">(</span><span class="str">'هل يأذن لك والديك؟'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

	<p>
		لاحظ أن الأقواس حول التعبير <code>age &gt; 18</code> ليست مطلوبة هنا لكن وجودها يُسهِّل قراءة الشيفرة.
	</p>
</div>

<h3>
	الدالة <code>min(a,b)‎</code>
</h3>

<p class="task__importance">
	الأهمية: 1
</p>

<p>
	اكتب الدالة <code>min(a,b)‎</code> التي ترجع قيمة العدد الأصغر من العددين <code>a</code> و <code>b</code> المعطيين. أي دالة مثل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_75" style="">
<span class="pln">min</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pln">
min</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pln">
min</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span></pre>

<p>
	<strong>الحل</strong>
</p>

<div class="task__answer">
	<p>
		النموذج الأول باستخدام التعبير الشرطي <code>if</code>:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_77" style="">
<span class="kwd">function</span><span class="pln"> min</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">&lt;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

	<p>
		النموذج الثاني باستخدام المعامل الشرطي علامة الاستفهام <code>?</code>:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_79" style="">
<span class="kwd">function</span><span class="pln"> min</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">&lt;</span><span class="pln"> b </span><span class="pun">?</span><span class="pln"> a </span><span class="pun">:</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

	<p>
		ملاحظة: في حال كان العددان متساويين <code>a == b</code>، لا فرق إذا أُرجِع الأول أم الثاني.
	</p>
</div>

<h3>
	الدالة <code>pow(x,n)‎</code>
</h3>

<p class="task__importance">
	الأهمية: 4
</p>

<p>
	اكتب الدالة <code>pow(x,n)‎</code> التي تُرجع قيمة العدد <code>x</code> مرفوع للقوة <code>n</code>. بعبارة أخرى، تُرجع ناتج ضرب العدد <code>x</code> في نفسه عدد <code>n</code> من المرات.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_81" style="">
<span class="pln">pow</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">9</span><span class="pln">
pow</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">27</span><span class="pln">
pow</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">...*</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span></pre>

<p>
	أنشئ صفحة ويب باستخدام الدالة <code>prompt</code> تسمح للمستخدم إدخال العدد <code>x</code> والعدد <code>n</code>، ثم تُظهر نتيجة الدالة <code>pow(x,n)‎</code>. ملاحظة: في هذا التمرين، يجب أن يكون العدد <code>n</code> من الأعداد الطبيعية الصحيحة وأكبر من العدد <code>1</code> أيضًا.
</p>

<p>
	<strong>الحل</strong>
</p>

<div class="task__answer">
	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8123_83" style="">
<span class="kwd">function</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let result </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    result </span><span class="pun">*=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
let x </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"x?"</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
let n </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"n?"</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(`القوة</span><span class="pln"> $</span><span class="pun">{</span><span class="pln">n</span><span class="pun">}</span><span class="pln"> </span><span class="pun">غير</span><span class="pln"> </span><span class="pun">مدعومة،</span><span class="pln"> </span><span class="pun">لذا</span><span class="pln"> </span><span class="pun">أدخل</span><span class="pln"> </span><span class="pun">عددًا</span><span class="pln"> </span><span class="pun">صحيحًا</span><span class="pln"> </span><span class="pun">أكبر</span><span class="pln"> </span><span class="pun">من</span><span class="pln"> </span><span class="pun">الصفر`);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> pow</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>
</div>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/function-basics" rel="external nofollow">Functions</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%88%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D8%B3%D9%87%D9%85%D9%8A%D8%A9-r782/" rel="">تعابير الدوال والدوال السهمية</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%8A%D9%85%D8%A9-switch-r780/" rel="">التعليمة switch</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">781</guid><pubDate>Sun, 19 Jan 2020 13:07:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x639;&#x644;&#x64A;&#x645;&#x629; switch &#x641;&#x64A; &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A;</title><link>https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%8A%D9%85%D8%A9-switch-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r780/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/16.jpg.3b71ab04a9e81ca33a672585dc648a7a.jpg" /></p>

<p>
	يمكن للتعليمة <code>switch</code> أن تحل محل الشرط <code>if</code> المُتعدِّد، إذ تمنحك طريقة وصفية أكثر لموازنة قيمة ما مع عدَّة متغيرات.
</p>

<h2>
	الصياغة
</h2>

<p>
	تحتوي التعليمة <code>switch</code> على واحدة أو أكثر من كتل <code>case</code> (حالة) وكتلة <code>default</code> (حالة افتراضية) أخيرة اختيارية.
</p>

<p>
	الصياغة العامة هي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8411_7" style="">
<span class="kwd">switch</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'value1'</span><span class="pun">:</span><span class="pln">  </span><span class="com">// if (x === 'value1')</span><span class="pln">
    </span><span class="pun">...</span><span class="pln">
    </span><span class="pun">[</span><span class="kwd">break</span><span class="pun">]</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'value2'</span><span class="pun">:</span><span class="pln">  </span><span class="com">// if (x === 'value2')</span><span class="pln">
    </span><span class="pun">...</span><span class="pln">
    </span><span class="pun">[</span><span class="kwd">break</span><span class="pun">]</span><span class="pln">
  </span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
    </span><span class="pun">...</span><span class="pln">
    </span><span class="pun">[</span><span class="kwd">break</span><span class="pun">]</span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		يُتحقَّق من المساواة الصارمة (strict equality) لقيمة المتغير <code>x</code> مع القيمة في الحالة <code>case</code> الأولى (أي <code>value1</code>) ثم الحالة الثانية (أي <code>value2</code>) وهلم جرًّا.
	</li>
	<li>
		في حال تحقَّقت المساواة الصارمة، يبدأ تنفيذ الشيفرة بدءًا من الكتلة البرمجية <code>case</code> المتطابقة حتى أقرب تعليمة خروج <code>break</code> (أو حتى نهاية التعليمة <code>switch</code> بأكملها).
	</li>
	<li>
		في حال لم تتحقق المساواة الصارمة مع أي حالة <code>case</code>، فستُنفَّذ كتلة <code>default</code> الافتراضيَّة (إن وجدت).
	</li>
</ul>
<h2>
	مثال تطبيقي
</h2>

<p>
	مثال على التعليمة <code>switch</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8411_9" style="">
<span class="pln">let a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">3</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'صغير جدًا'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">4</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'بالضبط!'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">5</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'كبير جدًا'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"لا أعرف ما هذه القيمة"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تبدأ <code>switch</code> هنا في موازنة المُتغيِّر <code>a</code> مع قيمة الحالة <code>case</code> الأولى التي هي <code>3</code>. لن تتحقق المطابقة في مثالنا لأنَّ قيمة <code>a</code> هي <code>4</code> ولكن ستتحقَّق مع قيمة الحالة الثانية، <code>4</code>. بعد تَحقُّق المطابقة، يبدأ تنفيذ الشيفرة الموجودة بين case 4 وحتى أقرب <code>break</code>.
</p>

<p>
	إذا لم يكن هناك تعليمة <code>break</code> (توقف وخروج)، ستُنفَّذ الحالة <code>case 5</code> (والحالات اللاحقة) أيضًا دون إجراء عملية التحقُّق.
</p>

<p>
	سنعيد كتابة المثال نفسه دون التعليمة <code>break</code> لترى الفرق:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8411_11" style="">
<span class="pln">let a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">3</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Too small'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">4</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Exactly!'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">5</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Too big'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"I don't know such values"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في المثال أعلاه، ستُنفَّذ الدوال <code>alert</code> الثلاث تنفيذًا متسلسلًا وكأننا ننفِّذ الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8411_13" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Exactly!'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Too big'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"I don't know such values"</span><span class="pln"> </span><span class="pun">);</span></pre>

<h3>
	أي تعبير برمجي يمكن أن يكون وسيطًا للمبدِّل <code>switch/case</code>
</h3>

<p>
	يمكنك تمرير تعابير تعسفية إلى <code>switch/case</code> مثل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8411_15" style="">
<span class="pln">let a </span><span class="pun">=</span><span class="pln"> </span><span class="str">"1"</span><span class="pun">;</span><span class="pln">
let b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(+</span><span class="pln">a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> b </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"this runs, because +a is 1, exactly equals b+1"</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"this doesn't run"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	قيمة التعبير <code>‎+a</code> هنا هي <code>1</code> والتي توازن مع قيمة التعبير <code>b + 1</code> في <code>case</code> لتُنفَّذ آنذاك الشيفرة المقابلة للقيمة المطابقة.
</p>

<h2>
	تجميع حالات <code>case</code> متعدِّدة
</h2>

<p>
	يمكنك تجميع العديد من الحالات <code>case</code> المختلفة لتتشارك الكتلة نفسها المراد تنفيذها عند تطابق إحداها. على سبيل المثال، إن أردنا تنفيذ الشيفرة نفسها للحالتين <code>case 3</code> و <code>case 5</code> (أي عندما تكون قيمة <code>a</code> هي 3 و 5)، نكتبهما بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8411_17" style="">
<span class="pln">let a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">4</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">'Right!'</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">3</span><span class="pun">:</span><span class="pln">                    </span><span class="com">// (*) جمع حالتين</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">5</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">'Wrong!'</span><span class="pun">);</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">"Why don't you take a math class?"</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="str">'The result is strange. Really.'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الآن، تُظهِر كلًا من الحالة <code>case 3</code> والحالة <code>case 5</code> الرسالة نفسها عند تطابق إحداهما.
</p>

<p>
	القدرة على تجميع الحالات هي أحد الآثار الجانبية لكيفيَّة تنفيذ <code>switch/case</code> دون الحاجة إلى الفاصل <code>break</code>. يبدأ هنا تنفيذ الحالة <code>case 3</code> (عند تطابقها) من السطر <code>(*)</code> ويمر عبر الحالة <code>case 5</code> بسبب عدم وجود التعليمة <code>break</code>.
</p>

<h2>
	نوع القيم
</h2>

<p>
	دعني أركز على أمر مهم يتعلق بالتحقق من المساواة وهو أنَّ عملية المساواة تكون «صارمة» دومًا. أي يجب أن تكون القيم من النوع نفسه دائمًا لتتساوى.
</p>

<p>
	لتكن لدينا الشيفرة التالية مثلًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8411_19" style="">
<span class="pln">let arg </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"أدخل قيمة عددية؟"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">arg</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'0'</span><span class="pun">:</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'1'</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'صفر أو واحد'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'2'</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'اثنان'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">3</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'لا تُنفَّذ أبدًا'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'قيمة مجهولة'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<ol>
<li>
		عند الحالة <code>0</code> والحالة <code>1</code>، تُنفَّذ الدالة <code>alert</code> الاولى.
	</li>
	<li>
		عند الحالة <code>2</code>، تُنفَّذ الدالة <code>alert</code> الثانية.
	</li>
	<li>
		لكن عند الحالة <code>3</code>، ناتج الدالة <code>prompt</code> هي السلسلة النصية <code>"3"</code>، والتي لا تحقق المساواة الصارمة <code>===</code> مع العدد <code>3</code>، لذا فإنَّ الشيفرة المكتوبة في الحالة <code>case 3</code> هي شيفرة ميتة ولا تُنفَّذ أبدًا. وستُنفَّذ آنذاك شيفرة الحالة <code>default</code> الافتراضيَّة.
	</li>
</ol>
<h2>
	تمارين
</h2>

<h3>
	أعد كتابة المبدِّل <code>switch</code> بصيغة الشرط <code>if</code>
</h3>

<p class="task__importance">
	الأهمية: 5
</p>

<p>
	اكتب الشرط <code>if..else</code> المقابل للمبدِّل <code>switch</code> التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8411_21" style="">
<span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">browser</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'Edge'</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"لديك المتصفح Edge!"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'Chrome'</span><span class="pun">:</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'Firefox'</span><span class="pun">:</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'Safari'</span><span class="pun">:</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'Opera'</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'حسنًا، نحن ندعم هذه المتصفحات أيضًا!'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'نرجو أن تظهر هذه الصفحة بمظهر جيد!'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الحل
</p>

<div class="task__answer">
	<p>
		لمحاكاة عمل التعليمة <code>switch</code> بدقَّة، يجب استخدام المساواة الصارمة <code>'==='</code> في الشرط <code>if</code>. ويمكنك استخدام المساواة <code>'=='</code> أيضًا مع السلاسل النصية المعروفة مسبقًا.
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8411_23" style="">
<span class="kwd">if</span><span class="pun">(</span><span class="pln">browser </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Edge'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="str">"لديك المتصفح Edge!"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">browser </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Chrome'</span><span class="pln">
 </span><span class="pun">||</span><span class="pln"> browser </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Firefox'</span><span class="pln">
 </span><span class="pun">||</span><span class="pln"> browser </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Safari'</span><span class="pln">
 </span><span class="pun">||</span><span class="pln"> browser </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Opera'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'حسنًا، نحن ندعم هذه المتصفحات أيضًا!'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'نرجو أن تظهر هذه الصفحة بمظهر جيد!'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

	<p>
		<strong>ملاحظة</strong>: كُتِب التعبير التالي: <code>browser == 'Chrome' || browser == 'Firefox' …‎</code> في الشيفرة أعلاه على أسطر متعدِّدة لتسهيل قراءته.
	</p>

	<p>
		على أي حال، تبقى صيغة التعليمة <code>switch</code> أكثر وضوحًا.
	</p>
</div>

<h3>
	أعد كتابة الشرط <code>if</code> بصيغة المبدِّل <code>switch</code>
</h3>

<p class="task__importance">
	الأهمية: 4
</p>

<p>
	اكتب المبدِّل <code>switch</code> المقابل للشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8411_25" style="">
<span class="pln">let a </span><span class="pun">=</span><span class="pln"> </span><span class="pun">+</span><span class="pln">prompt</span><span class="pun">(</span><span class="str">'a?'</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> a </span><span class="pun">==</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'2,3'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الحل
</p>

<div class="task__answer">
	<p>
		تتحول عملية التحقُّق الأولى والثانية إلى حالتين منفصلتين (أي <code>case</code>) بينما تُجمَع عملية التحقق الثالثة في حالتين معًا:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8411_27" style="">
<span class="pln">let a </span><span class="pun">=</span><span class="pln"> </span><span class="pun">+</span><span class="pln">prompt</span><span class="pun">(</span><span class="str">'a?'</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
  </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">3</span><span class="pun">:</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'2,3'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

	<p>
		ملاحظة: التعليمة <code>break</code> في آخر الشيفرة غير مطلوبة، ولكنها تجنبنا الحصول على خطأ في الصياغة مستقبلًا. فقد تود لاحقًا إضافة حالة <code>case</code> أخرى، مثل <code>case4</code>. فإذا نسيت إضافة <code>break</code> قبلها (لأنك لم تكتبها الآن، أي في نهاية <code>case3</code>)، فستواجه خطأ حتميًّا؛ لذلك، هذا نوع من الاحتياط والحذر المسبق من ارتكاب الأخطاء.
	</p>
</div>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/switch" rel="external nofollow">The "switch" statement</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-javascript-r781/" rel="">الدوال في JavaScript</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D8%AD%D9%84%D9%82%D8%AA%D8%A7-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-while-%D9%88-for-r779/" rel="">حلقتا التكرار while و for</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">780</guid><pubDate>Thu, 16 Jan 2020 13:00:00 +0000</pubDate></item><item><title>&#x62D;&#x644;&#x642;&#x62A;&#x627; &#x627;&#x644;&#x62A;&#x643;&#x631;&#x627;&#x631; while &#x648; for &#x641;&#x64A; &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A;</title><link>https://academy.hsoub.com/programming/javascript/%D8%AD%D9%84%D9%82%D8%AA%D8%A7-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-while-%D9%88-for-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r779/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/15.jpg.51116031b7c67a87660341f7c1f98ecc.jpg" /></p>

<p>
	نحتاج في بعض الأحيان لتكرار إجراء ما مثل إخراج قيم من قائمة واحدة تلو الأخرى أو تشغيل نفس الشيفرة للأعداد من 1 إلى 10 لكل عدد على حدة.
</p>

<p>
	حلقات التكرار (loops) عبارة عن وسيلة لتكرار شيفرة ما عدة مرات.
</p>

<h2>
	حلقة التكرار <code>while</code>
</h2>

<p>
	الصيغة الخاصة بها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_7" style="">
<span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">condition</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// الشيفرة المراد تكرار تنفيذها</span><span class="pln">
  </span><span class="com">// تدعى جسم الحلقة</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	طالما كان الشرط <code>condition</code> مُحققًا، أي <code>true</code>، تُنفذ الشيفرة الموجودة في جسم الحلقة. على سبيل المثال، تطبع حلقة التكرار أدناه قيمة المتغير <code>i</code> طالما كان الشرط <code>i &lt; 3</code> مُحققًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_11" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// إظهار 0 ثم 1 ثم 2</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span><span class="pln">
  i</span><span class="pun">++;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُسمى التنفيذ الواحد من جسم حلقة التكرار «تكرارًا» (iteration). ينفِّذ المثال السابق ثلاثة تكرارات. إذا كان <code>i++‎</code> غير موجود في المثال أعلاه، ستُكرَّر الحلقة (نظريًا) إلى اللانهاية. أمَّا عمليًا، يوقف المتصفح تكرار مثل هذه الحلقات اللانهائية عند حدٍّ معيَّن، ويمكنك إنهاء العملية أيضًا من طرف الخادم في JavaScript.
</p>

<p>
	شرط حلقة التكرار غير مقصور على تعبيرات الموازنة، بل يمكن أن يكون أي تعبير أو متغير: يُقّيم الشرط ويُحوّل إلى قيمة منطقية بواسطة حلقة التكرار <code>while</code>.
</p>

<p>
	على سبيل المثال، الطريقة الأقصر لكتابة <code>while (i != 0)‎</code> هي <code>while (i)‎</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_13" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// وتتوقف الحلقة false صفرًا 0، يُقيَّم إلى القيمة i عندما تصبح قيمة المتغير</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span><span class="pln">
  i</span><span class="pun">--;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	ليس هناك حاجة للأقواس المعقوصة عند كتابة سطر برمجي واحد
</h3>

<p>
	إذا كان جسم حلقة التكرار عبارة عن سطر واحد، يمكنك حذف الاقواس المعقوصة <code>{…}</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_15" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">--);</span></pre>

<h2>
	حلقة التكرار <code>do..while</code>
</h2>

<p>
	يمكن إزاحة شرط حلقة التكرار الى أسفل جسم الحلقة باستخدام الصيغة <code>do..while</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_17" style="">
<span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// جسم الحلقة</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">condition</span><span class="pun">);</span></pre>

<p>
	ستُنفذ أولًا الشيفرة الموجودة في جسم الحلقة ثم يتم التحقق من الشرط؛ فإذا كان الشرط مُحققًا، تُكرَّر هذه العملية مرة أخرى. إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_19" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span><span class="pln">
  i</span><span class="pun">++;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span></pre>

<p>
	تستخدم هذه الصيغة عندما ترغب في تنفيذ الشيفرة مرة واحدة على الأقل بغض النظر عن كون الشرط محققًا أم لا. عادة ما تُفضل الصيغة الأخرى: <code>while(…) {…}‎</code>.
</p>

<h2>
	حلقة التكرار <code>for</code>
</h2>

<p>
	تعد حلقة التكرار <code>for</code> أكثر حلقات التكرار شيوعًا. تبدو صياغة الحلقة بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_21" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">begin</span><span class="pun">;</span><span class="pln"> condition</span><span class="pun">;</span><span class="pln"> step</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// ... جسم الحلقة ...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إليك المثال التالي لتتعرف ماهية هذه الأجزاء <code>begin; condition; step</code>. تُنفِّذ حلقة التكرار أدناه الدالة <code>alert(i)‎</code> لقيمة المتغيِّر <code>i</code> العددية من <code>0</code> إلى <code>3</code> ( باستثناء العدد 3، لأن الشرط <code>i &lt; 3</code> لا يشمل العدد 3):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_25" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// إظهار 0 ثم 1 ثم 2</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يعرض الجدول التالي شرحًا مفصلًا لأجزاء حلقة التكرار السابقة:
</p>

<table>
<thead><tr>
<th>
				الجزء
			</th>
			<th>
				الشيفرة المقابلة
			</th>
			<th>
				الوظيفة
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				البدء (التهيئة)
			</td>
			<td>
				<code>i = 0</code>
			</td>
			<td>
				يُنفَّذ مرةً واحدةً لحظة ولوج الحلقة
			</td>
		</tr>
<tr>
<td>
				الشرط
			</td>
			<td>
				<code>i &lt; 3</code>
			</td>
			<td>
				يُتحقَّق من هذا الشرط قبل كل تكرار (دورة تنفيذ) للحلقة، فإذا كان غير محقَّق (<code>false</code>)، يوقف تنفيذ الحلقة.
			</td>
		</tr>
<tr>
<td>
				الجسم
			</td>
			<td>
				<code>alert(i)‎</code>
			</td>
			<td>
				يُنفَّذ ما دام الشرط محقَّقًا (<code>true</code>).
			</td>
		</tr>
<tr>
<td>
				الخطوة
			</td>
			<td>
				<code>i++‎</code>
			</td>
			<td>
				يُنفَّذ بعد تنفيذ جسم الحلقة في كل تكرار.
			</td>
		</tr>
</tbody>
</table>
<p>
	تعمل خوارزمية حلقة التكرار كالتالي:
</p>

<ul>
<li>
		دخول الحلقة:
		<ul>
<li>
				-&gt; إذا تحقَّق الشرط -&gt; نفِّذ جسم الحلقة ثمَّ نفِّذ الخطوة
			</li>
			<li>
				-&gt; إذا تحقَّق الشرط -&gt; نفِّذ جسم الحلقة ثمَّ نفِّذ الخطوة
			</li>
			<li>
				-&gt; إذا تحقَّق الشرط -&gt; نفِّذ جسم الحلقة ثمَّ نفِّذ الخطوة
			</li>
			<li>
				-&gt; …
			</li>
		</ul>
</li>
</ul>
<p>
	في حال كنت مبتدئًا، قد يساعدك ذلك في العودة إلى المثال وتدوين آلية تنفيذه خطوة بخطوة على الورق. إليك شرح لما يحدث في هذه الحالة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_27" style="">
<span class="com">// for (let i = 0; i &lt; 3; i++) alert(i)</span><span class="pln">
</span><span class="com">// دخول الحلقة</span><span class="pln">
let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="com">// إذا تحقَّق الشرط -&gt; نفِّذ جسم الحلقة ثمَّ نفِّذ الخطوة</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln"> i</span><span class="pun">++</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="com">// إذا تحقَّق الشرط -&gt; نفِّذ جسم الحلقة ثمَّ نفِّذ الخطوة</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln"> i</span><span class="pun">++</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="com">// إذا تحقَّق الشرط -&gt; نفِّذ جسم الحلقة ثمَّ نفِّذ الخطوة</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln"> i</span><span class="pun">++</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="com">// i == 3 أوقف الحلقة لعدم تحقُّق الشرط 3 &gt; 3 عند</span></pre>

<h3>
	التصريح عن المتغيرات داخل نطاق الحلقة
</h3>

<p>
	يُصرَّح عن المتغير <code>i</code> المسمى «بالعدَّاد» مباشرةً ضمن حلقة التكرار، لذا تكون متاحةً ضمن نطاقها فقط وغير ظاهرة للعموم.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_29" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 0, 1, 2</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln"> </span><span class="com">// خطأ! لا يوجد متغيِّر بهذا الاسم</span></pre>

<p>
	بدلًا من تعريف متغير جديد، يمكنك استخدام متغير معرَّف مسبقًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_31" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// استعمال متغير موجود مسبقًا</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 0, 1, 2</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln"> </span><span class="com">// يعرض القيمة 3 لوجوده ضمن النطاق العام</span></pre>

<h3>
	تجاهل بعض أجزاء التحكم بحلقة التكرار <code>for</code>
</h3>

<p>
	يمكن تجاهل أي جزء من أجزاء الحلقة <code>begin; condition; step</code> مثل حذف جزء التهيئة <code>begin</code> في حال لم يكن وجوده مهمًا كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_33" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="com">// المتغيِّر جاهز </span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// فلا حاجة لقسم التهيئة</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 0, 1, 2</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكنك أيضًا حذف الخطوة <code>step</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_35" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> i</span><span class="pun">++</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	فتصبح حينئذٍ الحلقة <code>for</code> مطابقة للحلقة <code>while (i &lt; 3)‎</code>.
</p>

<p>
	يمكنك فعليًا إزالة جميع الأجزاء، وخلق حلقة تكرار لانهائية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_37" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(;;)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// تكرار لا نهائي</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يرجى التحقق من وجود الفاصلتين المنقوطتين <code>;</code> في صيغة حلقة التكرار <code>for</code>. خلاف ذلك، سيُطلَق خطأ.
</p>

<h2>
	إيقاف حلقة التكرار
</h2>

<p>
	يتوقف تنفيذ حلقة التكرار عندم عدم تحقُّق الشرط أي أصبح التقييم المنطقي للشرط <code>false</code>. مع ذلك، يمكنك إيقاف تنفيذ الحلقة في أي وقت باستخدام التعليمة <code>break</code>.
</p>

<p>
	في المثال التالي، تطلب حلقة التكرار من المستخدم إدخال سلسلة من الأرقام عن طريق الدالة <code>prompt</code>، ويتوقف تنفيذ الحلقة عندما لا يُدخَل أي رقم:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_39" style="">
<span class="pln">let sum </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  let value </span><span class="pun">=</span><span class="pln"> </span><span class="pun">+</span><span class="pln">prompt</span><span class="pun">(</span><span class="str">"Enter a number"</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">value</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">break</span><span class="pun">;</span><span class="pln"> </span><span class="com">// (*)</span><span class="pln">
  sum </span><span class="pun">+=</span><span class="pln"> value</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Sum: '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> sum </span><span class="pun">);</span></pre>

<p>
	عند النظر إلى الشيفرة، تُنفَّذ الكلمة المفتاحية <code>break</code> في السطر <code>(*)</code> إذا أدخل المستخدم سطرًا فارغًا أو ألغى عملية الإدخال وبذلك تتوقف حلقة التكرار فورًا، وينتقل تنفيذ الشيفرة إلى السطر الأول بعد حلقة التكرار أي إلى الدالة <code>alert</code>.
</p>

<p>
	يمكن استعمال حلقة أبدية (لانهائية) مع الكلمة المفتاحية <code>break</code> في الحالات التي لا يُعرَّف فيها متى يصبح الشرط غير محقَّقٍ.
</p>

<h2>
	الاستمرار في التكرار التالي
</h2>

<p>
	الموجِّه <code>continue</code> هو "نسخة أخف" من الموجِّه <code>break</code>، إذ لا يوقف تنفيذ حلقة التكرار بأكملها بل يوقف تنفيذ التكرار الحالي فقط، وينتقل لتنفيذ التكرار التالي (إذا تحقق الشرط طبعًا). أي نستعمله في الحالات التي نرغب فيها بإيقاف تنفيذ التكرار الحالي والانتقال إلى التكرار التالي.
</p>

<p>
	حلقة التكرار أدناه تستخدم الموجِّه <code>continue</code> لإخراج القيم الفردية فقط من الأعداد 0 وحتى 10:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_41" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// إذا تحقق التعبير، تخطى جسم الحلقة وانتقل للتكرار التالي</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 1, 3, 5, 7, 9</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	فيما يخص القيم الزوجية <code>i</code>، يوقف التعبير البرمجي <code>continue</code> تنفيذ حلقة التكرار وينتقل إلى التكرار التالي في الحلقة <code>for</code> (مع الرقم التالي)، لذلك تظهر الدالة <code>alert</code> فقط القيم الفردية.
</p>

<h3>
	تقليل مستوى التداخل عبر الموجِّه <code>continue</code>
</h3>

<p>
	حلقة التكرار المسؤولة عن إخراج القيم الفردية سوف تبدو كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_43" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	من الناحية التقنية، هذا مشابه للمثال أعلاه. يمكنك استخدام الشرط <code>if</code> بدلًا من استخدام الموجِّه <code>continue</code>. ولكن سيؤدي ذلك لخلق مستوى إضافي من التداخل (استدعاء الدالة <code>alert</code> داخل الأقواس المعقوصة <code>{}</code>). تقل قابلية القراءة الإجمالية إذا كانت الشيفرة الموجودة داخل التعبير الشرطي <code>if</code> أطول من بضعة أسطر.
</p>

<h3>
	لا يُستخدم الموجهان <code>break/continue</code> في المعامل الشرطي الثلاثي <code>?</code>
</h3>

<p>
	لاحظ أنه لا يمكن استخدام البنى التي لا تشبه صياغتها التعابير البرمجية مع المعامل الثلاثي <code>?</code> تحديدًا موجهات مثل <code>break/continue</code>.
</p>

<p>
	إليك الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_45" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أعد كتابتها باستخدام المعامل الشرطي <code>?</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_47" style="">
<span class="pun">(</span><span class="pln">i </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln"> </span><span class="com">// هنا continue لا يسمح باستخدام الموجه</span></pre>

<p>
	توقفت الشيفرة عن العمل بسبب خطأ في الصياغة (syntax error)، وهذا سبب آخر لعدم استخدام المعامل <code>?</code> بدلًا من الشرط <code>if</code>.
</p>

<h2>
	تسمية حلقات التكرار
</h2>

<p>
	تحتاج في بعض الأحيان لإيقاف حلقات تكرار متداخلة ومتعددة في وقت واحد. على سبيل المثال، تُنفذ حلقتي تكرار في الشيفرة التالية على المتغيرين <code>i</code> و <code>j</code> ، لإخراج الإحداثيات <code>(i, j)</code> من <code>(0,0)</code> إلى <code>(3,3)</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_49" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> j </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> j</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    let input </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(`</span><span class="typ">Value</span><span class="pln"> at coords </span><span class="pun">(</span><span class="pln">$</span><span class="pun">{</span><span class="pln">i</span><span class="pun">},</span><span class="pln">$</span><span class="pun">{</span><span class="pln">j</span><span class="pun">})`,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// التي تليها؟ alert ماذا لو أردت الخروج من الحلقة والانتقال للدالة</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">'Done!'</span><span class="pun">);</span></pre>

<p>
	ستحتاج إلى طريقة لإيقاف حلقة التكرار إذا ألغى المستخدم الإدخال.
</p>

<p>
	استخدام الموجِّه <code>break</code> بعد <code>input</code> سيُوقف حلقة التكرار الداخلية فقط. هذا ليس كافيًا، فما الحل يا ترى؟! هنا يأتي دور اللافتات (labels)!
</p>

<p>
	اللافتة (label) عبارة عن مُعرِّف (وليست كلمةً محجوزةً) يتبعه نقطتين رأسيتين وتأتي قبل حلقة التكرار مباشرةً:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_51" style="">
<span class="pln">labelName</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يوقف الموجِّه <code>break &lt;labelName&gt;‎</code> في المثال أدناه تنفيذه حلقة التكرار ذات المُعرِّف <code>&lt;labelName&gt;</code> (أي <code>outer</code> في حالتنا):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_53" style="">
<span class="pln">outer</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> j </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> j</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    let input </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(`</span><span class="typ">Value</span><span class="pln"> at coords </span><span class="pun">(</span><span class="pln">$</span><span class="pun">{</span><span class="pln">i</span><span class="pun">},</span><span class="pln">$</span><span class="pun">{</span><span class="pln">j</span><span class="pun">})`,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// الخروج من كلتا الحلقتين إن ألغيت عملية الإدخال أو أعطيت قيم فارغة</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">input</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">break</span><span class="pln"> outer</span><span class="pun">;</span><span class="pln"> </span><span class="com">// (*)</span><span class="pln">
    </span><span class="com">// افعل شيئًا بالقيم المعطاة</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">'Done!'</span><span class="pun">);</span></pre>

<p>
	وظيفة الموجِّه <code>break outer</code> في المثال السابق إيقاف حلقة تكرار مسماة بالاسم <code>outer</code>؛ لذلك، ينتقل تنفيذ الشيفرة مباشرة من السطر <code>(*)</code> إلى السطر <code>alert('Done!')‎</code>.
</p>

<p>
	يمكنك وضع اللافتة في سطر منفصل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_55" style="">
<span class="pln">outer</span><span class="pun">:</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	يُستخدَم الموجِّه <code>continue</code> مع لافتة أيضًا وينتقل تنفيذ التعليمات البرمجية آنذاك إلى التكرار التالي ليس لحلقة التكرار الموجود فيها وإنما للحلقة الموسومة بتلك اللافتة.
</p>

<h3>
	لا تسمح اللافتات بالقفز إلى أي مكان في الشيفرة
</h3>

<p>
	لا تسمح لك اللافتات بالانتقال إلى أي سطر تريده في الشيفرة لتنفيذه إجباريًا، فمن المستحيل مثلًا تنفيذ المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_57" style="">
<span class="kwd">break</span><span class="pln"> label</span><span class="pun">;</span><span class="pln">  </span><span class="com">// label لا يمكن القفز إلى السطر التالي المعنون بـ</span><span class="pln">
label</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(...)</span></pre>

<p>
	لا يمكن إستدعاء <code>break/continue</code> إلا من داخل حلقة تكرارية ويمكن استعمال لافتة معهما إن سبق عنونة الحلقة بها مسبقًا.
</p>

<h2>
	الخلاصة
</h2>

<p>
	تعرفت إلى الآن على ثلاثة أنواع من حلقات التكرار:
</p>

<ul>
<li>
		<code>while</code>: تتحقَّق من الشرط قبل كل تكرار، ويُنفذ التكرار إذا كان الشرط محققًا.
	</li>
	<li>
		<code>do..while</code>: تتحقَّق من الشرط بعد كل تكرار، ولا يُنفذ التكرار التالي إذا لم يكن الشرط محققًا.
	</li>
	<li>
		<code>for (;;)</code>: تتحقَّق من الشرط قبل كل تكرار، وهناك أيضًا عناصر تتيح التحكم أكثر بالحلقة.
	</li>
</ul>
<p>
	لبناء حلقة أبدية (لا نهائية)، تُستخدم حلقة التكرار <code>while(true)‎</code> (أي أن يكون الشرط دائمًا محققًا)، ويمكن إيقاف هذه الحلقة مثل أي حلقة أخرى، عن طريق الموجِّه <code>break</code>.
</p>

<p>
	في حال عدم رغبتك بتنفيذ التكرار الحالي وتود الانتقال إلى التكرار التالي، فيمكنك استخدام الموجِّه <code>continue</code>. ويمكنك استخدام الموجين <code>break/continue</code> مع لافتات (labels) شرط أن تكون مُعرّفة قبل بداية حلقة التكرار. فتوفر اللافتة عندما استعمالها مع <code>break/continue</code> تحكمًا أكبر بالحلقات المتداخلة.
</p>

<h2>
	التمارين
</h2>

<h3>
	قيمة حلقة التكرار الأخيرة
</h3>

<p class="task__importance">
	الأهمية: 3
</p>

<p>
	ما هي القيمة الأخيرة التي أظهرتها الدالة <code>alert</code> في هذه الشيفرة؟ ولماذا؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_59" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> i</span><span class="pun">--</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الحل
</p>

<div class="task__answer">
	<p>
		الإجابة: <code>1</code>.
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_61" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> i</span><span class="pun">--</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

	<p>
		تَنقص قيمة المتغير <code>i</code> بمقدار <code>1</code> في كل تكرار في حلقة التكرار هذه. تتوقف حلقة التكرار <code>while(i)‎</code> عندما يتحقق الشرط <code>i = 0</code>، وبالتالي تشكل خطوات حلقة التكرار هذه التسلسل التالي:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_63" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">--);</span><span class="pln"> </span><span class="com">// بمقدار 1 لتصبح 2 i إظهار 3 ثم إنقاص قيمة</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">--)</span><span class="pln"> </span><span class="com">// بمقدار 1 لتصبح 1 i إظهار 2 ثم إنقاص قيمة</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">i</span><span class="pun">--)</span><span class="pln"> </span><span class="com">// بمقدار 1 لتصبح 0 i إظهار 1 ثم إنقاص قيمة</span><span class="pln">
</span><span class="com">// توقف الحلقة لعدم تحقق الشرط</span></pre>
</div>

<h3>
	ما هي القيم التي ستظهرها حلقة التكرار <code>while</code>؟
</h3>

<p class="task__importance">
	الأهمية: 4
</p>

<p>
	سجّل القيمة الناتجة من كل تكرار في الحلقة، ثم وازنها بالإجابة النهائية. هل تُظهر الدالة <code>alert</code> نفس القيم في الحلقتين أم لا؟
</p>

<ul>
<li>
		النموذج السابق <code>i++</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_65" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(++</span><span class="pln">i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span></pre>

<ul>
<li>
		النموذج اللاحق <code>++i</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_67" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i</span><span class="pun">++</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span></pre>

<p>
	الحل
</p>

<div class="task__answer">
	<p>
		يوضح هذا التمرين كيف يمكن أن يؤدي النموذج السابق/ اللاحق (postfix/prefix) إلى نتائج مختلفة عند استخدامهما في الموازنات.
	</p>

	<ul>
<li>
			من 1 إلى 4
		</li>
	</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_69" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(++</span><span class="pln">i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span></pre>

	<p>
		القيمة الأولى هي <code>i = 1</code>، لأن معامل الزيادة <code>i++</code> الأول يزيد <code>i</code> ثم يُرجع القيمة الجديدة. لذلك الموازنة الأولى هي<code>‎1 &lt; 5</code> وتُظهر الدالة <code>alert</code> العدد <code>1</code>.
	</p>

	<p>
		ثم تتبعها الأعداد 2، 3، 4. تستخدم الموازنة دائمًا القيمة الأخيرة، نظرًا لأن معامل الزيادة <code>++</code> قبل المتغير. وأخيرًا، يُزاد <code>i = 4</code> إلى <code>5</code>، ولا يتحقق شرط حلقة التكرار <code>while(5 &lt; 5)‎</code> في هذه الحالة، وتتوقف الحلقة. لذلك لا يظهر العدد <code>5</code>.
	</p>

	<ul>
<li>
			من 1 إلى 5
		</li>
	</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_71" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i</span><span class="pun">++</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span></pre>

	<p>
		القيمة الأولى هي <code>i = 1</code>. يزيد النموذج اللاحق <code>++i</code> المتغير <code>i</code> ثم يُرجع القيمة القديمة، لذلك ستستخدم الموازنة <code>i++ &lt; 5</code> التعبير <code>i = 0</code> (على عكس <code>‎++i &lt; 5</code>). لكن استدعاء الدالة <code>alert</code> منفصل وتُنفَّذ بعد معامل الزيادة والموازنة، لذلك تحصل على القيمة الحالية للمتغير <code>i = 1</code>. ثم تتبعها الأعداد 2، 3، 4. عند <code>i = 4</code>، يزيد النموذج السابق <code>i++</code> قيمة المتغير ويستخدم العدد <code>5</code> في الموازنة ولكن هنا لدينا النموذج اللاحق <code>++i</code>. أي أن قيمة المتغير <code>i</code> تصبح <code>5</code>، لكنه يُرجع القيمة القديمة. وبهذا تصبح الموازنة <code>while(4 &lt; 5)‎</code>- صحيحة، وتُنفذ الدالة <code>alert</code>. القيمة <code>i = 5</code> آنذاك هي القيمة الأخيرة، لأن الشرط في التكرار التالي <code>while(5 &lt; 5)‎</code> غير مُحقق.
	</p>
</div>

<h3>
	ما القيم التي ستظهرها حلقة التكرار <code>for</code>؟
</h3>

<p class="task__importance">
	الأهمية: 4
</p>

<p>
	سجّل القيمة الناتجة من كل حلقة تكرار، ثم قارنها بالإجابة. هل تُظهر الدالة <code>alert</code> نفس القيم في الحلقتين أم لا؟
</p>

<ul>
<li>
		النموذج اللاحق <code>++i</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_73" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span></pre>

<ul>
<li>
		النموذج السابق <code>i++</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_75" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span></pre>

<p>
	الحل
</p>

<div class="task__answer">
	<p>
		الإجابة في كلتا الحلقتين: من <code>0</code> إلى <code>4</code>.
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_77" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span></pre>

	<p>
		يمكنك بسهولة استنتاج التالي من الخوارزمية <code>for</code>:
	</p>

	<ol>
<li>
			تُنفذ التعليمة <code>i = 0</code> مرة واحدة في البداية.
		</li>
		<li>
			يتم يُتحقَّق من الشرط <code>i &lt; 5</code>.
		</li>
		<li>
			إذا كان الشرط محققًا <code>true</code>- يُنفذ جسم الحلقة <code>alert(i)‎</code> ويليه معامل الزيادة <code>++i</code>.
		</li>
	</ol>
<p>
		معامل الزيادة <code>++i</code> منفصل عن الشرط في الحالتين، فهو عبارة عن تعليمة أخرى. لا تُستخدَم القيمة التي يعيدها معامل الزيادة هنا، لذلك لا يوجد فرق بين النموذجين <code>++i</code> و <code>i++</code>.
	</p>
</div>

<h3>
	إخراج الأعداد الزوجية باستخدام حلقة التكرار
</h3>

<p class="task__importance">
	الأهمية: 5
</p>

<p>
	استخدم حلقة التكرار <code>for</code> لإظهار الأعداد الزوجية من <code>2</code> إلى <code>10</code>.
</p>

<p>
	الحل
</p>

<div class="task__answer">
	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_79" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

	<p>
		يمكنك استخدام معامل باقي القسمة (modulo) <code>%</code> للحصول على باقي القسمة والتحقق من التكافؤ هنا.
	</p>
</div>

<h3>
	استبدال حلقة التكرار <code>for</code> بحلقة التكرار <code>while</code>
</h3>

<p class="task__importance">
	الأهمية: 5
</p>

<p>
	أعد كتابة الشيفرة باستبدال حلقة التكرار <code>for</code> بحلقة التكرار <code>while</code> دون تغيير سلوك الشيفرة (يجب أن يظل ناتج حلقة التكرار كما هو).
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_81" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="pun">`</span><span class="pln">number $</span><span class="pun">{</span><span class="pln">i</span><span class="pun">}!`</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الحل
</p>

<div class="task__answer">
	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_83" style="">
<span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="pun">`</span><span class="pln">number $</span><span class="pun">{</span><span class="pln">i</span><span class="pun">}!`</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
  i</span><span class="pun">++;</span><span class="pln">
</span><span class="pun">}</span></pre>
</div>

<h3>
	كرر حتى يكون الإدخال صحيحًا
</h3>

<p class="task__importance">
	الأهمية: 5
</p>

<p>
	اكتب حلقة تكرار تطلب من المستخدم إدخال عدد أكبر من 100. إذا أدخل المستخدم عدد آخر، فاطلب منه الإدخال مرة أخرى.
</p>

<p>
	يجب أن تسأل حلقة التكرار عن العدد حتى يُدخل المستخدم عدد أكبر من 100 أو يلغي الإدخال / يُدخل سطرًا فارغًا. في هذا التمرين، يدخل المستخدم الأعداد فقط أي ليس هناك حاجة لتنفيذ معالجة خاصة للتحقق من القيم المدخلة.
</p>

<p>
	الحل
</p>

<div class="task__answer">
	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_85" style="">
<span class="pln">let num</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  num </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"Enter a number greater than 100?"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">num </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">100</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> num</span><span class="pun">);</span></pre>

	<p>
		تتكرر حلقة التكرار <code>do..while</code> طالما أن الشرط <code>num &lt;= 100 &amp;&amp; num</code> محقق:
	</p>

	<ol>
<li>
			الجزء الأول من الشرط <code>num &lt;= 100</code>- أي أن القيمة التي أدخلها المستخدم لا تزال أقل من <code>100</code>.
		</li>
		<li>
			الجزء الثاني من الشرط <code>&amp;&amp; num</code>- لا يتحقق هذا الجزء إذا كان الإدخال <code>null</code> أو سلسلة نصية فارغة. تتوقف حلقة التكرار <code>while</code> في هذه الحالة أيضًا.
		</li>
	</ol>
<p>
		ملاحظة: إذا كان المتغير <code>num</code> فارغًا <code>null</code>، فسيكون الجزء الأول من الشرط <code>num &lt;= 100</code> صحيحًا <code>true</code>، دون الجزء الثاني من الشرط لن تتوقف الحلقة إذا نقر المستخدم على زر الإلغاء (CANCEL). لذا لا يمكن الاستغناء عن أي الجزئين.
	</p>
</div>

<h3>
	إظهار الأعداد الأولية
</h3>

<p class="task__importance">
	الأهمية: 3
</p>

<p>
	يسمى العدد عددًا أولي (prime) إذا كان عددًا صحيحًا أكبر من <code>1</code>، ولا يقبل القسمة (القسمة دون باقي قسمة) إلا على نفسه وعلى العدد <code>1</code>. بعبارة أخرى، <code>n &gt; 1</code> المتغير <code>n</code> عبارة عن عدد أولي إذا كان لا يقبل القسمة بالتساوي على أي عدد باستثناء <code>1</code> و <code>n</code>. على سبيل المثال، العدد <code>5</code> هو عدد أولي، لأنه لا يمكن تقسيمه بالتساوي دون وجود باقي قسمة بمقدار <code>2</code>، و <code>3</code> و<code>4</code>.
</p>

<p>
	اكتب الشيفرة التي تخرج الأعداد الأولية في المجال من <code>2</code> إلى <code>n</code>. إذا كانت <code>n = 10</code> مثلًا، فستكون النتيجة <code>2,3,5,7</code>.
</p>

<p>
	ملاحظة: يجب أن تعمل الشيفرة من أجل أي قيمة للمتغير <code>n</code>، أي لا يكون المتغير <code>n</code> معرّف لقيمة ثابتة.
</p>

<p>
	الحل
</p>

<p>
	هناك العديد من الخوارزميات لهذا التمرين:
</p>

<ul>
<li>
		كتابة الشيفرة باستخدام حلقة تكرار متداخلة:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_87" style="">
<span class="typ">For</span><span class="pln"> each i in the interval </span><span class="pun">{</span><span class="pln">
  check </span><span class="kwd">if</span><span class="pln"> i has a divisor from </span><span class="lit">1.</span><span class="pun">.</span><span class="pln">i
  </span><span class="kwd">if</span><span class="pln"> yes </span><span class="pun">=&gt;</span><span class="pln"> the value is not a prime
  </span><span class="kwd">if</span><span class="pln"> no </span><span class="pun">=&gt;</span><span class="pln"> the value is a prime</span><span class="pun">,</span><span class="pln"> show it
</span><span class="pun">}</span></pre>

<ul>
<li>
		كتابة الشيفرة باستخدام اللافتة (label):
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4985_89" style="">
<span class="pln">let n </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
nextPrime</span><span class="pun">:</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// i لكل قيمة من قيم</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">let j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> j </span><span class="pun">&lt;</span><span class="pln"> i</span><span class="pun">;</span><span class="pln"> j</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// ابحث عن المقسوم عليه</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">%</span><span class="pln"> j </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">continue</span><span class="pln"> nextPrime</span><span class="pun">;</span><span class="pln"> </span><span class="com">// ليس عددًا أوليًا، انتقل للتكرار التالي</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> i </span><span class="pun">);</span><span class="pln"> </span><span class="com">// عددٌ أولي</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هناك مساحة كبيرة لتحسين الشيفرة، على سبيل المثال يمكنك البحث عن القواسم من <code>2</code> إلى الجذر التربيعي ل <code>i</code> (مثال: القواسم الموجبة للعدد 24 هي 1، 2، 3، 4، 6، 8، 12، 24). على أي حال، إذا كنت تريد تنفيذ التمرين السابق على مجالات كبيرة، فستحتاج إلى تغيير النهج والاعتماد على الرياضيات المتقدمة والخوارزميات المعقدة مثل المنخل التربيعي (<a href="https://en.wikipedia.org/wiki/Quadratic_sieve" rel="external nofollow">Quadratic sieve</a>) أو منخل الأعداد العام (<a href="https://en.wikipedia.org/wiki/General_number_field_sieve" rel="external nofollow">General number field sieve</a>) وما إلى ذلك.
</p>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/while-for" rel="external nofollow">Loops: while and for</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%8A%D9%85%D8%A9-switch-r780/" rel="">التعليمة switch</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%85%D8%B9%D8%A7%D9%85%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%86%D8%B7%D9%82%D9%8A%D8%A9-r778/" rel="">المعاملات المنطقية</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">779</guid><pubDate>Tue, 14 Jan 2020 13:09:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x639;&#x627;&#x645;&#x644;&#x627;&#x62A; &#x627;&#x644;&#x645;&#x646;&#x637;&#x642;&#x64A;&#x629; &#x641;&#x64A; &#x62C;&#x627;&#x641;&#x627;&#x633;&#x643;&#x631;&#x628;&#x62A;</title><link>https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%85%D8%B9%D8%A7%D9%85%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%86%D8%B7%D9%82%D9%8A%D8%A9-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r778/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/14.jpg.50399d30f4d6abd3e9fb7970c71a815c.jpg" /></p>

<p>
	هناك ثلاثة معاملات منطقية في JavaScript وهي: <code>||</code> (OR)، و <code>&amp;&amp;</code> (AND)، و <code>!</code> (NOT). رغم أنها تسمى معاملات منطقية، إلا أنه يمكن تطبيقها على أي نوع من أنواع البيانات وليس فقط على البيانات المنطقية. دعنا نرى التفاصيل.
</p>

<h2>
	المعامل <code>||</code> (OR) المنطقي
</h2>

<p>
	يُمثَّل معامل OR المنطقي بخطين عموديين <code>||</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_7" style="">
<span class="pln">result </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">||</span><span class="pln"> b</span><span class="pun">;</span></pre>

<p>
	في لغات البرمجة القديمة، يعالج المعامل OR المنطقي البيانات المنطقية فقط. إذا كانت أي من وسائطه (arguments) تحمل القيمة <code>true</code>، فإن المعامل يُرجع القيمة <code>true</code>، عدا ذلك يُرجع <code>false</code>.
</p>

<p>
	في JavaScript، المعامل أصعب قليلاً وأكثر فائدة، دعنا نرى ما يحدث مع البيانات المنطقية.
</p>

<p>
	هناك أربع مجموعات منطقية محتملة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_9" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">);</span><span class="pln">   </span><span class="com">// true</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">);</span><span class="pln">  </span><span class="com">// true</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">);</span><span class="pln">  </span><span class="com">// true</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// false</span></pre>

<p>
	كما ترى، النتيجة صحيحة <code>true</code> دائمًا باستثناء الحالة التي يكون فيها كلا العاملين (operands) خطأ <code>false</code>. إذا لم يكن العامل منطقيًا، سيُحوّل إلى قيمة منطقية لتتم عملية التقييم. على سبيل المثال، يتم التعامل مع العدد <code>1</code> على أنه <code>true</code>، والعدد <code>0</code> على أنه <code>false</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_11" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// تمامًا true || false يقابل التعبير</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'truthy!'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	غالبًا ما يُستخدام المعامل <code>||</code> في الجُمل الشرطية <code>if</code> لاختبار ما إذا كان أي من الشروط محقق <code>true</code>. على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_13" style="">
<span class="pln">let hour </span><span class="pun">=</span><span class="pln"> </span><span class="lit">9</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">hour </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> hour </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'The office is closed.'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن التحقُّق من عدَّة شروط في الوقت نفسه مثل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_15" style="">
<span class="pln">let hour </span><span class="pun">=</span><span class="pln"> </span><span class="lit">12</span><span class="pun">;</span><span class="pln">
let isWeekend </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">hour </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> hour </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">18</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> isWeekend</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'The office is closed.'</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">//الوقت عطلة  </span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	المعامل OR يرجع القيمة الصحيحة الاولى
</h3>

<p>
	المنطق الموصوف أعلاه قديم إلى حد ما. لنوضّح ميزات إضافية في JavaScript. الخوارزمية الموسعة تعمل على النحو التالي. بالنظر إلى قيم المعامل OR المتسَلسَلة في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_17" style="">
<span class="pln">result </span><span class="pun">=</span><span class="pln"> value1 </span><span class="pun">||</span><span class="pln"> value2 </span><span class="pun">||</span><span class="pln"> value3</span><span class="pun">;</span></pre>

<p>
	يقوم المعامل المنطقي <code>||</code> بالتالي:
</p>

<ul>
<li>
		يقيم المعاملات (operand) من اليسار إلى اليمين.
	</li>
	<li>
		يحوِّل جميع العاملات (operands) إلى قيم منطقية إن لم تكن كذلك. إذا كانت النتيجة صحيحة <code>true</code>، يتوقف ويرجع القيمة الأصلية لذلك العامل.
	</li>
	<li>
		إذا قيِّمَت جميع العامِلات وكانت جميعها <code>false</code> خطأ، يرجع العامل الأخير.
	</li>
</ul>
<p>
	تُرجَع القيمة بشكلها الأصلي. بمعنى آخر، سلسلة من المعامل <code>||</code> تُرجع القيمة الصحيحة الأولى أو القيمة الأخيرة إذا لم يتم العثور على قيمة صحيحة.
</p>

<p>
	على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_20" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 1 العدد 1 عبارة عن القيمة الصحيحة</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="str">'no matter what'</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// (true is truthy)</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 1 القيمة الصحيحة الأولى هي</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 1 القيمة الصحيحة الأولى هي</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">undefined</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 0 جميع القيم خاطئة، يرجع القيمة الأخيرة</span></pre>

<p>
	هذه المميزات تؤدي إلى بعض الاستخدامات المثيرة للاهتمام موازنةً بالمعامل المنطقي (OR) الكلاسيكي، أو المنطقي فقط.
</p>

<p>
	1- <strong>الحصول على أول قيمة صحيحة من قائمة المتغيرات أو التعبيرات</strong>. تخيل أن لدينا قائمة من المتغيرات التي يمكن أن تحتوي على بيانات أو تكون فارغة/غير محددة <code>null/undefined</code>. كيف يمكننا العثور على أول واحد مع البيانات؟ باستخدام المعامل المنطقي <code>||</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_22" style="">
<span class="pln">let currentUser </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span><span class="pln">
let defaultUser </span><span class="pun">=</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">;</span><span class="pln">

let name </span><span class="pun">=</span><span class="pln"> currentUser </span><span class="pun">||</span><span class="pln"> defaultUser </span><span class="pun">||</span><span class="pln"> </span><span class="str">"unnamed"</span><span class="pun">;</span><span class="pln">

alert</span><span class="pun">(</span><span class="pln"> name </span><span class="pun">);</span><span class="pln"> </span><span class="com">// يختار القيمة الصحيحة الأولى</span></pre>

<p>
	إذا كان كلًا من المتغيرات <code>currentUser</code> و <code>defaultUser</code> خطأ، فستكون النتيجة <code>unnamed</code>.
</p>

<p>
	2- <strong>تقييم الدارة القصيرة (Short-circuit)</strong>
</p>

<p>
	لا تكون العاملات (operands) قيمًا فقط، بل يمكن أن تكون تعبيرات عشوائية. المعامل المنطقي OR يفحصها ويقييمها من اليسار إلى اليمين، يتوقف التقييم عند الوصول إلى قيمة صحيحة وتُرجع القيمة. تسمى هذه العملية "تقييم الدارة القصيرة" لأنها تختصر عملية التقييم قدر الإمكان من اليسار إلى اليمين.
</p>

<p>
	يظهر هذا بوضوح عندما يكون التعبير المعطى كعامل ثاني، له تأثير جانبي مثل إسناد متغير. في المثال أدناه، لا يتم إسناد <code>x</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_24" style="">
<span class="pln">let x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">true</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> </span><span class="com">// undefined, because (x = 1) not evaluated</span></pre>

<p>
	إذا كان العامل الأول خطأ <code>false</code>، يقييم المعامل المنطقي <code>||</code> العامل الثاني، وبالتالي تستمر عملية الإسناد:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_26" style="">
<span class="pln">let x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">false</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 1</span></pre>

<p>
	عملية الإسناد عملية بسيطة. قد تكون هناك آثار جانبية، لن تظهر إذا كان التقييم لم يصل إليها.
</p>

<p>
	كما نرى، فإن حالة الاستخدام هذه هي "طريقة أقصر للقيام بالمعامل الشرطي<code>if</code>". يُحوَّل العامل الأول إلى قيمة منطقية؛ فإذا كان خطأ، فسيُقيَّم العامل الثاني.
</p>

<p>
	في أغلب الأحيان، من الأفضل استخدام المعامل الشرطي <code>if</code> بشكله الاعتيادي للحفاظ على سهولة فهم الشيفرة، ولكن لا يكون دائمًا في متناول اليد.
</p>

<h2>
	المعامل AND) <code>&amp;&amp;</code>‎) المنطقي
</h2>

<p>
	يُمثَّل المعامل AND المنطقي بعلامتين <code>&amp;&amp;</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_28" style="">
<span class="pln">result </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">&amp;&amp;</span><span class="pln"> b</span><span class="pun">;</span></pre>

<p>
	عند كتابة شيفرة بلغات البرمجة القديمة، يُرجع المعامل AND المنطقي <code>true</code> إذا كان كلا العاملان صحيحين ويُرجع <code>false</code> عدا ذلك:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_30" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">);</span><span class="pln">   </span><span class="com">// true</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">);</span><span class="pln">  </span><span class="com">// false</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">);</span><span class="pln">  </span><span class="com">// false</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// false</span></pre>

<p>
	مثال مع المعامل الشرطي <code>if</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_32" style="">
<span class="pln">let hour </span><span class="pun">=</span><span class="pln"> </span><span class="lit">12</span><span class="pun">;</span><span class="pln">
let minute </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">hour </span><span class="pun">==</span><span class="pln"> </span><span class="lit">12</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> minute </span><span class="pun">==</span><span class="pln"> </span><span class="lit">30</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'The time is 12:30'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تمامًا كما هو الحال مع المعامل المنطقي OR، يُسمح بأي قيمة لتكون عاملًا للمعامل المنطقي AND:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_34" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// تقييم كأنها صواب او خطأ</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"won't work, because the result is falsy"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	المعامل AND يرجع القيمة الخطأ الأولى
</h3>

<p>
	بالنظر إلى قيم المعامل AND المتعدِّدة في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_36" style="">
<span class="pln">result </span><span class="pun">=</span><span class="pln"> value1 </span><span class="pun">&amp;&amp;</span><span class="pln"> value2 </span><span class="pun">&amp;&amp;</span><span class="pln"> value3</span><span class="pun">;</span></pre>

<p>
	يقوم المعامل المنطقي AND بالتالي:
</p>

<ul>
<li>
		يقيم العاملات من اليسار إلى اليمين.
	</li>
	<li>
		يحوّل جميع العاملات إلى قيم منطقية. إذا كانت النتيجة <code>false</code>، يتوقف ويرجع القيمة الأصلية لذلك العامل.
	</li>
	<li>
		إذا قيِّمَت جميع العامِلات وكانت جميعها صحيحة، يُرجَع العامل الأخير.
	</li>
</ul>
<p>
	بمعنى آخر، سلسلة من المعامل AND تُرجع القيمة الخطأ الأولى أو القيمة الأخيرة إذا لم يُعثَر على أي قيمة خطأ.
</p>

<p>
	القواعد المذكورة أعلاه تشبه قواعد المعامل المنطقي OR. الفرق هو أن المعامل المنطقي AND يُرجع القيمة الخطأ الأولى بينما يُرجع المعامل المنطقي OR القيمة الصحيحة الأولى.
</p>

<p>
	على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_38" style="">
<span class="com">// إذا كان العامل الأول صحيحًا، يرجع</span><span class="pln">
</span><span class="com">// العامل الثاني AND المعامل المنطقي </span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 0</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 5</span><span class="pln">
</span><span class="com">// إذا كان العامل الأول خطأ، يرجع المعامل</span><span class="pln">
</span><span class="com">// هذا العامل ويتجاهل العامل الثاني AND المنطقي </span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// null</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="str">"no matter what"</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 0</span></pre>

<p>
	يمكننا أيضا سَلسَلة العديد من القيم على التوالي. انظر كيف تُرجَع أول قيمة خطأ:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_40" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// null</span></pre>

<p>
	عندما تكون جميع القيم صحيحة، تُرجَع آخر قيمة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_42" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// 3, القيمة الأخيرة</span></pre>

<h3>
	أولوية المعامل المنطقي <code>&amp;&amp;</code> في التنفيذ أعلى من أولوية المعامل المنطقي <code>||</code>
</h3>

<p>
	لذلك، التعبير التالي <code>a &amp;&amp; b || c &amp;&amp; d</code> هو نفس التعبير <code>(a &amp;&amp; b) || (c &amp;&amp; d)</code> مع الأقواس التي لها الأولية دومًا.
</p>

<p>
	يمكن استعمال المعامل المنطقي <code>&amp;&amp;</code> بدلًا من <code>if</code> مثل المعامل المنطقي <code>||</code>. على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_44" style="">
<span class="pln">let x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">(</span><span class="pln">x </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Greater than zero!'</span><span class="pln"> </span><span class="pun">);</span></pre>

<p>
	لن ينفَّذ الإجراء في الجزء الأيمن الخاص بالمعامل المنطقي <code>&amp;&amp;</code> إلا إذا وصل التقييم إليه، أي فقط إذا كان <code>x&gt;0</code> محقَّقًا (صحيحًا):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_46" style="">
<span class="pln">let x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Greater than zero!'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يبدو المثال الأول الذي استعملنا فيه المعامل المنطقي <code>&amp;&amp;</code> أقصر، ولكن المثال الثاني الذي استعلمنا فيه <code>if</code> أوضح أضف إلى سهولة قراءة الشيفرة. لذلك، نوصي باستخدام كل معامل للغرض المناسب له: أي يمكنك استخدام التعليمة الشرطية <code>if</code> عندم وجود شرط، واستعمل المعامل المنطقي <code>&amp;&amp;</code>عند التعامل مع القيم المنطقية.
</p>

<h2>
	المعامل المنطقي <code>!</code> (NOT)
</h2>

<p>
	المعامل المنطقي NOT يُعبَّر عنه بعلامة التعجب <code>!</code>. الصيغة الخاصة به بسيطة للغاية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_48" style="">
<span class="pln">result </span><span class="pun">=</span><span class="pln"> </span><span class="pun">!</span><span class="pln">value</span><span class="pun">;</span></pre>

<p>
	يقبل المعامل المنطقي NOT عاملًا واحدًا (operand) ويقوم بما يلي:
</p>

<ul>
<li>
		يُحوِّل العامل إلى قيمة منطقية: <code>true/false</code>.
	</li>
	<li>
		يرجع القيمة العكسية لتلك القيمة المنطقية.
	</li>
</ul>
<p>
	على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_50" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="pun">!</span><span class="kwd">true</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// false</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="pun">!</span><span class="lit">0</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span></pre>

<p>
	يُستخدَم المعامل المنطقي NOT المزدوج (أي <code>!!</code>) في بعض الأوقات لتحويل قيمة معينة إلى قيمة منطقية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_52" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="pun">!!</span><span class="str">"non-empty string"</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="pun">!!</span><span class="kwd">null</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// false</span></pre>

<p>
	بمعنى، المعامل المنطقي NOT الأول (أي <code>‎!"non-empty string"‎</code>) يحول القيمة إلى قيمة منطقية (<code>true!</code>) ويرجع القيمة العكسية (<code>false</code>)، والمعامل المنطقي NOT الثاني (أي <code>‎!!"non-empty string"‎</code>) يرجع القيمة العكسية مرة أخرى للقيمة التي أعادها المعامل الأول (<code>true</code> الناتج النهائي). في النهاية، يوفر لنا المعامل <code>!!</code> وسيلةً لتحويل أي قيمة إلى قيمة منطقية بسهولة.
</p>

<p>
	هناك طريقة مطوّلة أكثر قليلاً لفعل الشيء نفسه - باستخدام الدالة <code>Boolean</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_54" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Boolean</span><span class="pun">(</span><span class="str">"non-empty string"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Boolean</span><span class="pun">(</span><span class="kwd">null</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// false</span></pre>

<p>
	أولوية المعامل المنطقي <code>!</code> هي الأعلى بين جميع المعاملات المنطقية الأخرى، لذلك ينفذ أولًا قبل المعامل <code>&amp;&amp;</code> والمعامل <code>||</code>.
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}</style>
<h2>
	تمارين
</h2>

<h3>
	ما هي نتيجة المعامل OR
</h3>

<p class="task__importance">
	<em>الأهمية: 5</em>
</p>

<p>
	ما ناتج الشيفرة التالية؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_56" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="kwd">undefined</span><span class="pln"> </span><span class="pun">);</span></pre>

<p>
	<strong>الحل</strong>:
</p>

<div class="task__answer">
	<p>
		الإجابة هي <code>2</code>، هذه هي القيمة الصحيحة الأولى.
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_58" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="kwd">undefined</span><span class="pln"> </span><span class="pun">);</span></pre>
</div>

<h3>
	ما هي نتيجة سلسلة من المعامل OR للدالة <code>alert</code>
</h3>

<p class="task__importance">
	<em>الأهمية: 3</em>
</p>

<p>
	ما ناتج الشيفرة التالية؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_60" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> alert</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> alert</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span></pre>

<p>
	<strong>الحل</strong>:
</p>

<div class="task__answer">
	<p>
		الإجابة هي: أولًا <code>1</code> ثم <code>2</code>
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_62" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> alert</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> alert</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span></pre>

	<p>
		استدعاء الدالة <code>alert</code> لا يُرجع قيمة. بصيغة أخرى، يرجع <code>undefined</code> .
	</p>

	<ol>
<li>
			معامل OR الأول <code>||</code> يُقييم العامل الأيسر <code>alert(1)‎</code> وهذا يُظهر رسالةً تحوي <code>1</code>.
		</li>
		<li>
			الدالة <code>alert</code> ترجع <code>undefined</code>، لذلك ينتقل المعامل OR للعامل التالي بحثًا عن قيمة صحيحة.
		</li>
		<li>
			العامل الثاني <code>2</code> عبارة عن قيمة صحيحة (أي يقيَّم إلى <code>true</code>)، وبذلك يتوقف تنفيذ سلسلة المعامل OR ويُرجع العامل <code>2</code> ثم يُعرَض بواسطة الدالة <code>alert</code>.
		</li>
	</ol>
<p>
		لن يظهر العدد 3، لأن التقييم انتهى عند العامل الثاني و لن يصل إلى <code>alert(3)‎</code>.
	</p>
</div>

<h3>
	ما هي نتيجة المعامل AND
</h3>

<p class="task__importance">
	<em>الأهمية: 5</em>
</p>

<p>
	ما ناتج الشيفرة التالية؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_64" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">);</span></pre>

<p>
	<strong>الحل</strong>:
</p>

<div class="task__answer">
	<p>
		الإجابة هي: <code>null</code> لأنها القيمة الخطأ الأولى في التعبير:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_66" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">);</span></pre>
</div>

<h3>
	ما هي نتيجة سلسلة من المعامل AND للدالة <code>alert</code>
</h3>

<p class="task__importance">
	<em>الأهمية: 3</em>
</p>

<p>
	ماذا ستُظهر الشيفرة التالية؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_68" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> alert</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> alert</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span></pre>

<p>
	<strong>الحل</strong>:
</p>

<div class="task__answer">
	<p>
		الإجابة هي: <code>1</code> ثم <code>undefined</code>:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_70" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> alert</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> alert</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span></pre>

	<p>
		استدعاء الدالة <code>alert</code> يُرجع <code>undefined</code> (هي فقط تُظهر رسالة للمستخدم، أي ليس هناك شيء ذا معنى لإعادته). لهذا السبب، يقيِّم المعامل <code>&amp;&amp;</code> العامل الأيسر (المخرجات <code>1</code>) ، ويتوقف على الفور، لأنَّ القيمة <code>undefined</code> هي قيمة خطأ (أي <code>false</code>). والمعامل <code>&amp;&amp;</code> يبحث عن أول قيمة خطأ ويُرجعها، فقط.
	</p>
</div>

<h3>
	الناتج من سَلسلة المعاملات على النحو التالي (OR AND OR)
</h3>

<p class="task__importance">
	<em>الأهمية: 5</em>
</p>

<p>
	ما الناتج من الشيفرة التالية؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_72" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">);</span></pre>

<p>
	<strong>الحل</strong>:
</p>

<div class="task__answer">
	<p>
		الإجابة هي: <code>3</code>.
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_74" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">);</span></pre>

	<p>
		أولوية المعامل <code>&amp;&amp;</code> في التنفيذ أكبر من أولوية المعامل <code>||</code>، لذلك يُنفَّذ أولًا. نتيجة لذلك <code>2 &amp;&amp; 3 = 3</code>، يصبح التعبير:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_76" style="">
<span class="kwd">null</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">4</span></pre>

	<p>
		الآن، الإجابة هي القيمة الصحيحة الأولى: <code>3</code>.
	</p>
</div>

<h3>
	حصر قيمة متغير ضمن مجال
</h3>

<p class="task__importance">
	<em>الأهمية: 3</em>
</p>

<p>
	اكتب شرطًا (أي <code>if</code>) للتحقق من أنَّ قيمة المتغير <code>age</code> محصورة بين <code>14</code> و <code>90</code> (داخلة ضمن المجال).
</p>

<p>
	<strong>الحل</strong>:
</p>

<div class="task__answer">
	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_78" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">14</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> age </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">90</span><span class="pun">)</span></pre>
</div>

<h3>
	حصر متغير خارج مجال
</h3>

<p class="task__importance">
	<em>الأهمية: 3</em>
</p>

<p>
	اكتب شرطًا (أي <code>if</code>) للتحقق من أنَّ قيمة المتغير <code>age</code> لا تقع ضمن <code>14</code> و <code>90</code> (داخلة ضمن المجال). أنشئ تعبيرين مختلفين: الأول باستخدام معامل النفي <code>!</code>، والثاني دونه.
</p>

<p>
	<strong>الحل</strong>:
</p>

<div class="task__answer">
	<p>
		التعبير الأول:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_80" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(!(</span><span class="pln">age </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">14</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> age </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">90</span><span class="pun">))</span></pre>

	<p>
		التعبير الثاني:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_82" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">14</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> age </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">90</span><span class="pun">)</span></pre>
</div>

<h3>
	سؤال باستخدام التعبير الشرطي <code>if</code>
</h3>

<p class="task__importance">
	<em>الأهمية: 5</em>
</p>

<p>
	أي دالة من الدوال <code>alert</code> سوف تُنفَّذ؟ ماذا ستكون نتائج التعبيرات الموجودة في داخل التعبير الشرطي <code>if(...)</code>‎:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_84" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(-</span><span class="lit">1</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'first'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(-</span><span class="lit">1</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'second'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">null</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'third'</span><span class="pln"> </span><span class="pun">);</span></pre>

<p>
	<strong>الحل</strong>:
</p>

<div class="task__answer">
	<p>
		الإجابة هي: التعبير الأول والثالث والسبب:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_86" style="">
<span class="com">// يعمل</span><span class="pln">
</span><span class="com">// ناتج 0 || 1- هو 1-، أول قيمة صحيحة</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(-</span><span class="lit">1</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'first'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">

</span><span class="com">// لا يعمل</span><span class="pln">
</span><span class="com">// ناتج 0 &amp;&amp; 1- هو 0، قيمة خطأ</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(-</span><span class="lit">1</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'second'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">

</span><span class="com">// يُنفَّذ بالشكل التالي</span><span class="pln">
</span><span class="com">// || المعامل &amp;&amp; له أولوية في التنفيذ أكبر من المعامل </span><span class="pln">
</span><span class="com">// || يُنفذ أولًا 1 &amp;&amp; 1- ثم المعامل </span><span class="pln">
</span><span class="com">// null || -1 &amp;&amp; 1  -&gt;  null || 1  -&gt;  1</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">null</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'third'</span><span class="pln"> </span><span class="pun">);</span></pre>
</div>

<h3>
	التحقق من تسجيل الدخول
</h3>

<p class="task__importance">
	<em>الأهمية: 3</em>
</p>

<p>
	اكتب الشيفرة التي تطلب من المستخدم تسجيل الدخول بواسطة الدالة <code>prompt</code>. إذا أدخل المستخدم <code>Admin</code>، فاطلب كلمة مرور بواسطة الدالة <code>prompt</code>، إذا كان الإدخال عبارة عن سطر فارغ أو مفتاح الهروب Esc - فأظهر "تم الإلغاء"، إذا كان عبارة عن سلسلة نصية أخرى - فأظهر "لا أعرفك".
</p>

<p>
	تُقحص كلمة المرور على النحو التالي:
</p>

<ul>
<li>
		إذا كانت تساوي "TheMaster"، سيُعرَض "مرحبًا!" ،
	</li>
	<li>
		سلسلة نصية أخرى، سيُعرَض "خطأ" ،
	</li>
	<li>
		سلسلة نصية فارغة أو "Cancel"، أظهر "إلغاء".
	</li>
</ul>
<p style="text-align: center;">
	<img alt="schema.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33260" data-unique="oxhv5uhdl" src="https://academy.hsoub.com/uploads/monthly_2020_01/schema.png.1541def8747e7d70c5652bac15a2d3f2.png"></p>

<p>
	يُرجى استخدام الشرط المتداخل (nested) للمحافظة على سهولة قراءة الشيفرة.
</p>

<p>
	ملاحظة: تمرير قيمة فارغة للدالة <code>prompt</code> يُرجِع سلسلة فارغة ''. الضغط على مفتاح الهروب ESC أثناء تنفيذ الدالة <code>prompt</code> يُرجِع <code>null</code>.
</p>

<p>
	<strong>الحل</strong>:
</p>

<div class="task__answer">
	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7186_88" style="">
<span class="pln">let userName </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"من أنت؟"</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">userName </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Admin'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  let pass </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(ما</span><span class="pln"> </span><span class="pun">كلمة</span><span class="pln"> </span><span class="pun">المرور؟</span><span class="str">', '');</span><span class="pln">

  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pass </span><span class="pun">==</span><span class="pln"> </span><span class="str">'TheMaster'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'مرحبًا!'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pass </span><span class="pun">==</span><span class="pln"> </span><span class="str">''</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> pass </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'إلغاء'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'خطأ'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">userName </span><span class="pun">==</span><span class="pln"> </span><span class="str">''</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> userName </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'إلغاء'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"لا أعرفك"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

	<p>
		لاحظ أن المسافات البادئة الرأسية داخل الشرط <code>if</code> غير مطلوبة من الناحية التقنية، لكنها تجعل الشيفرة سهلة القراءة.
	</p>
</div>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/logical-operators" rel="external nofollow">Logical operators</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%AD%D9%84%D9%82%D8%AA%D8%A7-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-while-%D9%88-for-r779/" rel="">حلقتا التكرار while و for</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%85%D8%B9%D8%A7%D9%85%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%B4%D8%B1%D8%B7%D9%8A%D8%A9-r708/" rel="">المعاملات الشرطية</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">778</guid><pubDate>Sun, 12 Jan 2020 13:09:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x648;&#x627;&#x62C;&#x647;&#x629; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x64A;&#x629; Promise &#x641;&#x64A; JavaScript</title><link>https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-promise-%D9%81%D9%8A-javascript-r740/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_09/5d807f1d026a7_promise.jpg.94bfb7e9e229ecbcadf927e0282c23f3.jpg" /></p>

<p>
	الواجهة البرمجية <a href="https://wiki.hsoub.com/JavaScript/Promise" rel="external">Promise</a> رائعة ويمكنك جعلها مذهلة باستخدام <a href="https://wiki.hsoub.com/JavaScript/async_function" rel="external">async</a> و <a href="https://wiki.hsoub.com/JavaScript/await" rel="external">await</a>.
</p>

<p>
	إنّ الشيفرة المتزامنة سهلة التتبع والتنقيح إلا أنّ الشيفرة غير المتزامنة أفضل بشكل عام من حيث الأداء والمرونة، فلماذا "توقف العرض" بينما بإمكانك استقبال الكثير من الطلبات في وقت واحد ثمّ معالجة كلٍّ منها عندما يصبح جاهزًا؟ مع العديد من الواجهات البرمجية <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> الجديدة التي تم تحقيقها مع مبدأ الوعد، إذ أصبحت الوعود جزءًا كبيرًا في عالم الجافاسكربت. لنلقِ نظرة على كيفية استخدام الواجهة البرمجية للوعود.
</p>

<h2 id="-">
	الوعود قيد التطبيق
</h2>

<p>
	الواجهة البرمجية XMLHttpRequest غير متزامنة ولكنها لا تستخدم الواجهة البرمجية Promises. هناك عدة واجهات برمجية أصلية تستخدم الوعود الآن، مثل:
</p>

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-battery-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7-%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-%D8%A7%D9%84%D9%88%D8%B9%D9%88%D8%AF-r738/" rel="">Battery <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-fetch-%D9%81%D9%8A-javascript-r739/" rel="">fetch <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></a> (بديل XHR)
	</li>
	<li>
		الواجهة البرمجية ServiceWorker
	</li>
</ul>
<p>
	ستصبح الوعود أكثر شيوعًا، لذا من المهم أن يعتاد عليها جميع مطوري الواجهات الأمامية، وتجدر الإشارة إلى أنّ Node.js هي منصة أخرى للوعود. (يبدو هذا واضحًا، كما الواجهة البرمجية Promise ميزة أساسية في اللغة).
</p>

<p>
	من المحتمل أن يكون اختبار الوعود أسهل مما تعتقد لأنه يمكنك استخدام <code>setTimeout</code> كـ "مهمة" لك غير متزامنة.
</p>

<h2 id="-promise-">
	استخدام Promise الأساسي
</h2>

<p>
	يجب أن يستخدم الباني <code>new Promise()‎</code> فقط للمهام الغير متزامنة الموروثة، مثل استخدام <code>setTimeout</code> أو <code>XMLHttpRequest</code>. يتم إنشاء وعدًا جديدًا باستخدام الكلمة المفتاحية <code>new</code> ويتم تمرير توابع <code>resolve</code> و <code>reject</code> لردّ النداء المزوَّد:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2531_9" style="">
<span class="kwd">var</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Promise</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">resolve</span><span class="pun">,</span><span class="pln"> reject</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    </span><span class="com">// ...القيام بمهمة غير متزامنة وثم</span><span class="pln">

    </span><span class="kwd">if</span><span class="pun">(</span><span class="com">/* شرط جيد */</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        resolve</span><span class="pun">(</span><span class="str">'Success!'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        reject</span><span class="pun">(</span><span class="str">'Failure!'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

p</span><span class="pun">.</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">result</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    </span><span class="com">/* القيام بفعل ما مع النتيجة */</span><span class="pln">
</span><span class="pun">}).</span><span class="kwd">catch</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">/* خطأ :( */</span><span class="pln">
</span><span class="pun">}).</span><span class="pln">finally</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="com">/* تنفّذ بغض النظر عن النجاح أو الفشل */</span><span class="pln"> 
</span><span class="pun">});</span></pre>

<p>
	يعود الأمر للمطور فيما إذا كان يريد استدعاء <code>resolve</code> أو <code>reject</code> يدويًا ضمن جسم رد النداء اعتمادًا على نتيجة المهمة المعطاة. مثال واقعي لتحويل XMLHttpRequest إلى مهمة تعتمد على الوعد:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2531_11" style="">
<span class="com">// من وعود جاك أرشيبالد والعودة</span><span class="pln">
</span><span class="com">// http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promisifying-xmlhttprequest</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> </span><span class="kwd">get</span><span class="pun">(</span><span class="pln">url</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">//إعادة وعد جديد.</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Promise</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">resolve</span><span class="pun">,</span><span class="pln"> reject</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// XHR القيام بالعمل الاعتيادي لـ</span><span class="pln">
    </span><span class="kwd">var</span><span class="pln"> req </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">XMLHttpRequest</span><span class="pun">();</span><span class="pln">
    req</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">'GET'</span><span class="pun">,</span><span class="pln"> url</span><span class="pun">);</span><span class="pln">

    req</span><span class="pun">.</span><span class="pln">onload </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="com">// هذا يتم استدعاؤه حتى في حالة 404</span><span class="pln">
      </span><span class="com">// لذا اختبر الحالة</span><span class="pln">
      </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">.</span><span class="pln">status </span><span class="pun">==</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// قم بإنهاء الوعد مع نص الرد</span><span class="pln">
        resolve</span><span class="pun">(</span><span class="pln">req</span><span class="pun">.</span><span class="pln">response</span><span class="pun">);</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
      </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// وإلا ارفض مع نص الحالة</span><span class="pln">
        </span><span class="com">// والذي نأمل أن يكون خطأ ذو معنى</span><span class="pln">
        reject</span><span class="pun">(</span><span class="typ">Error</span><span class="pun">(</span><span class="pln">req</span><span class="pun">.</span><span class="pln">statusText</span><span class="pun">));</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    </span><span class="com">// معالجة أخطاء الشبكة</span><span class="pln">
    req</span><span class="pun">.</span><span class="pln">onerror </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      reject</span><span class="pun">(</span><span class="typ">Error</span><span class="pun">(</span><span class="str">"Network Error"</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    </span><span class="com">// القيام بالطلب</span><span class="pln">
    req</span><span class="pun">.</span><span class="pln">send</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// استخدمه!</span><span class="pln">
</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'story.json'</span><span class="pun">).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">response</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Success!"</span><span class="pun">,</span><span class="pln"> response</span><span class="pun">);</span><span class="pln">
</span><span class="pun">},</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">error</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">error</span><span class="pun">(</span><span class="str">"Failed!"</span><span class="pun">,</span><span class="pln"> error</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	إذا كان من الممكن اتخاذ إجراء غير متزامن قد لا تحتاج إلى إكمال المهام غير المتزامنة ضمن الوعد، لكن سيكون الأفضل هو أن تكون القيمة المعادة وعدًا لذا يمكنك أن تعدّ كم عدد الوعود التي حصلت عليها من تابع معطى. في تلك الحالة يمكنك ببساطة استدعاء <code>Promise.resolve()</code>‎ أو <code>Promise.reject()</code>‎ بدون استخدام الكلمة المفتاحية <code>new</code>. مثلًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2531_13" style="">
<span class="kwd">var</span><span class="pln"> userCache </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> getUserDetail</span><span class="pun">(</span><span class="pln">username</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// في كلتا الحالتين، تم إضافته إلى الذاكرة أو لا، سيتم إعادة وعد</span><span class="pln">

  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">userCache</span><span class="pun">[</span><span class="pln">username</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="com">// new إعادة وعد بدون الكلمة المفتاحية </span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Promise</span><span class="pun">.</span><span class="pln">resolve</span><span class="pun">(</span><span class="pln">userCache</span><span class="pun">[</span><span class="pln">username</span><span class="pun">]);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="com">//  لتحصل على المعلومات fetch استخدم الواجهة البرمجية</span><span class="pln">
  </span><span class="com">// وعدًا fetch تعيد </span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> fetch</span><span class="pun">(</span><span class="str">'users/'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> username </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.json'</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">result</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      userCache</span><span class="pun">[</span><span class="pln">username</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">})</span><span class="pln">
    </span><span class="pun">.</span><span class="kwd">catch</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Error</span><span class="pun">(</span><span class="str">'Could not find user: '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> username</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بما أن القيمة المعادة هي وعد لذا يمكنك استخدام التوابع <code>then</code> و <code>catch</code> عليها.
</p>

<h2 id="then">
	then
</h2>

<p>
	كل كائنات الوعد تملك التابع <a href="https://wiki.hsoub.com/JavaScript/Promise/then" rel="external">then</a> الذي يسمح لك بالتفاعل مع الوعد. رد النداء الأول لتابع <code>then</code> يستدعي النتيجة المعطاة له عن طريق استدعاء <code><a href="https://wiki.hsoub.com/JavaScript/Promise/resolve" rel="external">()resolve</a></code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2531_15" style="">
<span class="kwd">new</span><span class="pln"> </span><span class="typ">Promise</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">resolve</span><span class="pun">,</span><span class="pln"> reject</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// setTimeout حدث زائف غير متزامن باستخدام </span><span class="pln">
    setTimeout</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> resolve</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln"> </span><span class="pun">},</span><span class="pln"> </span><span class="lit">3000</span><span class="pun">);</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="pun">.</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">result</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">result</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="com">// console من الطرفية </span><span class="pln">
</span><span class="com">// 10</span></pre>

<p>
	رد النداء لـ <code>then</code> يتم تشغيله عندما ينتهي الوعد. يمكنك أيضًا أن تسلسل ردود النداء للتابع <code>then</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2531_17" style="">
<span class="kwd">new</span><span class="pln"> </span><span class="typ">Promise</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">resolve</span><span class="pun">,</span><span class="pln"> reject</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    </span><span class="com">// setTimeout حدث زائف غير متزامن باستخدام </span><span class="pln">
    setTimeout</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> resolve</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln"> </span><span class="pun">},</span><span class="pln"> </span><span class="lit">3000</span><span class="pun">);</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="pun">.</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">num</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'first then: '</span><span class="pun">,</span><span class="pln"> num</span><span class="pun">);</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> num </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> </span><span class="pun">})</span><span class="pln">
</span><span class="pun">.</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">num</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'second then: '</span><span class="pun">,</span><span class="pln"> num</span><span class="pun">);</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> num </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> </span><span class="pun">})</span><span class="pln">
</span><span class="pun">.</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">num</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'last then: '</span><span class="pun">,</span><span class="pln"> num</span><span class="pun">);});</span><span class="pln">

</span><span class="com">// من الـ console</span><span class="pln">
</span><span class="com">// first then:  10</span><span class="pln">
</span><span class="com">// second then:  20</span><span class="pln">
</span><span class="com">// last then:  40</span></pre>

<p>
	كل <code>then</code> تستقبل القيمة المعادة من استدعاء <code>then</code> السابق.
</p>

<p>
	إذا أُنهي الوعد قبل أن يتم استدعاء التابع <code>then</code> مجددًا، يتم إيقاف رد النداء مباشرةً. إذا تم رفض الوعد ثم استدعاء التابع <code>then</code> بعد الرفض، لا يتم استدعاء رد النداء أبدًا.
</p>

<h2 id="catch">
	catch
</h2>

<p>
	يتم استدعاء رد النداء <a href="https://wiki.hsoub.com/JavaScript/Promise/catch" rel="external">catch</a> عندما يُرفض الوعد:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2531_19" style="">
<span class="kwd">new</span><span class="pln"> </span><span class="typ">Promise</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">resolve</span><span class="pun">,</span><span class="pln"> reject</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// setTimeout حدث زائف غير متزامن باستخدام </span><span class="pln">
    setTimeout</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> reject</span><span class="pun">(</span><span class="str">'Done!'</span><span class="pun">);</span><span class="pln"> </span><span class="pun">},</span><span class="pln"> </span><span class="lit">3000</span><span class="pun">);</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="pun">.</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'done'</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">);</span><span class="pln"> </span><span class="pun">})</span><span class="pln">
</span><span class="pun">.</span><span class="kwd">catch</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'catch: '</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">);</span><span class="pln"> </span><span class="pun">});</span><span class="pln">

</span><span class="com">// console من الطرفية </span><span class="pln">
</span><span class="com">// 'catch: Done!'</span></pre>

<p>
	ما تمرره لتابع <a href="https://wiki.hsoub.com/JavaScript/Promise/reject" rel="external">reject</a> يعود لك ولكن النمط المعتاد هو إرسال <code>Error</code> لـ <code>catch</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2531_21" style="">
<span class="pln">reject</span><span class="pun">(</span><span class="typ">Error</span><span class="pun">(</span><span class="str">'Data could not be found'</span><span class="pun">));</span></pre>

<h2 id="finally">
	finally
</h2>

<p>
	رد النداء المعرّف حديثًا <a href="https://wiki.hsoub.com/JavaScript/Promise/finally" rel="external">finally</a> يتم استدعاؤه بغض النظر عن النجاح أو الفشل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2531_23" style="">
<span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Promise</span><span class="pun">((</span><span class="pln">resolve</span><span class="pun">,</span><span class="pln"> reject</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> reject</span><span class="pun">(</span><span class="str">"Nope"</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}))</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">then</span><span class="pun">(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"success"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">})</span><span class="pln">
    </span><span class="pun">.</span><span class="kwd">catch</span><span class="pun">(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"fail"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">})</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">finally</span><span class="pun">(</span><span class="pln">res </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"finally"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">});</span><span class="pln">

</span><span class="com">// &gt;&gt; fail</span><span class="pln">
</span><span class="com">// &gt;&gt; finally</span></pre>

<h2 id="-promise-all-">
	<code>Promise.all</code>
</h2>

<p>
	فكر بمحمّلات الجافاسكربت: يوجد أوقات يتم فيها تشغيل عدة تفاعلات غير متزامنة وتريد الاستجابة عندما تكتمل جميعها، هنا يأتي دور التابع <a href="https://wiki.hsoub.com/JavaScript/Promise/all" rel="external">Promise.all</a>، هذا التابع يأخذ مصفوفة من الوعود ويعطيك رد نداء واحد فقط عند إنهاء جميع الوعود.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2531_25" style="">
<span class="typ">Promise</span><span class="pun">.</span><span class="pln">all</span><span class="pun">([</span><span class="pln">promise1</span><span class="pun">,</span><span class="pln"> promise2</span><span class="pun">]).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">results</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// كلا الوعدين تم إنهاؤهما</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="pun">.</span><span class="kwd">catch</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">error</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// تم رفض وعد واحد أو أكثر</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	الطريقة المثالية للتفكير بـ <code>Promise.all</code> هي إطلاق عدة طلبات AJAX (باستخدام <code>fetch</code>) في نفس الوقت.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2531_27" style="">
<span class="kwd">var</span><span class="pln"> request1 </span><span class="pun">=</span><span class="pln"> fetch</span><span class="pun">(</span><span class="str">'/users.json'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> request2 </span><span class="pun">=</span><span class="pln"> fetch</span><span class="pun">(</span><span class="str">'/articles.json'</span><span class="pun">);</span><span class="pln">

</span><span class="typ">Promise</span><span class="pun">.</span><span class="pln">all</span><span class="pun">([</span><span class="pln">request1</span><span class="pun">,</span><span class="pln"> request2</span><span class="pun">]).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">results</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// كلا الوعدين تم تنفيذهما</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	يمكنك أن تدمج عدة واجهات برمجية مثل <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-fetch-%D9%81%D9%8A-javascript-r739/" rel=""><code>fetch</code></a> و<a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-battery-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7-%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-%D8%A7%D9%84%D9%88%D8%B9%D9%88%D8%AF-r738/" rel="">الواجهة البرمجية Battery</a> بما أنّها تعيد وعودًا.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2531_29" style="">
<span class="typ">Promise</span><span class="pun">.</span><span class="pln">all</span><span class="pun">([</span><span class="pln">fetch</span><span class="pun">(</span><span class="str">'/users.json'</span><span class="pun">),</span><span class="pln"> navigator</span><span class="pun">.</span><span class="pln">getBattery</span><span class="pun">()]).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">results</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// كلا الوعدين تم تنفيذهما</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	التعامل مع الرفض صعب بالطبع. إذا تم رفض أيّ وعد سيتم إطلاق <code>catch</code> للرفض الأول:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2531_31" style="">
<span class="kwd">var</span><span class="pln"> req1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Promise</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">resolve</span><span class="pun">,</span><span class="pln"> reject</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    </span><span class="com">// setTimeout حدث زائف غير متزامن باستخدام  </span><span class="pln">
    setTimeout</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> resolve</span><span class="pun">(</span><span class="str">'First!'</span><span class="pun">);</span><span class="pln"> </span><span class="pun">},</span><span class="pln"> </span><span class="lit">4000</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> req2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Promise</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">resolve</span><span class="pun">,</span><span class="pln"> reject</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    </span><span class="com">// setTimeout حدث زائف غير متزامن باستخدام  </span><span class="pln">
    setTimeout</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> reject</span><span class="pun">(</span><span class="str">'Second!'</span><span class="pun">);</span><span class="pln"> </span><span class="pun">},</span><span class="pln"> </span><span class="lit">3000</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">
</span><span class="typ">Promise</span><span class="pun">.</span><span class="pln">all</span><span class="pun">([</span><span class="pln">req1</span><span class="pun">,</span><span class="pln"> req2</span><span class="pun">]).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">results</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'Then: '</span><span class="pun">,</span><span class="pln"> results</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}).</span><span class="kwd">catch</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">err</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'Catch: '</span><span class="pun">,</span><span class="pln"> err</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="com">// console من الـ </span><span class="pln">
</span><span class="com">// Catch: Second!</span></pre>

<p>
	ستكون <code>Promise.all</code> مفيدة أكثر للواجهات البرمجية التي تتجه لاستخدام الوعود.
</p>

<h2 id="promise-race">
	Promise.race
</h2>

<p>
	تعدّ الدالة <a href="https://wiki.hsoub.com/JavaScript/Promise/race" rel="external">Promise.race</a> مفيدة فبدلًا من أن يتم الانتظار حتى إنهاء جميع الوعود أو رفضها تقوم بتشغيل أيّ وعد في المصفوفة تم إنهاؤه أو رفضه.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2531_35" style="">
<span class="kwd">var</span><span class="pln"> req1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Promise</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">resolve</span><span class="pun">,</span><span class="pln"> reject</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    </span><span class="com">// setTimeout حدث زائف غير متزامن باستخدام </span><span class="pln">
    setTimeout</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> resolve</span><span class="pun">(</span><span class="str">'First!'</span><span class="pun">);</span><span class="pln"> </span><span class="pun">},</span><span class="pln"> </span><span class="lit">8000</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> req2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Promise</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">resolve</span><span class="pun">,</span><span class="pln"> reject</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    </span><span class="com">// setTimeout حدث زائف غير متزامن باستخدام </span><span class="pln">
    setTimeout</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> resolve</span><span class="pun">(</span><span class="str">'Second!'</span><span class="pun">);</span><span class="pln"> </span><span class="pun">},</span><span class="pln"> </span><span class="lit">3000</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">
</span><span class="typ">Promise</span><span class="pun">.</span><span class="pln">race</span><span class="pun">([</span><span class="pln">req1</span><span class="pun">,</span><span class="pln"> req2</span><span class="pun">]).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">one</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'Then: '</span><span class="pun">,</span><span class="pln"> one</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}).</span><span class="kwd">catch</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">one</span><span class="pun">,</span><span class="pln"> two</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'Catch: '</span><span class="pun">,</span><span class="pln"> one</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="com">// console من الـ </span><span class="pln">
</span><span class="com">// Then: Second!</span></pre>

<p>
	يمكن أن تشغّل حالة الاستخدام طلبًا إلى مصدر أوليّ ومصدر ثانوي (في حال عدم توفر الأوليّ والثانوي).
</p>

<h2 id="-">
	اعتد على الوعود
</h2>

<p>
	كانت الوعود موضوعًا مثيرًا للاهتمام خلال السنوات القليلة الماضية (أو خلال السنوات العشرة الأخيرة إذا كنت مستخدم مجموعة أدوات Dojo) وانتقلت من كونها نمط في إطار عمل جافاسكربت إلى كونها من أساس اللغة. وربما من الأفضل افتراض أنك ستشاهد معظم الواجهات البرمجية الجديدة في جافاسكربت يتم تنفيذها بنمط يعتمد على الوعد، وهذا أمر ممتاز.
</p>

<p>
	إنّ المطورين قادرون على تجنب جحيم رد النداء وتمرير التفاعلات غير المتزامنة مثل أيّ متغير آخر. تستغرق الوعود بعض الوقت لتكون الأدوات الأصلية وقد حان الوقت لتعلّمها.
</p>

<p>
	يمكنك في أي وقت الرجوع إلى توثيق الكائن <a href="https://wiki.hsoub.com/JavaScript/Promise" rel="external"><code>Promise</code></a> في موسوعة حسوب كما ننصحك أيضًا بقراءة صفحة «<a href="https://wiki.hsoub.com/JavaScript/Promise/Using_promises" rel="external">استخدام الوعود</a>» بعد هذه المقالة مباشرةً لوضع ما تعلمته موضع التطبيق.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://davidwalsh.name/promises" rel="external nofollow">JavaScript Promise <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></a> لصاحبه David Walsh
</p>
]]></description><guid isPermaLink="false">740</guid><pubDate>Tue, 17 Sep 2019 06:38:14 +0000</pubDate></item><item><title>&#x627;&#x644;&#x648;&#x627;&#x62C;&#x647;&#x629; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x64A;&#x629; fetch &#x641;&#x64A; JavaScript</title><link>https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-fetch-%D9%81%D9%8A-javascript-r739/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_09/5d8072e747102_fetch.jpg.ae5b0a1e29a256e2db50f71a71bc3423.jpg" /></p>

<p>
	إحدى أسوأ الأسرار التي تمَّ الاحتفاظ بها حول AJAX على الويب هو أنّ الواجهة البرمجية (<abbr title="Application Programming Interface | واجهة برمجية">API</abbr>) الأساسية لها، XMLHttpRequest، لم توجد للغرض الذي نستخدمه الآن. لقد قمنا بعمل جيد في إنشاء واجهة برمجية جيّدة باستخدام الكائن XHR ولكننا نعرف أنه يمكننا القيام بعمل أفضل. نحن نبذل الجهود لتحقيق الأفضل الذي هو الواجهة البرمجية fetch. لنأخذ فكرة عامة عن التابع <code>window.fetch</code> الجديد، المتوفر الآن في Firefox و Chrome Canary.
</p>

<h2 id="-xmlhttprequest">
	الكائن XMLHttpRequest
</h2>

<p>
	إنَّ كائن <a href="https://davidwalsh.name/xmlhttprequest" rel="external nofollow">XHR</a> معقد قليلًا برأيي ولا أريد أن أبدأ بشرح لماذا "XML" تُكتب بأحرف كبيرة بينما "Http" تُكتب بأسلوب سنام الجمل. على أيّة حال، لنلاحظ كيف نستخدم XHR.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7111_6" style="">
<span class="com">// فوضى XHR فقط الحصول على  </span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">window</span><span class="pun">.</span><span class="typ">XMLHttpRequest</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// موزيلا، سفاري...</span><span class="pln">
  request </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">XMLHttpRequest</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">window</span><span class="pun">.</span><span class="typ">ActiveXObject</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// إنترنت إكسبلورر</span><span class="pln">
  </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    request </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ActiveXObject</span><span class="pun">(</span><span class="str">'Msxml2.XMLHTTP'</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln"> 
  </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      request </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ActiveXObject</span><span class="pun">(</span><span class="str">'Microsoft.XMLHTTP'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> 
    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// فتح، إرسال</span><span class="pln">
request</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">'GET'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'https://davidwalsh.name/ajax-endpoint'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
request</span><span class="pun">.</span><span class="pln">send</span><span class="pun">(</span><span class="kwd">null</span><span class="pun">);</span></pre>

<p>
	بالطبع إنَّ أطر عمل جافاسكربت الخاصة بنا تجعل XHR أكثر متعة للعمل، ولكن ما نراه في الأعلى هو مثال بسيط على فوضى XHR.
</p>

<h2 id="-fetch-">
	استخدام fetch الأساسي
</h2>

<p>
	تم توفير دالة <code>fetch</code> في نطاق <code>window</code> العام، الوسيط الأول له هو الرابط URL:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7111_8" style="">
<span class="com">// الرابط (إلزامي)، الخيارات (اختيارية)</span><span class="pln">
fetch</span><span class="pun">(</span><span class="str">'https://davidwalsh.name/some/url'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    method</span><span class="pun">:</span><span class="pln"> </span><span class="str">'get'</span><span class="pln">
</span><span class="pun">}).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">response</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pun">}).</span><span class="kwd">catch</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">err</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// خطأ :(</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	وهذا يشبه إلى حد بعيد الواجهة البرمجية <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-battery-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7-%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-%D8%A7%D9%84%D9%88%D8%B9%D9%88%D8%AF-r738/" rel="">Battery</a> المحدّثة، إذ تستخدم الواجهة البرمجية fetch <a href="https://wiki.hsoub.com/JavaScript/Promise" rel="external">الوعود في جافاسكربت</a> لمعالجة النتائج/ردود النداء:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7111_13" style="">
<span class="com">// معالجة رد بسيط</span><span class="pln">
fetch</span><span class="pun">(</span><span class="str">'https://davidwalsh.name/some/url'</span><span class="pun">).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">response</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pun">}).</span><span class="kwd">catch</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">err</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// خطأ :(</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="com">// "تسلسل لمعالجة أكثر "تطورًا</span><span class="pln">
fetch</span><span class="pun">(</span><span class="str">'https://davidwalsh.name/some/url'</span><span class="pun">).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">response</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="com">//...</span><span class="pln">
</span><span class="pun">}).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">returnedValue</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">}).</span><span class="kwd">catch</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">err</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// خطأ :(</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	إذا لم تكن معتادًا على استخدام <a href="https://wiki.hsoub.com/JavaScript/Promise/then" rel="external"><code>then</code></a>، يجب أن تعتاد عليه لأنها ستنتشر قريبًا في كلّ مكان.
</p>

<h2 id="-">
	ترويسات الطلب
</h2>

<p>
	القدرة على ضبط ترويسات الطلب هي أمر مهم في مرونة الطلب. يمكنك العمل مع ترويسات الطلب بتنفيذ <code>new Headers()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7111_16" style="">
<span class="com">// إنشاء كائن ترويسة فارغ</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> headers </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Headers</span><span class="pun">();</span><span class="pln">

</span><span class="com">// إضافة بعض الترويسات</span><span class="pln">
headers</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="str">'Content-Type'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'text/plain'</span><span class="pun">);</span><span class="pln">
headers</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="str">'X-My-Custom-Header'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'CustomValue'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// للترويسة set و get و check قيم</span><span class="pln">
headers</span><span class="pun">.</span><span class="pln">has</span><span class="pun">(</span><span class="str">'Content-Type'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
headers</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'Content-Type'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// "text/plain"</span><span class="pln">
headers</span><span class="pun">.</span><span class="kwd">set</span><span class="pun">(</span><span class="str">'Content-Type'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'application/json'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// حذف ترويسة</span><span class="pln">
headers</span><span class="pun">.</span><span class="kwd">delete</span><span class="pun">(</span><span class="str">'X-My-Custom-Header'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// إضافة قيم ابتدائية</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> headers </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Headers</span><span class="pun">({</span><span class="pln">
    </span><span class="str">'Content-Type'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'text/plain'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'X-My-Custom-Header'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'CustomValue'</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	يمكنك استخدام التوابع <code>append</code> و <code>has</code> و <code>get</code> و <code>set</code> و <code>delete</code> لتعديل ترويسات الطلب. لاستخدام ترويسات الطلب أنشئ الكائن <code>Request</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7111_18" style="">
<span class="kwd">var</span><span class="pln"> request </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Request</span><span class="pun">(</span><span class="str">'https://davidwalsh.name/some-url'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    headers</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Headers</span><span class="pun">({</span><span class="pln">
        </span><span class="str">'Content-Type'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'text/plain'</span><span class="pln">
    </span><span class="pun">})</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

fetch</span><span class="pun">(</span><span class="pln">request</span><span class="pun">).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">/* معالجة الرد*/</span><span class="pln"> </span><span class="pun">});</span></pre>

<p>
	لنطّلع على عمل الكائنين <code>Response</code> و <code>Request</code>.
</p>

<h2 id="-request">
	الكائن Request
</h2>

<p>
	يمثّل الكائن Request جزء الطلب عند استدعاء التابع <code>fetch</code>، يمكنك إنشاء طلبات مخصصة ومتطورة بتمرير الكائن <code>Request</code> للتابع <code>fetch</code>:
</p>

<ul>
<li>
		<code>method</code> (الطريقة): يمكن أن تكون <code>GET</code> أو <code>POST</code> أو <code>PUT</code> أو <code>DELETE</code> أو <code>HEAD</code>
	</li>
	<li>
		<code>url</code> (الرابط): رابط الطلب
	</li>
	<li>
		<code>headers</code> (الترويسة): ترتبط مع الكائن <code>Headers</code>
	</li>
	<li>
		<code>referrer</code> (المرجع): مرجع الطلب
	</li>
	<li>
		<code>mode</code> (النمط): يكون <code>cors</code> أو <code>no-cors</code> أو <code>same-origin</code>
	</li>
	<li>
		<code>credentials</code> (بيانات الاعتماد): هل تعمل ملفات تعريف الارتباط (cookies) مع الطلب؟ وتأخذ إحدى القيمتين <code>omit</code>، أو <code>same-origin</code>.
	</li>
	<li>
		<code>redirect</code> (إعادة التوجيه): يمكن أن يأخذ القيمة <code>follow</code> أو <code>error</code> أو <code>manual</code>.
	</li>
	<li>
		<code>integrity</code> (التكامل): قيمة تكامل المصدر الفرعي.
	</li>
	<li>
		<code>cache</code> (التخزين المؤقت): وضع التخزين المؤقت ويمكن أن يأخذ إحدى القيم <code>default</code> أو <code>reload</code> أو <code>no-cache</code> عينة عن استخدام الكائن <code>Request</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7111_20" style="">
<span class="kwd">var</span><span class="pln"> request </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Request</span><span class="pun">(</span><span class="str">'https://davidwalsh.name/users.json'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    method</span><span class="pun">:</span><span class="pln"> </span><span class="str">'POST'</span><span class="pun">,</span><span class="pln"> 
    mode</span><span class="pun">:</span><span class="pln"> </span><span class="str">'cors'</span><span class="pun">,</span><span class="pln"> 
    redirect</span><span class="pun">:</span><span class="pln"> </span><span class="str">'follow'</span><span class="pun">,</span><span class="pln">
    headers</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Headers</span><span class="pun">({</span><span class="pln">
        </span><span class="str">'Content-Type'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'text/plain'</span><span class="pln">
    </span><span class="pun">})</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="com">// الآن استخدمه</span><span class="pln">
fetch</span><span class="pun">(</span><span class="pln">request</span><span class="pun">).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">/* معالجة الرد */</span><span class="pln"> </span><span class="pun">});</span></pre>

<p>
	الوسيط الأول URL هو فقط الوسيط الإلزامي، وكل خاصية تصبح للقراءة فقط حالما يتم إنشاء نسخة من الكائن <code>Request</code>، ومن المهم أن نلاحظ أن الكائن <code>Request</code> يملك التابع <code>clone</code> المهم عند استخدام <code>fetch</code> ضمن الواجهة البرمجية Service Worker -- يعد الكائن <code>Request</code> مجرًى ولهذا يجب أن يتم نسخه عند تمريره إلى استدعاء آخر للتابع <code>fetch</code>.
</p>

<p>
	بصمة التابع <code>fetch</code> ولكن نفس استخدام الكائن <code>Request</code> لذا يمكنك القيام بما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7111_23" style="">
<span class="pln">fetch</span><span class="pun">(</span><span class="str">'https://davidwalsh.name/users.json'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    method</span><span class="pun">:</span><span class="pln"> </span><span class="str">'POST'</span><span class="pun">,</span><span class="pln"> 
    mode</span><span class="pun">:</span><span class="pln"> </span><span class="str">'cors'</span><span class="pun">,</span><span class="pln"> 
    redirect</span><span class="pun">:</span><span class="pln"> </span><span class="str">'follow'</span><span class="pun">,</span><span class="pln">
    headers</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Headers</span><span class="pun">({</span><span class="pln">
        </span><span class="str">'Content-Type'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'text/plain'</span><span class="pln">
    </span><span class="pun">})</span><span class="pln">
</span><span class="pun">}).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">/* معالجة الرد */</span><span class="pln"> </span><span class="pun">});</span></pre>

<p>
	من المحتمل أن تستخدم نسخًا من الكائن <code>Request</code> فقط ضمن Service Workers بما أن الكائن <code>Request</code> والتابع <code>fetch</code> يؤديان نفس الوظيفة.
</p>

<h2 id="-response">
	الكائن Response
</h2>

<p>
	التابع <code>then</code> الذي يخص <code>fetch</code> مزود بالكائن <code>Response</code> ولكن يمكنك أيضًا إنشاء كائنات <code>Response</code> بنفسك -- حالة أخرى قد تواجهها عند استخدام service workers. يمكنك ضبط ما يلي عند استخدام الكائن <code>Response</code>:
</p>

<ul>
<li>
		<code>type</code> (النوع): يمكن أن يكون basic أو cors
	</li>
	<li>
		<code>url</code> (الرابط)
	</li>
	<li>
		<code>useFinalURL</code> (استخدام الرابط النهائي): قيمة منطقية للرابط <code>url</code> إذا كان رابطًا نهائيًا أم لا
	</li>
	<li>
		<code>status</code> (الحالة): رمز الحالة (مثلًا 200، 400)
	</li>
	<li>
		<code>ok</code>: قيمة منطقية للاستجابة الناجحة (الحالة في المجال بين 200- 299)
	</li>
	<li>
		<code>statusText</code> (نص الحالة): نص يعبّر عن الحالة وفقًا للرمز (مثلًا: OK)
	</li>
	<li>
		<code>headers</code> (الترويسة): كائن <code>Headers</code> المرتبط بالاستجابة
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7111_25" style="">
<span class="com">// service worker أنشئ ردك لاختبار </span><span class="pln">
</span><span class="com">// جديد (الجسم، الخيارات) Response كائن </span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> response </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Response</span><span class="pun">(</span><span class="str">'.....'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    ok</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln">
    status</span><span class="pun">:</span><span class="pln"> </span><span class="lit">404</span><span class="pun">,</span><span class="pln">
    url</span><span class="pun">:</span><span class="pln"> </span><span class="str">'/'</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="com">// Response يجلب مجدَّدًا نسخة من  الكائن fetch الذي يخص then التابع</span><span class="pln">
fetch</span><span class="pun">(</span><span class="str">'https://davidwalsh.name/'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">.</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">responseObj</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'status: '</span><span class="pun">,</span><span class="pln"> responseObj</span><span class="pun">.</span><span class="pln">status</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	يوفر الكائن <code>Response</code> أيضًا التوابع التالية:
</p>

<ul>
<li>
		clone()‎: تُنشئ نسخة من الكائن <code>Response</code>
	</li>
	<li>
		()error: تعيد كائن <code>Response</code> جديد مرتبط مع خطأ في الشبكة
	</li>
	<li>
		()redirect: تنشئ استجابة جديدة مع رابط URL مختلف
	</li>
	<li>
		()arrayBuffer: تعيد وعدًا يُقبل (resolve) مع ArrayBuffer
	</li>
	<li>
		()blob: تعيد وعدًا يُقبل (resolve) مع Blob
	</li>
	<li>
		()formData: تعيد وعدًا يُقبل (resolve) مع كائن FormData
	</li>
	<li>
		()json: تعيد وعدًا يُقبل (resolve) مع كائن JSON
	</li>
	<li>
		()text: تعيد وعدًا يُقبل (resolve) مع القيمة النصية USVString
	</li>
</ul>
<h1 id="-json">
	التعامل مع JSON
</h1>

<p>
	بفرض أنّك أنشأت طلب لـJSON -- معلومات نتيجة ردود النداء لديها التابع <code>json</code> لتحويل البيانات الخام إلى كائن جافاسكربت:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7111_27" style="">
<span class="pln">fetch</span><span class="pun">(</span><span class="str">'https://davidwalsh.name/demo/arsenal.json'</span><span class="pun">).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">response</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    </span><span class="com">// JSON التحويل إلى </span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> response</span><span class="pun">.</span><span class="pln">json</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">j</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// هو كائن جافاسكربت j</span><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">j</span><span class="pun">);</span><span class="pln"> 
</span><span class="pun">});</span></pre>

<p>
	بالطبع هذا أسهل من (<code>JSON.parse(jsonString</code> لكن طريقة <code>json</code> تعد اختصارًا سهلًا أيضًا.
</p>

<h2 id="-text-html-">
	التعامل مع استجابات Text/HTML الأساسية
</h2>

<p>
	ليست دائما JSON هي صيغة رد الطلب المرغوبة لذا إليك كيف نجعل الاستجابة على شكل نص أو HTML:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7111_29" style="">
<span class="pln">fetch</span><span class="pun">(</span><span class="str">'/next/page'</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">.</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">response</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> response</span><span class="pun">.</span><span class="pln">text</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}).</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">text</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
      </span><span class="com">// &lt;!DOCTYPE ....</span><span class="pln">
      console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">text</span><span class="pun">);</span><span class="pln"> 
  </span><span class="pun">});</span></pre>

<p>
	بإمكانك الحصول على استجابة نصية عبر تسلسل طريقة <code>then</code> للوعد مع طريقة <code>text()</code>‎.
</p>

<h2 id="-">
	التعامل مع استجابات بشكل بيانات ثنائية
</h2>

<p>
	إذا كنت ترغب مثلًا بتحميل صورة باستخدام التابع <code>fetch</code> فإن هذا سيكون مختلفًا.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7111_31" style="">
<span class="pln">fetch</span><span class="pun">(</span><span class="str">'https://davidwalsh.name/flowers.jpg'</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">response</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> response</span><span class="pun">.</span><span class="pln">blob</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">})</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">imageBlob</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      document</span><span class="pun">.</span><span class="pln">querySelector</span><span class="pun">(</span><span class="str">'img'</span><span class="pun">).</span><span class="pln">src </span><span class="pun">=</span><span class="pln"> URL</span><span class="pun">.</span><span class="pln">createObjectURL</span><span class="pun">(</span><span class="pln">imageBlob</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span></pre>

<p>
	يأخذ التابع <code>blob()</code>‎ تدفق الاستجابة وتقرأه حتى يكتمل.
</p>

<h2 id="-">
	الحصول على بيانات النموذج
</h2>

<p>
	استخدام آخر شائع للـAJAX وهو إرسال بيانات نموذج، وإليك كيف يمكن أن نستخدم التابع <code>fetch</code> للحصول على بيانات نموذج مرسلة بالطريقة POST:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7111_33" style="">
<span class="pln">fetch</span><span class="pun">(</span><span class="str">'https://davidwalsh.name/submit'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    method</span><span class="pun">:</span><span class="pln"> </span><span class="str">'post'</span><span class="pun">,</span><span class="pln">
    body</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FormData</span><span class="pun">(</span><span class="pln">document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'comment-form'</span><span class="pun">))</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	وإذا أردت إرسال البيانات بصيغة JSON إلى الخادم:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7111_35" style="">
<span class="pln">fetch</span><span class="pun">(</span><span class="str">'https://davidwalsh.name/submit-json'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    method</span><span class="pun">:</span><span class="pln"> </span><span class="str">'post'</span><span class="pun">,</span><span class="pln">
    body</span><span class="pun">:</span><span class="pln"> JSON</span><span class="pun">.</span><span class="pln">stringify</span><span class="pun">({</span><span class="pln">
        email</span><span class="pun">:</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'email'</span><span class="pun">).</span><span class="pln">value</span><span class="pun">,</span><span class="pln">
        answer</span><span class="pun">:</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'answer'</span><span class="pun">).</span><span class="pln">value
    </span><span class="pun">})</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	سهل جدًا ومريح للعينين أيضًا.
</p>

<h2 id="-">
	قصة لم تُكتب
</h2>

<p>
	رغم أن <code>fetch</code> هي واجهة برمجية سهلة الاستخدام، إلا أنّ الواجهة البرمجية الحالية -تاريخ ترجمة المقال- لا تسمح بإلغاء الطلب مما يجعلها غير مستخدمة لكثير من المطورين.
</p>

<p>
	إن الواجهة البرمجية <code>fetch</code> الجديدة تبدو أفضل وأسهل استخدامًا من XHR. وبعد كل ذلك تمّ إنشاؤها حتى نتمكّن من استخدام AJAX بالطريقة الصحيحة. تملك <code>fetch</code> فوائد الخبرات السابقة، ولا أطيق الانتظار حتى يتم استخدامها على نطاق واسع.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://davidwalsh.name/fetch" rel="external nofollow">‎fetch <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></a> لصاحبه David Walsh
</p>
]]></description><guid isPermaLink="false">739</guid><pubDate>Mon, 30 Sep 2019 13:01:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x648;&#x627;&#x62C;&#x647;&#x629; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x64A;&#x629; Battery &#x641;&#x64A; &#x62C;&#x627;&#x641;&#x627; &#x633;&#x643;&#x631;&#x628;&#x62A;: &#x627;&#x644;&#x648;&#x639;&#x648;&#x62F;</title><link>https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-battery-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7-%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-%D8%A7%D9%84%D9%88%D8%B9%D9%88%D8%AF-r738/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_09/5d806e4f653c4_battery.jpg.29eafe573ef77aae32c961b208515f95.jpg" /></p>

<p>
	أتاح لي العمل في موزيلا وقتًا كافيًا للنظر في الواجهات البرمجية <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> الجديدة، وإحداها هي <a href="https://www.w3.org/TR/battery-status/" rel="external nofollow">الواجهة البرمجية Battery</a>. لقد كتبت سابقًا عن <a href="https://davidwalsh.name/battery-api" rel="external nofollow">الواجهة البرمجية Battery</a> عندما كانت واجهة برمجية جديدة في المتصفحات ولكنها تغيرت لاحقًا وأصبحت واجهة برمجية يعتمد تنفيذها على الوعود ومتوفرة فقط في متصفح غوغل كروم. لنأخذ نظرة عن كيفية استخدام الواجهة البرمجية الجديدة.
</p>

<p>
	بإمكانك الاطلاع على <a href="https://davidwalsh.name/demo/battery-api.php" rel="external nofollow">النسخة التجريبية</a>.
</p>

<p>
	الوظيفة التي نحتاجها ما تزال موجودة لدى الكائن <code>navigator</code> ولكنها الآن على شكل تابع يدعى <code>getBattery</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3003_6" style="">
<span class="pln">navigator</span><span class="pun">.</span><span class="pln">getBattery</span><span class="pun">().</span><span class="pln">then</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">result</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{});</span></pre>

<p>
	يعيد استدعاء التابع <code>getBattery</code> وعدًا ورد النداء الممرّر لـ <a href="https://wiki.hsoub.com/JavaScript/Promise/then" rel="external">then</a> يُعطى كائن <code>BatteryManager</code> يوفر المعلومات التالية كمثال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3003_8" style="">
<span class="com">// النتيجة</span><span class="pln">
</span><span class="typ">BatteryManagery</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    charging</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln">
    chargingTime</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">Infinity</span><span class="pun">,</span><span class="pln">
    dischargingTime</span><span class="pun">:</span><span class="pln"> </span><span class="lit">8940</span><span class="pun">,</span><span class="pln">
    level</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0.59</span><span class="pun">,</span><span class="pln">
    onchargingchange</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">
    onchargingtimechange</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">
    ondischargingtimechange</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">
    onlevelchange</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">null</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بإمكانك الاطلاع على <a href="https://davidwalsh.name/demo/battery-api.php" rel="external nofollow">النسخة التجريبية</a>.
</p>

<p>
	إنّ الواجهة البرمجية الجديدة مختلفة في طريقة التنفيذ ولكنها مشابهة في النتيجة. تذكّر أنّ الواجهة البرمجية القديمة لديها مشاكل مع بطاريات أجهزة ماك ولا يبدو أنّ هذا قد تغيّر. من الصعب مراعاة بادئات المتصفحات المختلفة ولكن حصلنا على نتيجة مقبولة تقريبًا ولكنها تصبح فاشلة تمامًا عندما تتغير المنهجية بالكامل. نأمل أن يكون مالكي المتصفحات الأخرى سريعي التحديث لنحصل مجددًا على واجهة تطبيق موحدة البادئات للمتصفح.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://davidwalsh.name/javascript-battery-api" rel="external nofollow">JavaScript Battery <abbr title="Application Programming Interface | واجهة برمجية">API</abbr>: Promises‎</a> لصاحبه David Walsh
</p>
]]></description><guid isPermaLink="false">738</guid><pubDate>Tue, 17 Sep 2019 05:25:45 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x639;&#x627;&#x645;&#x644;&#x627;&#x62A; &#x627;&#x644;&#x634;&#x631;&#x637;&#x64A;&#x629;</title><link>https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%85%D8%B9%D8%A7%D9%85%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%B4%D8%B1%D8%B7%D9%8A%D8%A9-r708/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/13.jpg.45144bd6e3dc799059dd2cd7fd9da7ee.jpg" /></p>

<p>
	نحتاج في بعض الأحيان إلى تنفيذ إجراءات مختلفة بناءً على شروط مختلفة. للقيام بذلك، يمكنك استخدام التعبير الشرطي <code>if</code> والمعامل الشرطي <code>?</code> الذي يسمى أيضًا «معامل علامة استفهام» (question mark operator، أو المعامل الثلاثي كما سنرى من صياغته).
</p>

<h2 id="-if-">
	التعبير الشرطي <code>if</code>
</h2>

<p>
	يُقيّم التعبير الشرطي <code>if</code> شرطًا، فإذا تحقَّق <code>true</code>، فيُنفِّذ مجموعة من الشيفرات البرمجية. على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_7" style="">
<span class="pln">let year </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">'In which year was ECMAScript-2015 specification published?'</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">year </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">)</span><span class="pln"> alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'You are right!'</span><span class="pln"> </span><span class="pun">);</span></pre>

<p>
	في المثال أعلاه، يكون الشرط عبارة عن فحص بسيط لعملية المساواة <code>year == 2015</code>، ولكنه قد يصبح أكثر تعقيدًا. إذا كنت ترغب في تنفيذ أكثر من تعبير واحد، يجب أن تضع الشيفرة المطلوبة داخل الأقواس المعقوصة <code>{}</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_9" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">year </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"That's correct!"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">"You're so smart!"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	من الأفضل استخدام الأقواس المعقوصة <code>{}</code> في كل مرة تستخدم فيها التعبير الشرطي <code>if</code>، حتى إذا كنت تريد تنفيذ تعبير واحد فقط لأنَّها تُسهِّل قراءة الشيفرة.
</p>

<h2 id="-">
	التحويل المنطقي
</h2>

<p>
	يُقيِّم التعبير الشرطي <code>if</code> التعبير الموجود بين القوسين، ثم تُحوّل النتيجة إلى قيمة منطقية. هل تتذكر قواعد التحويل من الفصل <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AA%D8%AD%D9%88%D9%8A%D9%84-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D8%A3%D9%86%D9%88%D8%A7%D8%B9-r673/" rel="">التحويل بين الأنواع</a>؟ إذن، لنتذكرها سويةً:
</p>

<ul>
<li>
		يُحوَّل العدد <code>0</code>، والسلسلة النصية الفارغة <code>""</code>، و <code>null</code>، و <code>undefined</code>، و<code>NaN</code> جميعها إلى القيمة <code>false</code>. يُطلَق عليها بسبب ذلك «قيم زائفة خاطئة» (falsy values).
	</li>
	<li>
		تُحوَّل القيم الأخرى (أي باستثناء ما سبق) إلى القيمة المنطقية <code>true</code>، لذلك يطلق عليها «القيم الصادقة الصحيحة» (truthy values).
	</li>
</ul>
<p>
	لذلك، لن تُنفَّذ الشيفرة البرمجية التالية بناءً على الشرط المعطى:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_11" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// false القيمة 0 تُقيَّم إلى القيمة</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بينما ستُنفَّذ شيفرة الشرط التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_13" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// true ألقيمة 1 تُقيَّم إلى القيمة</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكنك أيضًا تمرير قيمة منطقية قُيِّمَت مسبقًا إلى الشرط <code>if</code> بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_15" style="">
<span class="pln">let cond </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">year </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">);</span><span class="pln"> </span><span class="com">// قيمة عملية التحقق من المساواة هي قيمة منطقية</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cond</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2 id="-else-">
	الكتلة الشرطية <code>else</code>
</h2>

<p>
	قد يحتوي التعبير الشرطي <code>if</code> على كتلة اختيارية تسمى <code>else</code> تُنفذ عندما يكون الشرط غير محقَّق. أي <strong>إن</strong> تحقق الشرط، فنفِّذ كذا، <strong>أو</strong> نفِّذ كذا. إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_17" style="">
<span class="pln">let year </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">'In which year was the ECMAScript-2015 specification published?'</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">year </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'You guessed it right!'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'How can you be so wrong?'</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// أي قيمة باستثناء 2015</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2 id="-else-if-">
	الشروط المتعددة <code>else if</code>
</h2>

<p>
	تود في بعض الأحيان التحقق من العديد من الحالات لشرط ما. التعبير الشرطي <code>else if</code> (<strong>أو إذا كان</strong> كذا، فنفِّذ كذا) تفي بهذا الغرض. اطلع على هذا المثال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_19" style="">
<span class="pln">let year </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">'In which year was the ECMAScript-2015 specification published?'</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">year </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Too early...'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">year </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Too late'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Exactly!'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الشيفرة أعلاه، تتحقق JavaScript أولاً من الشرط <code>year &lt; 2015</code>. فإذا كان ذلك غير محقَّق، فسيتم الانتقال إلى الشرط التالي <code>year &gt; 2015</code>. وإذا كان هذا أيضًا غير محقَّق، فستُنفَّذ الكتلة المرتبطة بالفرع <code>else</code> أي تُنفَّذ الدالة <code>alert</code>.
</p>

<p>
	يمكن أن يكون هناك أكثر من فرع <code>else if</code>، والكتلة الشرطية الأخيرة <code>else</code> اختيارية.
</p>

<h2 id="-">
	المعامل الشرطي <code>?</code>
</h2>

<p>
	تحتاج في بعض الأحيان إلى إسناد قيمة لمُتغيِّر وفقًا لشرط ما. يمكن تحقيق ذلك بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_21" style="">
<span class="pln">let accessAllowed</span><span class="pun">;</span><span class="pln">
let age </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">'How old are you?'</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  accessAllowed </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  accessAllowed </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">accessAllowed</span><span class="pun">);</span></pre>

<p>
	يتيح لك المعامل الشرطي <code>?</code> أو «علامة الاستفهام» القيام بذلك بطريقة أقصر وأبسط.
</p>

<p>
	يُمثِّل هذا المعامل بعلامة استفهام <code>?</code>. في بعض الأحيان يُطلَق عليه «المعامل الثلاثي» (ternary)، لأن لديه ثلاثة عاملات (operands) وهو المعامل الوحيد في JavaScript الذي يحتوي على هذا العدد.
</p>

<p>
	الصيغة الخاصة به:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_25" style="">
<span class="pln">let result </span><span class="pun">=</span><span class="pln"> condition </span><span class="pun">?</span><span class="pln"> value1 </span><span class="pun">:</span><span class="pln"> value2</span><span class="pun">;</span></pre>

<p>
	يتم تقييم الشرط <code>condition</code>: إذا كان محقَّقًا، يُرجع <code>value1</code>، عدا ذلك يُرجِع <code>value2</code>. على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_27" style="">
<span class="pln">let accessAllowed </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span></pre>

<p>
	من الناحية التقنية، يمكنك حذف الأقواس الموجودة حول <code>age &gt; 18</code>. المعامل الشرطي هذا (أي علامة الاستفهام) له أولوية منخفضة، لذلك يُنفَّذ بعد معامل الموازنة <code>&lt;</code>.
</p>

<p>
	يشبه المثال التالي المثال السابق مع اختلاف طفيف جدًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_29" style="">
<span class="com">// أولًا age &gt; 18 يُنفَّذ معامل الموازنة</span><span class="pln">
</span><span class="com">// (لا حاجة لاستخدام الأقواس)</span><span class="pln">
let accessAllowed </span><span class="pun">=</span><span class="pln"> age </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">18</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span></pre>

<p>
	لكن الأقواس تجعل الشيفرة أكثر قابلية للقراءة، لذلك نوصي باستخدامها.
</p>

<p>
	<strong>ملاحظة</strong>: في المثال أعلاه، تجنب استخدام معامل علامة الاستفهام لأنَّ معامل الموازنة نفسه يُرجِع <code>true/false</code>؛ أي المثال السابق يكافئ:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_31" style="">
<span class="pln">let accessAllowed </span><span class="pun">=</span><span class="pln"> age </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">;</span></pre>

<h2 id="-">
	المعامل الشرطي <code>?</code> المتعدد
</h2>

<p>
	يمكن لسلسلة من المعاملات الشرطية <code>?</code> إرجاع القيمة التي تعتمد على أكثر من شرط واحد. اطلع بتفحُّص على المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_33" style="">
<span class="pln">let age </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">'age?'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">18</span><span class="pun">);</span><span class="pln">
let message </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">'Hi, baby!'</span><span class="pln"> </span><span class="pun">:</span><span class="pln">
  </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">'Hello!'</span><span class="pln"> </span><span class="pun">:</span><span class="pln">
  </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">100</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">'Greetings!'</span><span class="pln"> </span><span class="pun">:</span><span class="pln">
  </span><span class="str">'What an unusual age!'</span><span class="pun">;</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> message </span><span class="pun">);</span></pre>

<p>
	قد يكون من الصعب فهم الشيفرة السابقة في البداية. ولكن بعد التمعُّن بها قليلًا، يمكنك أن ترى أنَّها مجرد تسلسل عادي من الاختبارات:
</p>

<ol>
<li>
		يتحقق المعامل <code>?</code> الأول من الشرط <code>age &lt; 3</code>
	</li>
	<li>
		إذا كان الشرط السابق محقَّقًا، فسيُرجِع <code>Hi, baby!‎</code>؛ خلاف ذلك، فإنَّه يستمر في التحقق من التعبير بعد النقطتين <code>:</code>، ويتحقق من الشرط <code>age &lt; 18</code>.
	</li>
	<li>
		إذا كان الشرط السابق محقَّقًا، فسيُرجِع <code>Hello!‎</code>؛ خلاف ذلك، فإنه يستمر في التحقق من التعبير بعد النقطتين <code>:</code> الثانية، ويَتحقَّق من الشرط <code>age &lt; 100</code>.
	</li>
	<li>
		إذا كان الشرط السابق محقَّقًا، فسيُرجِع <code>Greetings!</code> خلاف ذلك، فإنه يستمر في التحقق من التعبير بعد النقطتين <code>:</code> الأخيرتين، ويتحقق من الشرط <code>What an unusual age!‎</code>.
	</li>
</ol>
<p>
	إليك تنفيذ المثال السابق باستخدام <code>if..else</code> فقط:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_35" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Hi, baby!'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">18</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Hello!'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">100</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Greetings!'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'What an unusual age!'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3 id="-">
	الاستخدام غير التقليدي للمعامل <code>?</code>
</h3>

<p>
	في بعض الأحيان، يُستخدَم معامل علامة الاستفهام <code>?</code> بديلًا عن المعامل الشرطي <code>if</code> بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_37" style="">
<span class="pln">let company </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">'Which company created JavaScript?'</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
</span><span class="pun">(</span><span class="pln">company </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Netscape'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln">
   alert</span><span class="pun">(</span><span class="str">'Right!'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> alert</span><span class="pun">(</span><span class="str">'Wrong.'</span><span class="pun">);</span></pre>

<p>
	اعتمادًا على الشرط <code>company == 'Netscape'‎</code>، إمَّا أن يُنفَّذ التعبير الأول أو الثاني بعد المعامل <code>?</code> وتٌظهر الدالة <code>alert</code> القيمة الناتجة بناءً على الشرط. على أي حال، لا نوصي باستخدام معامل علامة الاستفهام <code>?</code> بهذه الطريقة.
</p>

<p>
	الشيفرة السابقة أقصر من شيفرة المعامل الشرطي <code>if</code> المقابلة، الذي يطبقه بعض المبرمجين لكنه يولد شيفرة صعبة القراءة.
</p>

<p>
	سنعيد كتابة الشيفرة السابقة باستخدام المعامل الشرطي <code>if</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_39" style="">
<span class="pln">let company </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">'Which company created JavaScript?'</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">company </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Netscape'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="str">'Right!'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="str">'Wrong.'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	عند إلقاء نظرة على الشيفرة للوهلة الأولى، من السهل فهم كتل التعليمات البرمجية التي تمتد عموديًّا لعدة أسطر بشكل أسرع من تلك الأفقية الطويلة.
</p>

<p>
	الغرض من معامل علامة الاستفهام <code>?</code> هو إرجاع قيمة ما حسب الشرط المُعطى. يُفضل استخدامه لذلك فقط. استخدم المعامل الشرطي <code>if</code> عندما تحتاج لتنفيذ فروع مختلفة من الشيفرة.
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2 id="-">
	تمارين
</h2>

<h3 id="-if-">
	التعبير الشرطي <code>if</code> (سلسلة نصية مع صفر)
</h3>

<p class="task__importance">
	الأهمية: 5
</p>

<p>
	هل ستُنفَّذ الدالة <code>alert</code> داخل الشرط التالي؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_41" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="str">"0"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Hello'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الحل:</strong>
</p>

<div class="task__answer">
	<p>
		نعم، سوف تُنفَّذ وتظهر الرسالة. الغرض من هذا التمرين هو التذكير بأنَّ أي سلسلة نصية باستثناء الفارغة منها (من ضمنها <code>"0"</code> الغير فارغة) تُحوَّل إلى القيمة <code>true</code> في السياق المنطقي.
	</p>
</div>

<h3 id="-javascript">
	اسم JavaScript
</h3>

<p class="task__importance">
	الأهمية: 2
</p>

<p>
	باستخدام الصيغة <code>if..else</code>، اكتب الشيفرة التي تسأل: "ما هو الاسم الرسمي لجافاسكربت؟" إذا أدخل المستخدم "ECMAScript"، تخرج الشيفرة "صحيح!"، وإلا - تُخرج: "ألا تعرف؟ ECMAScript!"
</p>

<p style="text-align: center;">
	<img alt="ifelse_task2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="30589" data-unique="5in8kyuiv" src="https://academy.hsoub.com/uploads/monthly_2019_07/ifelse_task2.png.cc32b3cf09e8a2e97c4643c8f7dbc78e.png"></p>

<p>
	<strong>الحل</strong>:
</p>

<div class="task__answer">
	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9003_43" style="">
<span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">
</span><span class="tag">&lt;html&gt;</span><span class="pln">
</span><span class="tag">&lt;body&gt;</span><span class="pln">
  </span><span class="tag">&lt;script&gt;</span><span class="pln">
    </span><span class="str">'use strict'</span><span class="pun">;</span><span class="pln">
    let value </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">'ما هو الاسم الرسمي لجافاسكربت؟'</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">value </span><span class="pun">==</span><span class="pln"> </span><span class="str">'ECMAScript'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      alert</span><span class="pun">(</span><span class="str">'صحيح!'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      alert</span><span class="pun">(</span><span class="str">"ألا تعرف الاسم الرسمي؟ إنه ECMAScript!"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
  </span><span class="tag">&lt;/script&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>
</div>

<h3 id="-">
	إظهار إشارة
</h3>

<p class="task__importance">
	الأهمية: 2
</p>

<p>
	باستخدام الصيغة <code>if..else</code>، اكتب الشيفرة التي تحصل على عدد عن طريق الدالة <code>prompt</code> ثم أظهر عبر الدالة <code>alert</code> القيمة:
</p>

<ul>
<li>
		<code>1</code> إذا كان العدد أكبر من صفر.
	</li>
	<li>
		<code>-1</code> إذا كان العدد أقل من صفر.
	</li>
	<li>
		<code>0</code> إذا كان العدد يساوي الصفر.
	</li>
</ul>
<p>
	في هذا التمرين، نفترض أنَّ القيمة المُدخلة دائمًا عدد.
</p>

<p>
	<strong>الحل:</strong>
</p>

<div class="task__answer">
	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_45" style="">
<span class="pln">let value </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">'Type a number'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">value </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">value </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  alert</span><span class="pun">(</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>
</div>

<h3 id="-if-">
	تحويل التعبير الشرطي <code>if</code> إلى صيغة المعامل <code>?</code>
</h3>

<p class="task__importance">
	الأهمية: 5
</p>

<p>
	أعد كتابة التعبير الشرطي <code>if</code> باستخدام المعامل الثلاثي <code>?</code>
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_47" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> b </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  result </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Below'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  result </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Over'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الحل</strong>:
</p>

<div class="task__answer">
	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_49" style="">
<span class="pln">result </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> b </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">'Below'</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">'Over'</span><span class="pun">;</span></pre>
</div>

<h3 id="-if-else-">
	تحويل التعبير الشرطي <code>if..else</code> إلى صيغة المعامل <code>?</code>
</h3>

<p class="task__importance">
	الأهمية: 5
</p>

<p>
	أعد كتابة التعبير الشرطي <code>if..else</code> باستخدام المعامل الثلاثي <code>?</code>. لتسهيل قراءة الشيفرة، يوصى بتقسيمها إلى أسطر متعددة .
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_51" style="">
<span class="pln">let message</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">login </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Employee'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Hello'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">login </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Director'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Greetings'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">login </span><span class="pun">==</span><span class="pln"> </span><span class="str">''</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'No login'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  message </span><span class="pun">=</span><span class="pln"> </span><span class="str">''</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الحل
</p>

<div class="task__answer">
	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9003_53" style="">
<span class="pln">let message </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">login </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Employee'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">'Hello'</span><span class="pln"> </span><span class="pun">:</span><span class="pln">
  </span><span class="pun">(</span><span class="pln">login </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Director'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">'Greetings'</span><span class="pln"> </span><span class="pun">:</span><span class="pln">
  </span><span class="pun">(</span><span class="pln">login </span><span class="pun">==</span><span class="pln"> </span><span class="str">''</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">'No login'</span><span class="pln"> </span><span class="pun">:</span><span class="pln">
  </span><span class="str">''</span><span class="pun">;</span></pre>
</div>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/ifelse" rel="external nofollow">conditional operators</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%85%D8%B9%D8%A7%D9%85%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%86%D8%B7%D9%82%D9%8A%D8%A9-r778/" rel="">المعاملات المنطقية</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D8%AA%D9%81%D8%A7%D8%B9%D9%84%D9%8A%D8%A9-confirm-%D8%8Cprompt-%D8%8Calert-r701/" rel="">الدوال التفاعلية: confirm ،prompt ،alert</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">708</guid><pubDate>Thu, 04 Jul 2019 18:01:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62F;&#x648;&#x627;&#x644; &#x627;&#x644;&#x62A;&#x641;&#x627;&#x639;&#x644;&#x64A;&#x629;: confirm &#x60C;prompt &#x60C;alert</title><link>https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D8%AA%D9%81%D8%A7%D8%B9%D9%84%D9%8A%D8%A9-confirm-%D8%8Cprompt-%D8%8Calert-r701/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/12.jpg.1f975e04413dee6db800985f91f152f0.jpg" /></p>

<p>
	في هذا الجزء من المقالات التعليمية، نتطرَّق إلى لغة JavaScript كما هي بدون تعديلات خاصة بالبيئة. لكن ما زلنا نستخدم المتصفح كبيئة تجريبية، لذلك يجب أن تتعرف على عددٍ قليلٍ من دوال واجهة المستخدم الخاصة به. ستتعرف في هذا الفصل على هذه الدوال التفاعلية الخاصة بالمتصفح.
</p>

<h2 id="-alert-">
	الدالة <code>alert</code>
</h2>

<p>
	الصياغة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6397_7" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="pln">message</span><span class="pun">);</span></pre>

<p>
	تعرض هذه الدالة رسالة نصية وتوقف تنفيذ السكربت مؤقتًا حتى يضغط المستخدم على «موافق» (OK). إليك الشيفرة البسيطة التالية مثلًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6397_9" style="">
<span class="pln">alert</span><span class="pun">(</span><span class="str">"مرحبًا"</span><span class="pun">);</span></pre>

<p>
	تسمى الرسالة النصية التي تظهر على شكل نافذة صغيرة تدعى «النافذة المنبثقة الشرطية» (modal window، وهي عنصر تحكم رسومي)؛ تعني كلمة «شرطية» أنه لا يمكن للزائر التفاعل مع بقية الصفحة، أو الضغط على أزرار أخرى وما إلى ذلك، إذ تشترط عليه التفاعل معها فقط، أي حتى يضغط على «موافق» (Ok) في هذه الحالة.
</p>

<h2 id="-prompt-">
	الدالة <code>prompt</code>
</h2>

<p>
	تقبل الدالة <code>prompt</code> وسيطين (arguments) لتكون صياغتها بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6397_11" style="">
<span class="pln">result </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="pln">title</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="kwd">default</span><span class="pun">]);</span></pre>

<p>
	تعرض هذه الدالة نافذة منبثقة شرطية مع رسالة نصية مخصصة، وحقل إدخال للمستخدم، وزرَّين (موافق [OK] وإلغاء [CANCEL]).
</p>

<ul>
<li>
		الوسيط <code>title</code>: هو عبارة عن النص الذي سيعرض للمستخدم.
	</li>
	<li>
		الوسيط <code>default</code>: هو وسيط اختياري يمثِّل القيمة الأولية لحقل الإدخال الخاص بالمستخدم.
	</li>
</ul>
<p>
	قد يكتب المستخدم شيئًا ما في حقل الإدخال، ثمَّ يضغط على موافق (Ok). أو يمكنه إلغاء الإدخال عند الضغط على إلغاء (CANCEL) أو الضغط على مفتاح الهروب (Esc).
</p>

<p>
	استدعاء الدالة <code>prompt</code> يرجع سلسلة نصية تمثِّل القيمة التي أدخلها المستخدم في حقل الإدخال أو يرجع القيمة <code>null</code> إذا تم الخروج من النافذة وإلغائها. جرب نفِّذ المثال التالي في الطرفية وعدل عليه:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6397_15" style="">
<span class="pln">let age </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">'كم عمرك؟'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">);</span><span class="pln">
alert</span><span class="pun">(`عمرك</span><span class="pln"> $</span><span class="pun">{</span><span class="pln">age</span><span class="pun">}</span><span class="pln"> </span><span class="pun">سنة!`);</span></pre>

<p>
	في IE (أي المتصفح Internet Explorer)، دائمُا ما يتم إضافة الوسيط <code>default</code>. أي هذا الوسيط اختياري في جميع المتصفحات باستثناء المتصفح IE الذي يعدُّه اجباريًّا، وإذا لم نحدِّد قيمته، يفترض المتصفح Internet Explorer أنَّ قيمته <code>"undefined"</code>.
</p>

<p>
	نفِّذ هذه الشيفرة في متصفح Internet Explorer لرؤية الناتج:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6397_17" style="">
<span class="pln">let test </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"Test"</span><span class="pun">);</span></pre>

<p>
	لجعل الدالة <code>prompt</code> تعمل جيدًا في المتصفح IE، نوصي دائمًا بتمرير قيمة الوسيط الثاني <code>default</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6397_21" style="">
<span class="pln">let test </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"Test"</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln"> </span><span class="com">// &lt;-- IE للمتصفح</span></pre>

<h2 id="-confirm-">
	الدالة <code>confirm</code>
</h2>

<p>
	الصياغة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6397_23" style="">
<span class="pln">result </span><span class="pun">=</span><span class="pln"> confirm</span><span class="pun">(</span><span class="pln">question</span><span class="pun">);</span></pre>

<p>
	تُظهر الدالة <code>confirm</code> نافذة منبثقة شرطية تحتوي على سؤال <code>question</code>، وزريّن (موافق [OK] وإلغاء [CANCEL]). تكون النتيجة <code>true</code> إذا ضغط المستخدم على الزر "Ok" وتكون <code>false</code> عدا ذلك. جرِّب المثال التالي في طرفيتك:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6397_25" style="">
<span class="pln">let isBoss </span><span class="pun">=</span><span class="pln"> confirm</span><span class="pun">(</span><span class="str">"Are you the boss?"</span><span class="pun">);</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln"> isBoss </span><span class="pun">);</span></pre>

<h2 id="-">
	الخلاصة
</h2>

<p>
	ذكرنا في هذا المقال ثلاثة دوال للتفاعل مع مستخدمي الموقع وهي:
</p>

<ul>
<li>
		الدالة <code>alert</code>: تعرض رسالة لإعلام المستخدم بشئ ما، وُتعطل كافة عمليات الصفحة حتى يتفاعل مع هذه الرسالة.
	</li>
	<li>
		الدالة <code>prompt</code>: تعرض رسالة تطلب من المستخدم إدخال شيء ما في حقل إدخال خاص لتعيد القيمة المدخلة في سلسلة نصية، أو ترجع القيمة <code>null</code> إذا تم العملية.
	</li>
	<li>
		الدالة <code>confirm</code>: تعرض رسالة (بمثابة سؤال) وتنتظر من المستخدم الرد عليها بالقبول أو الرفض، أي تكون النتيجة <code>true</code> إذا تم الضغط على زر "Ok" أو تكون <code>false</code> عدا ذلك.
	</li>
</ul>
<p>
	كل هذه الدوال مشروطة: فهي تتوقف عن تنفيذ السكربت ولا تسمح للمستخدم بالتفاعل مع بقية الصفحة حتى يتم التفاعل مع النافذة التي تعرضها.
</p>

<p>
	هناك اثنين من القيود التي تشترك بها جميع الدوال المذكورة أعلاه:
</p>

<ol>
<li>
		يحدد المتصفح الموقع الذي ستظهر فيه النافذة، وعادة ما يكون في الوسط أو الأعلى.
	</li>
	<li>
		يعتمد شكل النافذة أيضًا على المتصفح، ولا يمكننا تعديله.
	</li>
</ol>
<p>
	هذا هو ثمن البساطة. هناك طرق أخرى لإظهار نوافذ أكثر جمالًا وفاعلية، ولكن إذا كانت التنسيقات الجمالية غير مهمة، فهذه الدوال تفي بالغرض.
</p>
<style type="text/css">
.task__importance {
    color: #999;
    margin-left: 30px;
}

.task__answer {
    border: 3px solid #f7f6ea;
    margin: 20px 0 14px;
    position: relative;
    display: block;
    padding: 25px 30px;
}
code {
    background-color: rgb(250, 250, 250);
    border-radius: 3px;
}</style>
<h2 id="-">
	تمارين
</h2>

<h3 id="-">
	صفحة بسيطة
</h3>

<p class="task__importance">
	الأهمية: 4
</p>

<p>
	قم بإنشاء صفحة ويب تطلب اسمًا ما ثم تعرضه.
</p>

<p>
	الحل
</p>

<div class="task__answer">
	<p>
		شيفرة JavaScript:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6397_27" style="">
<span class="pln">let name </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"ما اسمك؟"</span><span class="pun">,</span><span class="pln"> </span><span class="str">""</span><span class="pun">);</span><span class="pln">
alert</span><span class="pun">(</span><span class="pln">name</span><span class="pun">);</span></pre>

	<p>
		الشيفرة كاملة:
	</p>

	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6397_29" style="">
<span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">
</span><span class="tag">&lt;html&gt;</span><span class="pln">
</span><span class="tag">&lt;body&gt;</span><span class="pln">

  </span><span class="tag">&lt;script&gt;</span><span class="pln">
    </span><span class="str">'use strict'</span><span class="pun">;</span><span class="pln">

    let name </span><span class="pun">=</span><span class="pln"> prompt</span><span class="pun">(</span><span class="str">"ما اسمك؟"</span><span class="pun">,</span><span class="pln"> </span><span class="str">""</span><span class="pun">);</span><span class="pln">
    alert</span><span class="pun">(</span><span class="pln">name</span><span class="pun">);</span><span class="pln">
  </span><span class="tag">&lt;/script&gt;</span><span class="pln">

</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>
</div>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://javascript.info/alert-prompt-confirm" rel="external nofollow">Interaction: alert, prompt, confirm</a> من كتاب <a href="https://javascript.info/js" rel="external nofollow">The JavaScript Language</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%85%D8%B9%D8%A7%D9%85%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%B4%D8%B1%D8%B7%D9%8A%D8%A9-r708/" rel="">المعاملات الشرطية</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/javascript/%D9%85%D8%B9%D8%A7%D9%85%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%88%D8%A7%D8%B2%D9%86%D8%A9-r700/" rel="">معاملات الموازنة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA/" rel="">كامل مقالات دليل تعلم جافاسكربت</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">701</guid><pubDate>Mon, 01 Jul 2019 13:03:00 +0000</pubDate></item></channel></rss>
