أعجوبة

البرمجيات الحُرة والمفتوحة المصدر

أدوات المستخدم

أدوات الموقع


docs:javascript-mistakes-you-must-avoid

اختلافات

عرض الاختلافات بين النسخة المختارة و النسخة الحالية من الصفحة.

رابط إلى هذه المقارنة

جانبي المراجعة السابقةالمراجعة السابقة
docs:javascript-mistakes-you-must-avoid [2011/08/28 10:24] – [التلاعب بـDOM باستخدام innerHTML] alsadidocs:javascript-mistakes-you-must-avoid [2015/04/23 03:19] (حالي) – تحرير خارجي 127.0.0.1
سطر 1: سطر 1:
 +{{tag>مقالات مترجمة برمجة مواقع ويب جافاسكربت}}
 +====== أخطاء جافاسكربت عليك تجنّبها ======
 +  * صاحب المقالة هو المطور الباكستاني [[http://www.ifadey.com/about/|iFadey]]
 +  * مصدر المقالة: http://www.ifadey.com/2011/05/javascript-mistakes-you-must-avoid/
 +  * ترجمة عبد الرحيم الفاخوري
 +
 +إذا كنت جديداً على جافاسكربت – سواء كنت تكتب سكربتات صَرِفَة أو تستخدم إطار عمل (jQuery, Mootools, Dojo, YUI) معها، فعليك تفادي بعض الأخطاء. هذه قائمة بالأخطاء التي قد تقع بها كمبتدئ:
 +
 +===== إشارة المساواة (=) =====
 +
 +قد تعلم أنّ للمقارنة في جافاسكربت طريقتان. الأولى استخدام إشارتي مساواة ( == ). بهذه الطريقة تقارن القيمة، لكنها لا تقارن نوع البيانات. فمثلاً، إذا قارنت بين الرقم 1 و قيمة true فستكون النتيجة صحيحة (true)
 +
 +<code javascript>
 +if( 1 == true ) {
 +   //this code will run
 +}
 +</code>
 +هنا أمثلة أخرى:
 +<code javascript>
 +1 == "1"        //true
 +"true" == true  //false
 +1 == true       //true
 +"0" == 0        //true
 +"" == 0         //true
 +" " == 0        //true
 +"Str" == false  //false
 +"Str" == true   //false
 +</code>
 +
 +بعض النتائج هنا لا يتوقّعها من لا يعلم كيف تتعامل جافاسكربت مع علامة ( == ). كلّ المعاملات هنا – مهما كان نوع بياناتها – يتمّ تحويلها إلى قيمتها النصّية قبل المقارنة.
 +
 +فلنأخذ المثال الأوّل (1==”1”). القيمة الأولى رقم بالأساس، لذا لا يتمّ تحويلها، ولكن المدخل الثاني من نوع "نصّيّ"، لذا يتمّ تحويله أو قراءته على أنّه رقم. النصّ "1” يتمّ تحويله إلى الرقم 1.
 +
 +المخرجات في المثال الثاني false، وذلك لأنّه عند محاولة تحويل قيمة سلسلة نصّية فيها محارف وليس أرقامًا، فإن التحويل سينتج عنه NaN والتي تعني "ليس رقماً" أو Not a Number. إذا قورن أيّ شيء بـ Nan هكذا فستكون النتيجة false.
 +
 +يمكنك معرفة نتيجة التحويل إلى رقم عن طريق تعريفها بـ Number. هنا بعض الاختبارات في Firebug:
 +
 +{{ :docs:jsnumberfirebug.png |}}
 +
 +قد تتساءل الآن عن كيفيّة استخدام ثلاثة إشارات مساواة هكذا ( === ). تستخدم هذه الطريقة لمقارنة نوع البيانات أيضاً، وليس قيمتها وحسب. إذا كان نوع المدخلين مختلفاً، فستكون النتيجة false دائماً. يجب أن يكون النوع والقيمة متساويين في المدخَلَين لتعطيك هذه المقارنة true.
 +<code javascript>
 +4 === 4         //true
 +"2" === 2       //false
 +1 === true       //false
 +"true" === true //false
 +</code>
 +===== عدم إعطاء القيمة null للأنواع المرجعيّة =====
 +
 +من الأخطاء الشائعة التي يقع فيها العديد من مطوّري ومبرمجي جافاسكربت عدم إعطاء القيمة null للأنواع المرجعيّة كالمصفوفات والكائنات عند الانتهاء من استخدامها. ألق نظرة على المثال التالي:
 +<code javascript>
 +var arr = [1, 2, 3];
 + 
 +//perform some processing on arr
 + 
 +//assign null to arr when its use is finished
 +arr = null;
 +</code>
 +
 +من فوائد إعطاء الأنواع المرجعيّة قيمة null استعادةُ مجمع القمامة (في محرّك جافاسكربت) الذاكرةَ المستخدمة في ذاك المتغيّر تلقائيًّا. اعلم أنّ هذا مهمّ جدًّا للمتغيرات ذات المحتوى الكبير، كالمتغيّرات العامّة. تزال المتغيّرات المحلّيّة تلقائيًّا عند خروجها من نطاق الاستخدام (خاصّة إذا كان محرّك جافاسكربت بمجمع قمامة Mark أو Sweep).
 +
 +بَدء متغيّر مرجعيّ
 +
 +لا تحاول إنشاء أكثر من متغيّر مرجعيّ في عِبارة واحدة. لاحظ المثال:
 +
 +<code javascript>
 +var arr1 = [1, 2, 3],
 + arr2 = ['a', 'b', 'c'];
 + 
 +//reset both arrays
 +arr1 = arr2 = [];
 + 
 +//add a single item in arr2 and arr1
 +arr2.push( 32 );
 +arr1.push( 10 );
 + 
 +//print both arrays and you will see same result
 +//OUTPUT: 10, 32
 +alert( arr1.join() );
 +alert( arr2.join() );
 +</code>
 +
 +تُنشأ في السطرين الأولين مصفوفتين، ثمّ يُعاد إنشاء هاتين المصفوفتين بقيم فارغة في السطر الخامس. المشكلة في هذه الطريقة أنّ كلتي المصفوفتين (arr1 و arr2) تشيران إلى نفس المصفوفة في الذاكرة، لذا ستنعكس تغييرات أيّ منهما على الأخرى.
 +
 +يُضاف الرقم 32 إلى المصفوفة الثانية arr2 في السطر الثامن، ثمّ يضاف الرقم 10 إلى المصفوفة الأولى في السطر التاسع. لفحص قيم كلتي المصفوفتين استخدمنا join لكلّ منهما في السطرين الثالث عشر والرابع عشر. لاحظ أنّ المصفوفتين تحويان نفس القيم!
 +
 +===== لا تَنْسَ الكلمة المفتاحيّة var =====
 +
 +يمكنك الإعلان عن متغيّرات في جافاسكربت باستخدام var، ويمكنك أيضاً استخدام المتغيرات دون الإعلان عنها. هناك اختلاف هامّ بين هاتين الطريقتين في استخدام المتغيّرات. انظر إلى المثال التالي:
 +<code javascript>
 +function createVar() {
 +       var myVar = 'local';
 +};
 + 
 +alert( myVar ); //output: undefined
 +</code>
 +
 +كما لاحظت في المثال السابق فإنّ تعريف متغيّر باستخدام var يجعل الوصول إليها من خارج الدالّة غير ممكن. فلنجرّب الآن الإعلان عن متغير دون استخدام var
 +<code javascript>
 +function createVar() {
 +       myVar = 'local';
 +};
 + 
 +alert( myVar ); //output: local
 +</code>
 +
 +
 +لاحظ أنّ المتغير المعرف دون var يمكن استخدامه من خارج الدالّة أيضاً، أي أنّ var يجعل المتغيّرات محلّيّة. لهذا انتبه عند استخدام متغيّرات في جافاسكربت. دائماً عرّف متغيّراتك باستخدام var.
 +
 +===== عدم استخدام الإعلان عن أحداث =====
 +
 +إرفاق معالج أحداث سهل في جافاسكربت. الكود في المثال التالي يضيف للوسم الذي يحمل id قيمته myLink متحكّماً بالنقر:
 +<code javascript>
 +document.getElementById('myLink').addEventListener( 'click', function() {
 +  //you code goes here...
 +}, false );
 +</code>
 +افترض أنّك تريد إضافة متحكّم بالنقرات إلى كلّ عناصر td في الجدول. هل ستقوم بإضافة متحكّم لكلّ عنصر td في هذا الجدول؟
 +
 +<code html>
 +<table id="myTable">
 +  <tbody>
 +     <tr>
 +        <td>1, 1</td>
 +        <td>1, 2</td>
 +     </tr>
 + 
 +     <tr>
 +        <td>2, 1</td>
 +        <td>2, 2</td>
 +     </tr>
 +  </tbody>
 +</table>
 +</code>
 +سيساعدنا مندوبو الحدث. سنضيف هنا متحكّماً بالأحداث من نوع "نقرة مفردة" إلى myTable وسنتعامل من خلاله مع عناصر td لنعرف إذا نقرت أم لا. في هذه الحالة ليس علينا إضافة متحكّم بالأحداث لكلّ عنصر td في الجدول فيما يعرف بمندوب الحدث. هذا مثال:
 +
 +<code javascript>
 +document.getElementById( 'myTable' ).addEventListener( 'click', function( e ) {
 +     if( e.target && e.target.nodeName == 'TD' ) {
 +        console.log( e.target.innerHTML );
 + 
 +        //to access id
 +        //console.log( e.target.id );
 + 
 +        //to access className
 +        //console.log( e.target.className );
 +     }
 +  }, false );
 +</code>
 +
 +===== عدم التفريق بين innerText و innerHTML =====
 +
 +لا يميّز المطوّرون الجدد في العادة بين خصائص innerHTML و innerText. يستخدم كلا الإثنين مع العناصر element objects. يتعامل innerHTML مع كود html داخل العنصر، بينما يتعامل innerText مع النصّ داخل العنصر.
 +
 +{{:docs:innerhtml.png|}}
 +
 +النصّ تحت Output مخرجات الأمر السابق. لاحظ أنّ وسوم HTML (في هذه الحالة وسم الفقرة <p>) تُضَمَّن في المخرجات.
 +
 +لنلقِ نظرة الآن على مخرجات innerText
 +
 +{{:docs:innertext-1.png|}}
 +
 +كما ترى في المثال أعلاه، يأخذ innerText النصّ داخل العنصر دون وسوم html الموجودة معه. {لاحظ اختفاء وسم الفقرة هنا}
 +
 +===== إضافة العُقَد  بكمية كبيرة =====
 +
 +من الشائع في جافاسكربت تمديد قائمة العُقَد لتشمل عناصر في DOM. قد ترغب على سبيل المثال – بتمديد قائمة أسماء لتشمل ul تمّ استقبالها من الخادم باستخدام أجاكس. هذه إحدى الطرق المستخدمة لهذا الغرض:
 +
 +<code javascript>
 +window.onload = function() {
 +//ul element - <ul id="list"></ul>
 +var list = document.getElementById( 'list' );
 + 
 +var item = null;
 + 
 +//suppose this json is returned from ajax call
 +var ajaxResponse = [
 +   { 'name' : 'Haiku' },
 +   { 'name' : 'Linux' },
 +   { 'name' : 'OS X' },
 +   { 'name' : 'Windows' }
 +];
 + 
 +//add all names in ajaxReponse to documentFragment
 +for( var i in ajaxResponse ) {
 +   item = document.createElement( 'li' );
 +   item.appendChild( document.createTextNode( ajaxResponse[ i ].name ) );
 +   list.appendChild( item );
 +}
 +} //end onload
 + 
 +/*
 +..:: OUTPUT ::..
 +<ul id="list">
 +<li>Haiku</li>
 +<li>Linux</li>
 +<li>OS X</li>
 +<li>Windows</li>
 +</ul>
 +*/
 +</code>
 +
 +المشكلة في هذه الطريقة أنّه في كلّ مرّة يتم فيها تمديد العنصر ليشمل حلقة "for in”، يتمّ تحديث DOM فوراً. هذا قد يؤثّر على الأداء، فالتلاعب بـ DOM عملية مكلفة!
 +
 +DocumentFragment إصدار خفيف من المستند ليس له أثر في ما يظهر لمستخدم الصفحة.
 +
 +نفس هذه المخرجات يمكن الحصول عليها باستخدام DocumentFragment. DocumentFragment إصدار خفيف من المستند ليس له أثر في ما يظهر لمستخدم الصفحة. هذا مثال لاستخدام DocumentFragment لزيادة عناصر قائمة.
 +<code javascript>
 +window.onload = function() {
 +   //create DocumentFragment
 +   var documentFragment = document.createDocumentFragment();
 + 
 +   var list = document.getElementById( 'list' ); //<ul id="list"></ul>
 +   var item = null;
 + 
 +   //suppose this json is returned from ajax call
 +   var ajaxResponse = [
 +       { 'name' : 'Haiku' },
 +       { 'name' : 'Linux' },
 +       { 'name' : 'OS X' },
 +       { 'name' : 'Windows' }
 +   ];
 + 
 +   //add all names in ajaxReponse to documentFragment
 +   for( var i in ajaxResponse ) {
 +       item = document.createElement( 'li' );
 +       item.appendChild( document.createTextNode( ajaxResponse[ i ].name ) );
 +       documentFragment.appendChild( item );
 +   }
 + 
 +   //append all items in documentFragment to list
 +   list.appendChild( documentFragment );
 +}
 +</code>
 +كتب John Resig مقالاً ممتازاً يشرح فيه DocumentFragment وأثره على الأداء.
 +
 +===== التلاعب بـDOM باستخدام innerHTML =====
 +
 +لا تستخدم معاملات المهام الحسابيّة ( += ) مع innerHTML لإضافة وسم. كلّ مرّة تعدّل فيها innerHTML يتمّ تحديث DOM (يسحب المتصفّح الوسم). لذا فإنّ إضافة وسم جديد باستخدام معامل += يقلّل الأداء، خاصّة إذا كان هذا ضمن حلقة.
 +<code javascript>
 +var container = document.getElementById( 'container' );
 + 
 +for( var i = 1; i <= 10; ++i ) {
 +   container.innerHTML += 'Item ' + i + '<br />';
 +}
 +</code>
 +دائماً استخدم متغيّراً مؤقّتاً لتسند إليه قيمة innerHTML كما في المثال أدناه:
 +<code javascript>
 +var container = document.getElementById( 'container' )
 + , str = '';
 + 
 +for( var i = 1; i <= 10; ++i ) {
 +   str += 'Item ' + i + '<br />';
 +}
 + 
 +container.innerHTML += str;
 +</code>
 +
  
docs/javascript-mistakes-you-must-avoid.txt · آخر تعديل: 2015/04/23 03:19 بواسطة 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki