JS ရဲ့ Reference တွေအကြောင်း

Mon May 26 2025 5 mins read


JS ရဲ့ Reference တွေအကြောင်း

JS မှာ pointer ဆိုတာမရှိပါဘူး။ ပြီးတော့ JS ရဲ့ reference သဘောတရားကလည်း တခြား language တွေနဲ့ ကွာခြားတာရှိပါတယ်။


JS မှာ variable တခုဟာ primitive ဒါမှမဟုတ် reference data type တခုခုကို သိမ်းဆည်းထားနိုင်ပါတယ်။ ဒီ data type နှစ်ခုဟာ ဘယ်လို ကွာခြားသလဲဆိုရင် memory ပေါ်မှာ သိမ်းဆည်းတဲ့ပုံစံနဲ့ manipulate လုပ်တဲ့ပုံစံတွေ ကွာခြားပါတယ်။ Number, Boolean, String စတာတွေဟာ scalar (single unit) တန်ဖိုးတွေဖြစ်ပြီး Array, Object စတာတွေဟာ compound တန်ဖိုးတွေဖြစ်ပါတယ်။ JS မှာဆိုရင် scalar တန်ဖိုးတွေဟာ primitive type တွေဖြစ်ပါတယ်။ သူတိုတွေဟာ immutable ဖြစ်ပြီး compound တန်ဖိုးတွေကတော့ mutable ဖြစ်ပါတယ်။


Primitive type တွေဆိုရင် variable ထဲမှာ တန်ဖိုးကို တိုက်ရိုက်သိမ်းဆည်းပါတယ်။ အဲဒီ variable ကို တခြားသော variable ထဲကို assign လုပ်လိုက်တာဖြစ်စေ၊ function တခုထဲကို argument အဖြစ် pass လုပ်လိုက်တာဖြစ်စေ၊ အဆိုပါ တန်ဖိုးကို copy အဖြစ်သာ ပွားပေးလိုက်ပါတယ်။ ဆိုလိုတာက variable အသစ်ပေါ်မှာ ပြောင်းလဲသမျှဟာ မူလ variable တန်ဖိုးပေါ်မှာ အကျိုးသက်ရောက်မှုရှိမှာ မဟုတ်ပါဘူး။ ဒီသဘောတရားကို assign-by-value လိုခေါ်ပါတယ်။

var batman = 7;
var superman = batman;   //assign-by-value
superman++;
console.log(batman);     //7
console.log(superman);   //8


နမူနာကုဒ်မှာဆိုရင် batman ဆိုတဲ့ variable လေးကို 7 ဆိုတဲ့ တန်ဖိုးနဲ့ initialized လုပ်ပါတယ်။ အဲဒီနောက်မှာ superman ဆိုတဲ့ variable ထဲကို batman ကို assign လုပ်ပါတယ်။ အဲဒီလို assign လုပ်လိုက်တဲ့အခါ superman ဆိုတဲ့ variable ထဲမှာ batman တန်ဖိုးကို တိုက်ရိုက်သိမ်းဆည်းသွားတာမျိုး မဟုတ်ဘဲ copy အဖြစ်ပွားလိုက်ပြီး သိမ်းဆည်းသွားတာဖြစ်ပါတယ်။ ဒါကြောင့် superman ဆိုတဲ့ တန်ဖိုးလေးကို ပြုပြင်ပြောင်းလဲလိုက်ပေမယ့် batman ရဲ့ တန်ဖိုးဟာ နဂိုအတိုင်း မပြောင်းလဲဘဲ ရှိနေနိုင်တာဖြစ်ပါတယ်။


Reference type တွေဆိုရင် variable ထဲမှာ တန်ဖိုးကို တိုက်ရိုက်မသိမ်းဆည်းဘဲ အဲဒီတန်ဖိုးတည်ရှိရာနေရာကိုသာ သိမ်းဆည်းထားပါတယ်။ အဲဒီလို variable ကို တခြားသော variable ထဲကို assign လုပ်လိုက်တာဖြစ်စေ၊ function တခုထဲကို argument အဖြစ် pass လုပ်လိုက်တာဖြစ်စေ၊ အဆိုပါ တန်ဖိုးရဲ့ မူရင်းတည်ရှိရာနေရာကိုသာ ရရှိမှာဖြစ်ပါတယ်။ ဆိုလိုတာက variable အသစ်ပေါ်မှာ ပြောင်းလဲသမျှဟာ မူလ variable တန်ဖိုးပေါ်မှာ အကျိုးသက်ရောက်မှုရှိနေမှာဖြစ်ပါတယ်။ ဒီသဘောတရားကို assign-by-reference လိုခေါ်ပါတယ်။

var flash = [8,8,8];
var quicksilver = flash;   //assign-by-reference
quicksilver.push(0);
console.log(flash);        //[8,8,8,0]
console.log(quicksilver);  //[8,8,8,0]

နမူနာကုဒ်မှာဆိုရင် compound value (array) တခုကို flash ဆိုတဲ့ variable ထဲ သိမ်းပါတယ်။ ပြီးတဲ့အခါ quicksilver ဆိုတဲ့ variable ထဲကို ထည့်လိုက်ပါတယ်။ ဒါဟာ flash နဲ့ quicksilver ဆိုတဲ့ variable နှစ်ခုကြား တူညီတဲ့ reference ကိုရရှိသွားပါတယ်။ ဆိုလိုတာက အဲဒီတန်ဖိုးရဲ့ တည်နေရာတခုတည်းကိုသာ အတူတူ လှမ်းထောက်ထားကြတာမျိုးပါ။ ဒါကြောင့် quicksilver ရဲ့ တန်ဖိုးကို ပြောင်းလဲလိုက်တဲ့အခါ flash ရဲ့တန်ဖိုးပေါ်မှာ အကျိုးသက်ရောက်မှုရှိနေတာဖြစ်ပါတယ်။


ဒီနေရာမှာ သတိထားရမှာရှိပါတယ်။ အကယ်၍သာ assign-by-reference လုပ်ထားတဲ့ variable ကို reassign လုပ်လိုက်မယ်ဆိုရင် နဂို reference ကနေ သွေဖယ်ပြီး သီးခြား reference အသစ်တခုကို ရရှိသွားမှာဖြစ်ပါတယ်။ အောက်က နမူနာကုဒ်ကိုကြည့်ပါ။

var firestorm = [3,6,3];
var atom = firestorm;   //assign-by-reference
console.log(firestorm); //[3,6,3]
console.log(atom);      //[3,6,3]
atom = [9,0,9];         //value is reassigned (create new reference)
console.log(firestorm); //[3,6,3]
console.log(atom);      //[9,0,9]


Function တွေထဲကို argument အဖြစ် pass လုပ်လိုက်တဲ့အခါမှာလည်း reference တွေဟာ အထက်ပါအတိုင်းပဲ အလုပ်လုပ်ပါတယ်။

var magneto = [8,4,8];
(function(x) {        //IIFE
    x.push(99);
    console.log(x);   //[8,4,8,99]
    x = [1,4,1];      //reassign variable (create new reference)
    x.push(88);
    console.log(x);   //[1,4,1,88]
})(magneto);
console.log(magneto); //[8,4,8,99]


အပေါ်ကကုဒ်မှာဆိုရင် IIF(Immediately Invoked Function) ထဲကို magneto ဆိုတဲ့ reference တန်ဖိုလေးကို ထည့်ပေးလိုက်ပါတယ်။ reference သဘောတရားအရ push() ကြောင့် မူလတန်ဖိုးဟာ ကနဦးအစမှာ ပြောင်းလဲသွားပါတယ်။ ဒါပေမယ့် array တန်ဖိုးအသစ်တခုကို reassign လုပ်လိုက်တဲ့အခါမှာတော့ နဂို reference ကနေ သွေဖယ်ပြီး သီးခြား reference အသစ်တခုကို ရရှိသွားပါတယ်။ ဒါကြောင့် မူလတန်ဖိုးကို မထိခိုက်တော့ဘဲ reference အသစ်ပေါ်မှာသာ အကျိုးသက်ရောက်သွားမှာဖြစ်ပါတယ်။

ဒါဆိုရင် ဒီလိုမျိုးအခြေအနေမှာ မူလတန်ဖိုးကို တန်ဖိုးအသစ်တခု ဘယ်လိုပြောင်းပေးလို့ရနိုင်မလဲ?

အဖြေကတော့ ရိုးရှင်းပါတယ်၊ မူလတန်ဖိုးကို အရင်ဆုံး empty လုပ်ပစ်ရတာပါ။ နမူနာကုဒ်ကိုကြည့်ပါ။

var wolverine = [8,7,8];
(function(x) {              //IIFE
    x.length = 0;           //make empty array object
    x.push(1,4,7,2);
    console.log(x);         //[1,4,7,2]
})(wolverine);
console.log(wolverine);     //[1,4,7,2]

ဒါဆို compound value (တနည်းအားဖြင့် reference data type)တွေကို assign-by-value ပုံစံမျိုးသိမ်းဖို့ လိုအပ်လာရင်၊ တနည်းအားဖြင့် မူလတန်ဖိုးပေါ်မှာ သွယ်ဝှိက် မထိခိုက်စေချင်ရင် ဘယ်လိုလုပ်ရမလဲ?


အကောင်းဆုံးအဖြေကတော့ မူလ compound value ကို copy ကူးယူပြီးမှသာ တခြားသော variable ထဲကို assign လုပ်လိုက်တာဖြစ်ပါတယ်။ reference type data တွေကို copy ကူးယူနိုင်တဲ့ နည်းလမ်းတွေရှိပါတယ်။ နမူနာကုဒ်ကိုကြည့်ပါ။

var cisco = [7,4,7];
var zoom = cisco.slice();  //create shallow copy
cisco.push(77,33);
console.log(zoom);         //[7,4,7]
console.log(cisco);        //[7,4,7,77,33]

Reference type data တွေကို copy ကူးယူနိုင်တဲ့ နည်းလမ်းတွေဖြစ်တဲ့ Shallow copy နဲ့ Deep Copy အကြောင်းကို ရှေ့က ဆောင်းပါးမှာ ဖော်ပြခဲ့ဖူးပါတယ်။ ဒီလင့်ခ်ကနေ တဖန်ဝင်ရောက်ဖတ်ရှုနိုင်ပါတယ်။


#webdevelopment #JavaScript #programming


0

Comments