เปลี่ยนความเคยชิน JavaScript เข้าสู่ BEST PRACTICES JavaScript

มีหลายครั้งที่เราเขียน JavaScript กันด้วยความเคยชิ้นตามที่เราเข้าใจ แต่วันนี้ผมมี Tip เล็กๆ (ไม่รู้จะเรียกว่า BEST PRACTICES ได้หรือเปล่าแต่ก็เรียกไปแล้ว)เพื่อเป็นทางเลือก ที่จะช่วยให้ Code ของเรามีประสิธิภาพที่ดีขึ้น(รีเปล่า) แต่ที่แน่ๆ คืออ่านง่ายขึ้นแน่นนอนครับผม

1 กำหนดค่าให้  Array

แบบเดิม 1385202649_MetroUI_Security_Denied

var lunch =Array();
lunch[0]='A';
lunch[1]='B';
lunch[2]='C';
lunch[3]='D';


1385202455_MetroUI_Security_Approved
แบบใหม่

var lunch = ['A','B','C','D'];

แบบนี่สั้นและสะอาดตามากกว่าแบบเก่ามากครับ

 

2 กำหนดตัวแปร

1385202649_MetroUI_Security_Denied

แบบเดิม

var Item1 = 'A';  
var Item2 = 'B';  
var Item3 = 'C';

ส่วนใหญ่เราก็ชิ้นแบบนี้กันครับ

1385202455_MetroUI_Security_Approvedแบบใหม่

var Item1 = 'A',
     Item2 = 'B',
     Item3 = 'C';

นี้ก็คล้ายกับ Programming ภาษาอื่นๆ ที่เขาก็แนะนำกัน แต่ถ้าทำตามนี้ ฝรั่งบอกว่าจะช่วยเพิ่มประสิทธิภาพมากขึ้น (แต่สำหรับผมแล้วมันอ่านง่ายขึ้น ก็ถือว่าดีแล้วผมก็พยายามทำตามนี้ครับ)

 3 if อย่างสั้น

1385202649_MetroUI_Security_Deniedแบบเดิม

if(v){
   var x = v;
} else {
   var x =99;
}

 

1385202455_MetroUI_Security_Approvedแบบใหม่

var x = v || 99;

สั้นกระชับและอ่านง่าย

 

4 Optimize Loops

Loop ใน JavaScript ค่อนข้างน่ากลัวครับเราจึงต้องระมัดระวังเป็นอย่างมากเพราะมันสามารถทำเครื่องของ User Hang ได้เลยครับ

1385202649_MetroUI_Security_Deniedแบบเดิม

var names = ['A', 'B', 'C', 'D'];

for(var i=0;i<names.length;i++){
   doSomethingWith(names[i]);
}

 

1385202455_MetroUI_Security_Approved

แบบใหม่

var names = ['A', 'B', 'C', 'D'];

for(var i=0,j=names.length;i<j;i++){
   doSomethingWith(names[i]);
}

แบบนี้เป็นการลดการเข้าถึง length หลายๆ คร้ังครับถ้า loop น้อยคงไม่แตกต่างถ้ามากก็จะเห็นผลที่แตกต่างได้ชัดเจนครับ

5 ยกเลิกการใช้  language=”javascript”

ในสมัยก่อนเราถูกสอนให้ใส่  language=”javascript” มาโดยตลอดแต่พอหลายปีผ่านมาเราก็ยังใส่มันด้วยความเคยชิ้น ทั้งที่ JavaScript ได้ยกเลิกมันออกไปแล้ว

1385202649_MetroUI_Security_Deniedแบบเดิม

<script type="text/javascript" language="javascript">  

</script>

 

1385202455_MetroUI_Security_Approvedแบบใหม่

<script type="text/javascript">  

</script>

ไม่ต้องใส่มานะครับ

6 array To String ใช้ Join

ถ้าเราต้องการนำค่า  array มาใส่มาต่อ String  ไม่ต้องวนลูปนะครับใช้

1385202649_MetroUI_Security_Deniedแบบเดิม

function ArrayToString()
{
var fruits = ["Banana", "Orange", "Apple", "Mango"];

var fruitsString='';
for (var f in fruits)
{
fruitsString += fruits[f] +'|';
}

}

//ผลที่ได้ Banana|Orange|Apple|Mango|

1385202455_MetroUI_Security_Approvedแบบใหม่

function myFunction()
{
var fruits = ["Banana", "Orange", "Apple", "Mango"];
 fruitsString=fruits.join('|');
}
//ผลที่ได้ Banana|Orange|Apple|Mango|

แบบใหม่เขียนง่ายอ่านง่ายและประสิทธิภาพก็ดีกว่าอีกด้วยครับ

7 หลีกเลี่ยง Global Variable

Variable ในที่นี้รวม function ด้วยนะครับ

1385202649_MetroUI_Security_Deniedแบบเดิม

var current = null;
var labels = {
   'home':'home',
   'articles':'articles',
   'contact':'contact'	
};
function init(){
};
function show(){
   current = 1;
};
function hide(){
   show();
};

1385202455_MetroUI_Security_Approvedแบบใหม่

module = function(){
   var current = null;
   var labels = {
      'home':'home',
      'articles':'articles',
      'contact':'contact'
   };
   var init = function(){
   };
   var show = function(){
      current = 1;
   };
   var hide = function(){
      show();
   }
   return{init:init, show:show, current:current}
}();
module.init();

ถ้าหากว่าเราไม่ได้ต้องการ Share Valiable  ร่วมกันเราไม่ครวประกาศค่าเป็น Global  ด้วยสองเหตุผลคือ

1 ถ้าค่าเราไม่ถูก Scope ไว้อาจถูกเปลี่ยนแปลงค่าโดยบังเอิญตอนไหนก็ได้ อันเป็นสาเหตุของข้อผิดพลาด ซึ่งตรวจหาค่อนข้างยาก

2 เป็นเรื่องของการบริหารจัดการ Memory เพราะ Global Scope จะถูกทำลายก็ต่อเมื่อปิด Browser

 8 ไม่ครวรวม Technology ถึงแม้ว่าทำได้

แม้ว่า JavaScript จะเก่งเรื่องการแปลี่ยนแปลงอินเตอร์เฟซ และการจัดการเหตุการณ์ ของ  Html แต่ไม่ควรทำอย่างด้านล่าง
1385202649_MetroUI_Security_Deniedแบบเดิม

var f = document.getElementById('form1');
var inputs = f.getElementsByTagName('input');

for(var i=0,j=inputs.length;i<j;i++){
   if( inputs.value === ''){
      inputs[i].style.borderColor = '#f00';  //
      inputs[i].style.borderStyle = 'solid';  //
      inputs[i].style.borderWidth = '1px';    
   }
}

1385202455_MetroUI_Security_Approvedแบบใหม่

var f = document.getElementById('form1');
var inputs = f.getElementsByTagName('input');

for(var i=0,j=inputs.length;i<j;i++){
   if(  inputs.value === ''){
      inputs[i].className+=' error';
   }
}

หรือพูดง่ายว่าเรามี  CSS (Cascading Style Sheets) เป็นภาคแสดงผลอยู่แล้วเราครวใช้   CSS (Cascading Style Sheets)   ยกตัวอย่างเช่นหากผ่านไปหลายเดือนเราต้องการเปลี่ยนแปลง  look and feel  ของ Validation จากด้านบนเราก็จะไม่ต้องแก้ Code JavaScript เราครวแก้   CSS (Cascading Style Sheets)เท่านั่น  (ข้อนี้ก็เข้าใจแหละแต่มันทำได้อยาก T_T เวลาเขียนอารมณ์มันพาไป)

9 ไม่ครวย่อ IF  ถึงแม้จะสามารถทำได้

เพราะการย่อเมื่อเวลาผ่านไปเวลานาน มันจะทำให้เราไม่มันใจว่าอันไหนเป็นสิ่งที่ถูกหรือผิด

1385202649_MetroUI_Security_Deniedแบบเดิม

if(DoSomething)  
   x = false; 
AddSomething()

 

1385202455_MetroUI_Security_Approvedแบบใหม่

if(DoSomething)  
  { x = false; }  
AddSomething()

 

10 ควรกำหนดตัวแปลไว้นอก Loop (โดยเฉพาะตัวแปรที่เกี่ยวดับ DOM)

1385202649_MetroUI_Security_Denied

แบบเดิม

for(var i = 0; i < someArray.length; i++) {  
   var spanA= document.getElementById('spanA');  
   spanA.innerHtml += 'my number: ' + i;  
}

 

1385202455_MetroUI_Security_Approved แบบใหม่

var spanA= document.getElementById('spanA');  

for(var i = 0; i < someArray.length; i++) {  
   spanA.innerHtml += 'my number: ' + i;  
}

แบบนี้ลดการ Loop Dom ไปได้ตั้งเยอะแต่ (แบบผิดไม่น่าจะมีคนทำหลอกมังแบบนี้ผมว่านะ)

 12 อย่าใช้ With Statement

คำสั่ง With นั้นให้มาเกือบทุกภาษา แต่ทุก BEST PRACTICES ของแต่ละภาษาก็บอกว่าอย่าไปใช้มันแล้วมันไม่ดียังไงละ เราลองมาดูกันครับ

1385202649_MetroUI_Security_Denied

แบบเดิม

MegaModule.BigModule.MidModule.SmallModule.MicroModule.NanoModule.Run= True; 
MegaModule.BigModule.MidModule.SmallModule.MicroModule.NanoModule.Visible = True;

ใช้ With Statement

with (MegaModule.BigModule.MidModule.SmallModule.MicroModule.NanoModule) {
   Run= True; 
   Visible = True; 
}

ดูแล้วก็ไม่น่าจะมีอะไร แต่ปัญหามันอยู่ตรงที่หาก Code มีตัวแปล ที่ชื่อเดียวกัน คือ Run และ Visible  ที่ถูกประกาศเป็นแบบ Global เราเองจะไม่สามารถ Set ค่าหรืออ่านค่า Run และ Visible ของ Global ได้เพราะมันอยู่ใน Scope With ปัญหานี้ที่ฝรั่งชอบใช้คำว่า ambiguity(ความกำกวม ถ้าเพื่อนที่เคยเขียน Sql มาบ้างแล้วนะจะเจอคำนี้บ้างนะครับผมว่า)
ตัวอย่าง Case ที่เป็นปัญหา 

var Run= 'Y'; 
var Visible = 'Y'; 
with (MegaModule.BigModule.MidModule.SmallModule.MicroModule.NanoModule) {
   Run= True; 
  Visible = True; 
}

1385202455_MetroUI_Security_Approved

แบบใหม่

ซึ่งผมมีทางเลือกที่ดีกว่าครับ (ผมเองก็กำลังฝึกเพื่อที่จะเปลี่ยนตัวเองจากความเคยชิ้นเก่าๆของผมตามข้อนี้เหมือนกันครับ  ^_^)

var Module= MegaModule.BigModule.MidModule.SmallModule.MicroModule.NanoModule;
Module.Run = true;
Module.Visible = true;

จากตัวอย่าง Code ด้านบนเท่านี้เราก็ไม่มีปัญกา ambiguity อีกต่อไปเลยครับ

 

…. ยังมีต่ออีกหลายข้อแล้วผมจะ Update ให้อีกนะครับ

 สุดท้ายถ้าเราไม่แน่ใจว่า Code ที่เราทำไปถูกต้องหรือไม่ก็ให้นำ Code ลองไปทดสอบที่ JSLint แล้วแก้ไขตามดูแล้วจะพบสิ่งที่เราไม่เคยรู้มาก่อนอีกมากเลยครับ

 

หวังว่าคงมีประโยชน์บ้างนะครับ

Leave a Reply