JavaScript ရဲ့ အခြေခံကနေ Advanced concepts တွေအထိ စနစ်တကျ လေ့လာထားတဲ့ Practice Repository ဖြစ်ပါတယ်။
- JavaScript Execution Model - Js Engine - Web APIs - Event Loop - Callback Queue
- LexicalStructure
- Expressions
- DataTypes
- Variables
- Operators
- Conditions
- Loops
- Functions
- Objects
- Arrays
- Asynchronous
- TypeCasting
- Modules
- ErrorHandling
- OOP
- JSON
- FetchAPI
- ES6+(Modern JavaScript)
- Hoisting
- Scope
- Scope Chain
- Lexical Scoping
- Closure
JavaScript Engine ဆိုတာ JavaScript code တွေကို Machine Code (သို့) Bytecode အဖြစ် ပြောင်းပြီး execute လုပ်ပေးတဲ့ software program တစ်ခုဖြစ်ပါတယ်။
-
Google Chrome, Edge → V8 Engine
-
Firefox → SpiderMonkey
-
Safari → JavaScriptCore (Nitro)
-
Node.js → V8 Engine ကိုပဲသုံးတယ်
-
- Memory Heap
-
- Call Stack
JavaScript Engine ထဲက Memory Heap ဆိုတာ variable တွေ၊ objects တွေနဲ့
data တွေကို သိမ်းဆည်းထားတဲ့ "ဂိုဒေါင်" တစ်ခုလိုပါပဲ။
Memory Heap ရဲ့ အဓိက အချက်များ
၁။ Unstructured Memory (ပုံသေ သတ်မှတ်မထားသော နေရာ)
Call Stack လိုမျိုး အစီအစဉ်တကျ (LIFO) သိမ်းတာမျိုး မဟုတ်ဘဲ၊
Heap ကတော့ ကြီးမားတဲ့ memory ဧရိယာကြီးတစ်ခုပါ။ ပုံထဲမှာလည်း data တွေကို
နေရာအနှံ့ ကြဲပြန့်ပြီး သိမ်းထားတာကို တွေ့နိုင်ပါတယ်။
၂။ ဘာတွေကို သိမ်းသလဲ?
Objects & Arrays: JavaScript မှာရှိတဲ့ reference types တွေ
(ဥပမာ- {name: "Mg Mg"}, [1, 2, 3]) ကို ဒီမှာ သိမ်းပါတယ်။
Functions: Function definition တွေကိုလည်း memory heap ထဲမှာပဲ သိမ်းဆည်းပါတယ်။
Large Data: Stack ထဲမှာ သိမ်းဖို့ အရွယ်အစား ကြီးမားလွန်းတဲ့ data တွေကို
ဒီနေရာမှာ နေရာချ (Allocate) ပေးပါတယ်။
၃။ Allocation vs Garbage Collection
Memory Allocation: Variable အသစ်တစ်ခု ဆောက်လိုက်တိုင်း Engine က Heap ထဲမှာ
နေရာအလွတ်တစ်ခု ရှာပြီး သိမ်းပေးပါတယ်။
Garbage Collection: JavaScript မှာ Memory ကို ကိုယ်တိုင် ဖျက်ပေးစရာ မလိုပါဘူး။
Engine ထဲမှာ Garbage Collector ဆိုတာ ပါပါတယ်။
သူက Heap ထဲကို အမြဲစစ်ဆေးပြီး ဘယ် variable ကိုမှ အသုံးမပြုတော့ဘူး
(Reference မရှိတော့ဘူး) ဆိုရင် အဲဒီ memory ကို အလိုအလျောက် ပြန်သိမ်းသွားပါတယ်။
Call Stack နဲ့ ဘယ်လို ချိတ်ဆက်သလဲ?
ဒီအချက်က အရေးကြီးပါတယ်။
Object တစ်ခုကို Heap ထဲမှာ သိမ်းလိုက်တဲ့အခါ သူ့ရဲ့
Memory Address (Reference) လေးတစ်ခု ရလာပါတယ်။
အဲဒီ Address လေးကိုမှ Call Stack ထဲမှာရှိတဲ့ variable ထဲကို ထည့်သိမ်းလိုက်တာပါ။
ဥပမာ: const user = { name: "Aung Aung" }; လို့ ရေးရင်:
{ name: "Aung Aung" } ဆိုတဲ့ object ကြီးက Heap ထဲ ရောက်သွားမယ်။
user ဆိုတဲ့ variable နာမည်နဲ့ အဲဒီ data ရှိရာနေရာကို ညွှန်ပြတဲ့ Memory Address (Reference)လေးကတော့ Call Stack ထဲမှာ ရှိနေပါမယ်။
Memory Heap ထဲမှာ data တွေ အရမ်းများလာပြီး Garbage Collector ကလည်း
မဖျက်ပေးနိုင်တဲ့အခါ Memory Leak (စက်လေးသွားတာမျိုး) ဖြစ်တတ်ပါတယ်။
Call Stack ဆိုတာ JavaScript Engine က လက်ရှိ ဘယ် function တွေကို လုပ်ဆောင်နေသလဲ၊
ဘယ် function ထဲမှာ ရောက်နေသလဲဆိုတာကို ခြေရာခံတဲ့ ယန္တရားတစ်ခု ဖြစ်ပါတယ်။
သူ့ကို ရိုးရိုးရှင်းရှင်း ပြောရရင် "အလုပ်စာရင်းမှတ်တဲ့ စာအုပ်" လိုမျိုးဖြစ်ပြီး
အောက်ပါ အချက်တွေက သူ့ရဲ့ အဓိက သဘောတရားတွေပါပဲ-
၁။ LIFO (Last In, First Out)
Call Stack ဟာ LIFO စနစ်နဲ့ အလုပ်လုပ်ပါတယ်။
ပန်းကန်ပြားတွေကို တစ်ချပ်ပေါ်တစ်ချပ် ဆင့်တင်ထားသလိုမျိုးပါပဲ။
Push: Function တစ်ခုကို ခေါ်လိုက်တဲ့အခါ Stack ရဲ့ အပေါ်ဆုံးကို ရောက်လာပါတယ်။
Pop: Function ထဲက အလုပ်တွေ ပြီးသွားတဲ့အခါ (Return ပြန်တဲ့အခါ) အပေါ်ဆုံးကနေ ပြန်ထွက်သွားပါတယ်။
၂။ Single Call Stack
JavaScript က Single-threaded ဖြစ်တဲ့အတွက် Call Stack တစ်ခုပဲ ရှိပါတယ်။
ဒါကြောင့် သူက တစ်ကြိမ်မှာ အလုပ်တစ်ခုတည်းကိုပဲ အာရုံစိုက်လုပ်နိုင်ပါတယ်။
အပေါ်က function မပြီးမချင်း အောက်က function ဆီကို မသွားပါဘူး။
၃။ အလုပ်လုပ်ပုံ ဥပမာ
function greet() {
sayHi();
console.log("Greet done");
}
function sayHi() {
console.log("Hi!");
}
greet();
greet() ကို ခေါ်လိုက်ရင် Stack ထဲကို greet ရောက်လာပါတယ်။
greet ထဲမှာမှ sayHi() ကို ထပ်ခေါ်တဲ့အတွက် Stack ရဲ့ အပေါ်ဆုံးကို sayHi ထပ်ရောက်လာပါတယ်။
sayHi အလုပ်ပြီးသွားတဲ့အခါ Stack ထဲကနေ sayHi ထွက်သွားပါတယ်။
နောက်ဆုံးမှာ greet အလုပ်ပြီးလို့ Stack ထဲကနေ greet ထွက်သွားပြီး Stack က ပြန်လွတ် (Empty) သွားပါတယ်။
၄။ Stack Overflow (Error)
Function တစ်ခုကနေ နောက်ထပ် function တစ်ခုကို အဆုံးမရှိ (Infinite) ခေါ်နေမယ်ဆိုရင်
Stack ထဲမှာ နေရာမဆန့်တော့ဘဲ ပြည့်လျှံသွားတတ်ပါတယ်။ ဒါကို Stack Overflow လို့ ခေါ်ပါတယ်။
Call Stack နဲ့ Event Loop
ပုံထဲမှာ မြင်ရတဲ့အတိုင်း Call Stack ထဲက အလုပ်တွေ အကုန်လုံး ပြီးသွားမှသာ
Event Loop က Callback Queue ထဲမှာ စောင့်နေတဲ့ အလုပ်တွေကို Stack ထဲကို ပို့ပေးတာ ဖြစ်ပါတယ်။
Web APIs ဆိုတာ Browser (Web Runtime Environment) ကနေ ထောက်ပံ့ပေးထားတဲ့
အပိုထည့်ပေးထားတဲ့ Features ဖြစ်ပါတယ်။
JavaScript က single-threaded ဖြစ်ပေမဲ့ နောက်ကွယ်မှာ အလုပ်တွေအများကြီးကို တစ်ပြိုင်နက်
လုပ်ဆောင်နိုင်နေတာဟာ ဒီ Web APIs တွေကြောင့် ဖြစ်ပါတယ်။
Web APIs ရဲ့ အဓိက တာဝန်များ
ပုံထဲမှာ ပြထားတဲ့အတိုင်း Web APIs တွေဟာ Engine ရဲ့ အပြင်ဘက်မှာ သီးသန့် အလုပ်လုပ်ကြတာပါ။
DOM (Document Object Model): JavaScript ကနေ HTML element တွေကို ရှာတာ၊ အရောင်ပြောင်းတာ၊
စာသားအသစ် ထည့်တာတွေကို လုပ်ဆောင်ပေးပါတယ်။
Timer (setTimeout/setInterval): သတ်မှတ်ထားတဲ့ အချိန်တစ်ခုအထိ စောင့်ဆိုင်းပေးတဲ့ အလုပ်ကို
လုပ်ဆောင်ပေးပါတယ်။
Fetch APIs (Network Requests): Server ဆီကနေ data တွေ လှမ်းတောင်းတဲ့အခါ Browser ရဲ့
Network thread ကို သုံးပြီး အလုပ်လုပ်ပေးပါတယ်။
Other APIs: ပုံထဲမှာ ... လို့ ပြထားတဲ့အထဲမှာ Geolocation (တည်နေရာကြည့်ခြင်း)၊
Local Storage နဲ့ Canvas လိုမျိုး APIs တွေလည်း ပါဝင်ပါတယ်။
Web APIs က ဘယ်လို အလုပ်လုပ်သလဲ?
၁။ Request: Call Stack ကနေ setTimeout ဒါမှမဟုတ် fetch လိုမျိုး function ကို ခေါ်လိုက်တဲ့အခါ
JS Engine က အဲဒီအလုပ်ကို Web APIs ဆီကို လွှဲပေးလိုက်ပါတယ်။
၂။ Offloading: Web APIs က အဲဒီအလုပ်ကို Browser ရဲ့ အခြား thread တွေ (ဥပမာ Network thread
သို့မဟုတ် Timer thread) ကို သုံးပြီး နောက်ကွယ်မှာ သီးသန့် လုပ်ဆောင်ပါတယ်။
၃။ Callback: အလုပ်ပြီးသွားတဲ့အခါ (ဥပမာ Timer ပြည့်သွားတဲ့အခါ) Web API က အဲဒီအလုပ်နဲ့ သက်ဆိုင်တဲ့
Callback function ကို Callback Queue ထဲကို ပို့ပေးလိုက်ပါတယ်။
ဘာကြောင့် အရေးကြီးတာလဲ?
Web APIs မရှိဘူးဆိုရင် JavaScript ဟာ အရမ်း "နှေး" တဲ့ ဘာသာစကား ဖြစ်သွားပါလိမ့်မယ်။
ဥပမာ- Server ကနေ data လာတာကို စောင့်နေတဲ့အချိန်မှာ Web API မရှိရင် Browser ကြီး တစ်ခုလုံး
ဘာမှလုပ်လို့မရဘဲ "Hang" နေမှာပါ။
အခုတော့ Web APIs က နောက်ကွယ်မှာ အလုပ်လုပ်ပေးနေလို့ ကျနော်တို့ Browser မှာ UI တွေကို ဆက်ပြီး
အသုံးပြုနိုင်နေတာ ဖြစ်ပါတယ်။
Event Loop ဆိုတာ JavaScript Runtime ရဲ့ "စပယ်ယာ" သို့မဟုတ် "ယာဉ်ထိန်းရဲ" လိုမျိုး အဓိကကျတဲ့
အစိတ်အပိုင်းဖြစ်ပါတယ်။ သူက Call Stack နဲ့ Callback Queue တို့ကြားမှာ အလုပ်တွေကို ဘယ်အချိန်မှာ
လုပ်ဆောင်ရမလဲဆိုတာကို အမြဲတမ်း စီစဉ်ပေးနေတာပါ။
ပုံထဲက မြှားလေးကို ကြည့်ရင် Event Loop က အလုပ်တွေ လှည့်ပတ်နေပုံကို မြင်နိုင်ပါတယ်။
Event Loop ရဲ့ အလုပ်လုပ်ပုံ အဆင့်ဆင့်
Event Loop က အောက်ပါ အဆင့် ၃ ဆင့်ကို အမြဲတမ်း ထပ်ခါတလဲလဲ (Loop) ပတ်ပြီး လုပ်ဆောင်နေပါတယ်-
၁။ Call Stack ကို စစ်ဆေးခြင်း
Event Loop က Call Stack ထဲမှာ လက်ရှိ လုပ်နေတဲ့ code တွေ ရှိသေးလားဆိုတာကို အရင်ကြည့်ပါတယ်။
အကယ်၍ Stack ထဲမှာ function တစ်ခုခု အလုပ်လုပ်နေတုန်းဆိုရင် သူက ဘာမှ ထပ်မလုပ်ဘဲ စောင့်နေပါတယ်။
၂။ Callback Queue ကို ကြည့်ခြင်း
Call Stack ထဲမှာ ဘာအလုပ်မှ မရှိတော့ဘူး (လွတ်သွားပြီ) ဆိုတာနဲ့ Event Loop က Callback Queue ဘက်ကို
လှည့်ကြည့်ပါတယ်။ Queue ထဲမှာ Web APIs ဆီကနေ ပြီးစီးလို့ ရောက်လာတဲ့ callback အလုပ်တွေ
(ဥပမာ- click, timer, data) ရှိနေသလားလို့ စစ်ပါတယ်။
၃။ အလုပ်ကို လွှဲပြောင်းပေးခြင်း (The Push)
Queue ထဲမှာ အလုပ်ရှိနေရင် Event Loop က အဲဒီထဲက ပထမဆုံးအလုပ်ကို ယူပြီး Call Stack ထဲကို
တွန်းတင် (Push) ပေးလိုက်ပါတယ်။ အဲဒီအခါမှသာ အဲဒီ callback function က တကယ် အလုပ်လုပ်တာဖြစ်ပါတယ်။
ဘာကြောင့် Event Loop က အရေးကြီးတာလဲ?
JavaScript က Single-threaded ဖြစ်ပေမဲ့ "မထစ်" ဘဲ အလုပ်လုပ်နိုင်တာဟာ ဒီ Event Loop ကြောင့်ပါ။
Non-blocking: setTimeout သို့မဟုတ် fetch လိုမျိုး ကြာမယ့်အလုပ်တွေကို Web APIs ဆီ လွှဲပေးထားနိုင်လို့ UI က
ပုံမှန်အတိုင်း အလုပ်လုပ်နေနိုင်တာပါ။
Concurrency: အလုပ်တွေကို တစ်ပြိုင်နက် လုပ်နေသလိုမျိုး ခံစားရစေပါတယ်။ တကယ်တော့ နောက်ကွယ်မှာ
Web APIs တွေက အလုပ်လုပ်ပေးနေပြီး Event Loop က အဖြေတွေကို အစီအစဉ်တကျ ပြန်စီပေးနေတာ ဖြစ်ပါတယ်။
Callback Queue (သို့မဟုတ် Task Queue) ဆိုတာ Web APIs တွေဆီကနေ အလုပ်ပြီးစီးလို့
ပြန်လာတဲ့ function လေးတွေ Call Stack ထဲကို ပြန်ဝင်ဖို့အတွက် စောင့်ဆိုင်းရတဲ့ "တန်းစီဇယား" နေရာဖြစ်ပါတယ်။
ပုံထဲက JS Runtime Environment ရဲ့ ညာဘက်အောက်ခြေမှာ click, timer, data စတဲ့
အလုပ်လေးတွေ တန်းစီနေတဲ့ နေရာပဲ ဖြစ်ပါတယ်။
၁။ Callback Queue ထဲကို ဘယ်လိုရောက်လာသလဲ?
အလုပ်တစ်ခုက Callback Queue ထဲကို တိုက်ရိုက်မရောက်ပါဘူး။ အဆင့်ဆင့် ဖြတ်သန်းရပါတယ်:
Web APIs ကနေ တဆင့်လာခြင်း: ဥပမာ- setTimeout ရဲ့ timer ပြည့်သွားတဲ့အခါ သို့မဟုတ် fetch ကနေ
data ရလာတဲ့အခါ အဲဒီအလုပ်နဲ့ သက်ဆိုင်တဲ့ callback function ကို Web API က Queue ထဲကို ပို့ပေးလိုက်တာပါ။
Events များ: User က ခလုတ်တစ်ခုကို နှိပ်လိုက်ရင် (click) အဲဒီ click event အတွက် ရေးထားတဲ့ function က
Queue ထဲမှာ လာပြီး တန်းစီပါတယ်။
၂။ FIFO (First In, First Out) စနစ်
Callback Queue ဟာ FIFO စနစ်နဲ့ အလုပ်လုပ်ပါတယ်။ မှတ်တိုင်မှာ လူတွေ တန်းစီသလိုမျိုး
အရင်ရောက်တဲ့ အလုပ်က အရင်ဆုံး ပြန်ထွက်ခွင့် ရပါတယ်။ Call Stack ရဲ့ LIFO စနစ်နဲ့ ဆန့်ကျင်ဘက်ပါ။
၃။ Event Loop နဲ့ ချိတ်ဆက်ပုံ
Callback Queue ထဲမှာ အလုပ်တွေ ဘယ်လောက်ပဲ ရှိနေပါစေ၊ သူတို့က Call Stack ထဲကို တန်းပြီး ဝင်လို့မရပါဘူး။
Event Loop က Call Stack ကို အမြဲကြည့်နေပြီး Stack လုံးဝ အားသွားပြီဆိုမှ Queue ထဲက အလုပ်တွေကို
တစ်ခုချင်းစီ Stack ထဲကို ပို့ပေးတာဖြစ်ပါတယ်။
Callback Queue အမျိုးအစားများ (The Priority)
တကယ်တော့ Browser ထဲမှာ Queue က တစ်ခုတည်း မဟုတ်ပါဘူး။ ဦးစားပေးအဆင့် (Priority) ကွာခြားမှု ရှိပါတယ်:
Microtask Queue (Promises): Promise.then() ဒါမှမဟုတ် async/await တွေအတွက်ပါ။ သူက ဦးစားပေး အမြင့်ဆုံးပါ။
Callback Queue (Macrotask): setTimeout, setInterval နဲ့ DOM events တွေအတွက်ပါ။
ဥပမာ: Timer အလုပ်နဲ့ Promise အလုပ် နှစ်ခုစလုံး Queue ထဲမှာ တန်းစီနေရင် Event Loop က Promise အလုပ်
(Microtask) ကို အရင်ယူပြီးမှ Timer အလုပ်ကို လုပ်ဆောင်ပေးမှာ ဖြစ်ပါတယ်။
JavaScript's lexical structure describes the basic building blocks of the language — the rules for writing code, forming tokens, naming variables, writing comments, and more. This document explains each part clearly.
JavaScript ရဲ့ Lexical Structure ဆိုတာ အခြေခံကျတဲ့ စည်းမျဉ်းတွေ (Grammar Rules) ဖြစ်ပါတယ်။ Programming language တစ်ခုမှာ စာလုံးတွေကို ဘယ်လိုပေါင်းရမယ်၊
ဘယ်လိုရေးရမယ်ဆိုတဲ့ အခြေခံ "သဒ္ဒါ" လို့ ပြောလို့ရပါတယ်။
၁။ Case Sensitivity (အကြီးအသေး ခွဲခြားခြင်း)
JavaScript ဟာ Case-sensitive ဖြစ်ပါတယ်။ ဆိုလိုတာက စာလုံးအကြီးအသေး ကွာခြားရင် အဓိပ္ပာယ် မတူတော့ပါဘူး။
let name = "Aung Aung";
let Name = "Su Su";
let NAME = "Kyaw Kyaw";
// ဒီသုံးခုလုံးဟာ variable သီးခြားစီ ဖြစ်ပါတယ်။
၂။ Whitespace and Line Breaks
JavaScript မှာ ကွက်လပ် (Space) တွေနဲ့ စာကြောင်းဆင်းတာ (Line break) တွေကို များသောအားဖြင့် လျစ်လျူရှုပါတယ်။ ဒါကြောင့် ကုဒ်တွေကို ဖတ်ရလွယ်အောင် စီရေးလို့ရပါတယ်။
// အတူတူပါပဲ
let x=5;
let x = 5;
၃။ Literals (တိုက်ရိုက်တန်ဖိုးများ)
Literals ဆိုတာ ကုဒ်ထဲမှာ တိုက်ရိုက်ရေးသားလိုက်တဲ့ data တန်ဖိုးတွေ ဖြစ်ပါတယ်။
123 (Number literal)
"Hello" (String literal)
true (Boolean literal)
{a: 1} (Object literal)
၄။ Identifiers (အမည်ပေးခြင်း စည်းမျဉ်း)
Variables တွေ၊ Functions တွေကို နာမည်ပေးတဲ့အခါ လိုက်နာရမယ့် စည်းမျဉ်းတွေပါ။
အစစာလုံးကို အက္ခရာ (letter)၊ underscore (_) ဒါမှမဟုတ် dollar sign ($) နဲ့ စရပါမယ်။
ကိန်းဂဏန်း (0-9) နဲ့ စလို့ မရပါ။
Reserved Keywords (ဥပမာ- if, while, return) တွေကို သုံးလို့မရပါ။
၆။ Semicolons (;)
JavaScript မှာ statement တစ်ခုပြီးတိုင်း semicolon ထည့်လေ့ရှိပါတယ်။ အခုခေတ်မှာ JavaScript က အလိုအလျောက် ထည့်ပေးတဲ့စနစ် (Automatic Semicolon Insertion)
ပါဝင်ပေမဲ့ အမှားနည်းအောင် ကိုယ်တိုင်ထည့်တာက အကောင်းဆုံး အလေ့အကျင့်ပါ။
၇။ Unicode
JavaScript ကုဒ်တွေကို Unicode character set နဲ့ ရေးသားထားတာဖြစ်လို့ variable name တွေမှာ မြန်မာစာအပါအဝင် ဘာသာစကားအမျိုးမျိုးကို သုံးလို့ရပါတယ်။
let နာမည် = "မောင်မောင်";
console.log(နာမည်); // Output: မောင်မောင်
Lexical structure defines how JavaScript source code is read and broken into tokens. It includes:
- Character set
- Case sensitivity
- Whitespace
- Line terminators
- Comments
- Literals
- Identifiers & keywords
- Operators & punctuators
JavaScript uses the Unicode character set.
- This means it supports characters from almost all languages.
- Variable names can include Unicode letters — even emojis (not recommended in production).
let မြန်မာ = "Hello";
let 🚀 = 10;JavaScript is case-sensitive.
let name = "A";
let Name = "B"; // different variableKeywords are also case-sensitive.
Whitespace includes spaces, tabs, and newlines.
- JavaScript generally ignores whitespace, except in specific cases.
Example:
let x = 10;
let y = 20;Both are valid.
Line terminators are characters such as:
\n(newline)\r(carriage return)
They can affect automatic semicolon insertion (ASI), so be careful.
Example (dangerous):
return
5; // returns undefined due to ASI// This is a comment/*
This is a multi-line comment
*/Note: Comments do not nest.
Identifiers are names for:
- variables
- functions
- classes
Rules:
- Must start with: letter,
_,$ - After first char: digits are allowed.
Valid:
let _value;
let $item;
let user123;Invalid:
let 1user; // cannot start with digitThese words have special meaning and cannot be used as identifiers. Examples:
break, case, class, const, continue, debugger, default,
delete, do, else, export, extends, finally, for, function,
if, import, in, instanceof, let, new, return, super,
switch, this, throw, try, typeof, var, void, while, with, yield
Literals are fixed values appearing directly in code.
let a = 10;
let b = 3.14;
let hex = 0xFF;
let binary = 0b1010;let s1 = "hello";
let s2 = 'world';
let s3 = `template literal`;true, falsenull;
undefined;These include:
+ - * / %= += -= *=== === != !=={ } [ ] ( ), ; . ? :
JavaScript treats these as tokens during lexical scanning.
JavaScript automatically inserts semicolons in some cases. This can cause unexpected behavior.
Bad:
let x = 5
let y = 10
(x + y).toString() // treated as function callRecommended:
- Always use semicolons or
- Follow JS formatting rules carefully.
Used inside strings:
\n→ newline\t→ tab\"→ double-quote\\→ backslash
Example:
let text = "Hello\nWorld";Identifiers may include Unicode escapes:
let \u006Eame = "John"; // same as "name"String Unicode:
"\u{1F600}"; // 😀JavaScript lexical structure defines how source code is read, including:
- Unicode support
- Case sensitivity
- Whitespace handling
- Comments
- Identifiers & keywords
- Literals
- Operators & punctuation
- ASI behavior
Understanding these rules helps you write cleaner and more predictable JavaScript.
JavaScript expressions are pieces of code that produce a value. They are the building blocks of statements and logic in JavaScript.
JavaScript မှာ Expression ဆိုတာ တန်ဖိုးတစ်ခု (Value) ထွက်လာအောင် လုပ်ပေးတဲ့ Code အစိတ်အပိုင်းလေးတွေကို ခေါ်တာပါ။ လွယ်လွယ်ပြောရရင် တွက်ချက်မှုတစ်ခု လုပ်လိုက်လို့ဖြစ်စေ၊ ခေါ်ယူလိုက်လို့ဖြစ်စေ အဖြေတစ်ခုခု ထွက်လာရင် အဲဒါ Expression ပါပဲ။
JavaScript မှာ Expression ဆိုတာ တန်ဖိုးတစ်ခုခု (Value) ထွက်လာအောင် တွက်ချက်ပေးတဲ့ Code အပိုင်းအစကို ခေါ်တာပါ။
အရိုးရှင်းဆုံး မှတ်သားချင်ရင် - "တစ်ခုခုကို တွက်ချက်ပြီး အဖြေ (Value) တစ်ခု ပြန်ပေးရင် အဲဒါ Expression ပဲ" လို့ မှတ်နိုင်ပါတယ်။
၁။ Expression အမျိုးအစားများ
JavaScript မှာ Expression အမျိုးအစား အများကြီးရှိပါတယ်။
Arithmetic Expressions: ကိန်းဂဏန်း တွက်ချက်မှုများ။
5 + 5 (အဖြေ 10 ထွက်သည်)
10 * 2 (အဖြေ 20 ထွက်သည်)
String Expressions: စာသားများ ပေါင်းစပ်ခြင်း။
"Hello " + "World" (အဖြေ "Hello World" ထွက်သည်)
Logical Expressions: ဟုတ်/မဟုတ် စစ်ဆေးခြင်း။
10 > 5 (အဖြေ true ထွက်သည်)
Primary Expressions: အခြေခံ တန်ဖိုးများ။
true, 22, "Mg Mg" (၎င်းတို့ကိုယ်တိုင်သည်လည်း expression များ ဖြစ်သည်)
၂။ Expression vs Statement (အရေးကြီးသော ကွာခြားချက်)
Programming မှာ Expression နဲ့ Statement ကို မှားတတ်ကြပါတယ်။
Expression: တန်ဖိုးတစ်ခုကို ပြန်ပေးတယ်။ ဥပမာ- 2 + 2
Statement: အလုပ်တစ်ခုကို လုပ်ဆောင်တယ်။ ဥပမာ- let x = 10; (ဒါက variable ကြေညာတဲ့ statement ဖြစ်ပြီး ဘာတန်ဖိုးမှ ပြန်မပေးပါဘူး)
၃။ React မှာ Expression ကို ဘယ်လိုသုံးသလဲ?
React (JSX) ရေးတဲ့အခါ JavaScript Expression တွေကို Curly Braces { } ထဲမှာ ထည့်ရေးရပါတယ်။
function Welcome() {
const name = "Aung Aung";
return (
<div>
{/* ဤသည်မှာ Expression ဖြစ်သည် */}
<h1>မင်္ဂလာပါ {name}</h1>
{/* ဤသည်မှာလည်း Expression ဖြစ်သည် */}
<p>၅ ပေါင်း ၅ သည် {5 + 5} ဖြစ်သည်။</p>
</div>
);
}
၄။ Ternary Operator (Expression အဖြစ်သုံးသော If-Else)
React မှာ if-else statement ကို JSX ထဲမှာ ရေးလို့မရပါဘူး (ဘာလို့လဲဆိုတော့ သူက statement ဖြစ်လို့ပါ)။ ဒါကြောင့် အဖြေပြန်ပေးတဲ့ Ternary Expression ကို သုံးရပါတယ်။
JavaScript
{isLoggedIn ? "Welcome Back!" : "Please Log In"}
အနှစ်ချုပ်
Expression သည် တန်ဖိုး (Value) တစ်ခုကို ထုတ်ပေးသည်။
React ၏ JSX ထဲတွင် Expression များကိုသာ { } ဖြင့် သုံးနိုင်သည်။
An expression is any valid unit of code that evaluates to a value.
Examples:
5 // number expression
"Hi" // string expression
x + y // arithmetic expression
sayHello() // function call expressionThese are the simplest expressions that represent literal values or keywords.
42
true
"hello"
null
undefined
thisname;
count;let user = {
name: "Aye",
age: 20,
};let numbers = [1, 2, 3];Perform mathematical operations.
x + y
x - y
x * 2
x / 10
x % 3
x ** 2Involves string concatenation or template literals.
"Hello" + " World"
`User: ${username}`Use &&, ||, and !.
true && false
isLoggedIn || hasToken
!isAdminLogical operators return values, not booleans only.
"A" && "B" // "B"
"A" || "B" // "A"x > y
x < y
x >= y
x === y
x !== yThey return true or false.
These assign values and return the assigned value.
x = 10
x += 5
x -= 2
x *= 3Example:
let a;
console.log(a = 5); // prints 5Calling a function is an expression.
doSomething()
alert("Hi")
sum(10, 20)Even methods:
user.getName()Safely access nested properties.
user?.address?.cityAccess properties:
user.nameuser["name"]Short "if...else" that returns a value.
let status = age >= 18 ? "Adult" : "Child";Functions used as expressions.
const add = (a, b) => a + b;Arrow function without body braces implicitly returns:
const double = x => x * 2;let newArr = [...oldArr];function sum(...nums) {
return nums.reduce((a, b) => a + b);
}Evaluates multiple expressions but returns the last one.
let x = (1, 2, 3); // x = 3Rarely used.
Used to create instances.
let date = new Date();
let user = new User("Aye");typeof 123 // "number"void 0 // undefineddelete obj.keyUsed in async functions.
let data = await fetch("/api");Control evaluation order.
(2 + 3) * 4JavaScript expressions:
- Always produce a value
- Can be simple (like
5) or complex (likeuser?.profile?.name ?? "Unknown") - Form the core of JavaScript logic
Understanding expressions helps you write more powerful and flexible code.
JavaScript has a flexible and dynamic type system. Every value in JavaScript belongs to a data type, and understanding them is essential for writing clean, predictable code.
JavaScript မှာ Data Types ဆိုတာ ကွန်ပျူတာက ဒေတာတွေကို ဘယ်လိုအမျိုးအစားအဖြစ် မှတ်သားမလဲဆိုတဲ့ သတ်မှတ်ချက် ဖြစ်ပါတယ်။
JavaScript မှာ ဒေတာအမျိုးအစားတွေကို အဓိက အုပ်စုကြီး (၂) စု ခွဲထားပါတယ်။
၁။ Primitive Data Types (အခြေခံ အမျိုးအစားများ)
ဒါတွေက တန်ဖိုးတစ်ခုတည်းကိုပဲ သိမ်းဆည်းနိုင်ပြီး ပြောင်းလဲလို့မရတဲ့ (Immutable) အခြေခံအမျိုးအစား ၇ ခု ဖြစ်ပါတယ်။
String: စာသားများ။ (ဥပမာ- "Hello", 'Mingalarbar')
Number: ကိန်းဂဏန်းများ (Integer ရော Float ပါ ပါဝင်သည်)။ (ဥပမာ- 25, 3.14)
Boolean: ဟုတ်/မဟုတ်။ (true သို့မဟုတ် false)
Undefined: Variable တစ်ခုကို ကြေညာထားပြီး တန်ဖိုးမထည့်ရသေးတဲ့ အခြေအနေ။
Null: တမင်တကာ "ဘာမှမရှိဘူး" လို့ သတ်မှတ်ထားတဲ့ တန်ဖိုး (Empty value)။
Symbol: ထူးခြားပြီး တစ်ခုတည်းသော identifier အဖြစ် သုံးပါတယ်။ (ES6)
BigInt: အလွန်ကြီးမားတဲ့ ကိန်းဂဏန်းတွေ သိမ်းဖို့ သုံးပါတယ်။
၂။ Non-Primitive (Reference) Data Types
ဒါတွေကတော့ ရှုပ်ထွေးတဲ့ ဒေတာပုံစံတွေဖြစ်ပြီး တန်ဖိုးအများကြီးကို စုစည်းသိမ်းဆည်းနိုင်ပါတယ်။
1. Object: Key-value အတွဲလိုက် သိမ်းဆည်းတဲ့ ဒေတာပုံစံ။
const person = { name: "Aung Aung", age: 20 };
2. Array: စာရင်း (List) ပုံစံ သိမ်းဆည်းတာဖြစ်ပြီး တကယ်တော့ Object အမျိုးအစားထဲကပါပဲ။
const fruits = ["Apple", "Banana", "Orange"];
3. Function: အလုပ်လုပ်ဆောင်ချက်တွေကို သိမ်းဆည်းထားတဲ့ အမျိုးအစား။
၃။ Static vs Dynamic Typing
JavaScript ဟာ Dynamic Typed Language ဖြစ်ပါတယ်။ ဆိုလိုတာက Variable တစ်ခုကို ဘာ အမျိုးအစားလဲဆိုတာ ကြိုပြောစရာမလိုဘဲ ထည့်လိုက်တဲ့ တန်ဖိုးပေါ်မူတည်ပြီး အမျိုးအစားက အလိုအလျောက် ပြောင်းလဲသွားပါတယ်။
let x = 5; // x က Number ဖြစ်သွားပြီ
x = "Hello"; // အခု x က String ဖြစ်သွားပြန်ပြီ
၄။ typeof Operator
Variable တစ်ခုက ဘာ Data Type လဲဆိုတာကို သိချင်ရင် typeof ကို သုံးပြီး စစ်ဆေးနိုင်ပါတယ်။
typeof 10; // "number"
typeof "hi"; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object" (bug)
typeof {}; // "object"
typeof []; // "object"
typeof function(){}; // "function"
Primitive တွေက ရိုးရှင်းပြီး Memory ထဲမှာ တိုက်ရိုက်သိမ်းတယ်။
Reference (Objects) တွေက ရှုပ်ထွေးပြီး Memory ထဲမှာ Reference (လိပ်စာ) အနေနဲ့ သိမ်းတယ်။
JavaScript has 8 main data types:
Primitive Data Types (7 types)
- Number
- String
- Boolean
- Undefined
- Null
- Symbol
- BigInt
Non‑Primitive Data Type (1 type)
- Object
Primitive values:
- are immutable
- compared by value
- stored directly in memory
Represents both integers and floating‑point numbers.
let age = 18;
let price = 19.99;
let infinity = Infinity;
let notNumber = NaN;JavaScript does not have separate types for int, float, double.
Represents text.
let name = "Aye";
let message = 'Hello';
let greeting = `Hi ${name}`; // template literalRepresents logical values.
let isLoggedIn = true;
let hasToken = false;Common Boolean operations:
true && false
true || false
!trueA variable that has been declared but not assigned.
let x;
console.log(x); // undefinedRepresents an intentional absence of value.
let user = null;Note:
typeof null; // "object" (JS historical bug)Unique and immutable values, often used as object keys.
let id = Symbol("id");
let obj = {
[id]: 123,
};Used for very large integers.
let big = 12345678901234567890n;
let sum = big + 10n;BigInts cannot mix with normal numbers:
10 + 10n; // ❌ errorObjects store key‑value pairs.
let user = {
name: "Aye",
age: 20,
};Objects include:
- arrays
- functions
- dates
- regex
- maps
- sets
Everything that is not primitive is an object.
Ordered list of values.
let arr = [1, 2, 3];Functions are objects with callable behavior.
function greet() {
return "Hello";
}Represents date and time.
let now = new Date();Stores key‑value pairs with any key type.
let map = new Map();
map.set("name", "Aye");Stores unique values.
let set = new Set([1, 2, 2, 3]); // {1,2,3}JavaScript is dynamically typed, meaning variables can change type at runtime.
let x = 10;
x = "ten";typeof 10; // "number"
typeof "hi"; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object" (bug)
typeof {}; // "object"
typeof []; // "object"
typeof function(){}; // "function"| Feature | Primitive | Object |
|---|---|---|
| Storage | Value | Reference |
| Mutable? | No | Yes |
| Compared by | Value | Reference |
| Examples | 10, "hi", true |
{}, [], functions |
Example:
let a = { x: 1 };
let b = { x: 1 };
a === b; // false (different references)"5" - 1 // 4
"5" + 1 // "51"Number("5")
String(123)
Boolean(1)JavaScript data types include:
- 7 primitive types: Number, String, Boolean, Undefined, Null, Symbol, BigInt
- 1 non‑primitive type: Object
- JavaScript is dynamically typed
- Primitive values are simple and immutable
- Objects are complex and mutable
Understanding data types helps prevent bugs and write cleaner, more predictable code.
Variables are one of the most fundamental parts of JavaScript. They allow you to store, update, and reuse values inside your programs.
A variable is a named container for storing data.
let message = "Hello World";JavaScript has 3 ways to declare variables:
Each behaves differently.
Introduced in ES6, used for block-scoped variables.
let age = 20;
age = 21; // reassign allowed- Block scoped
{} - Can be reassigned
- Cannot be redeclared in the same scope
Example:
if (true) {
let x = 10;
}
console.log(x); // ❌ Error (x is block-scoped)Also block-scoped, but cannot be reassigned.
const PI = 3.14;
// PI = 3.15; ❌ Errorconst does not make objects immutable.
const user = { name: "Aye" };
user.name = "Ko"; // ✔ allowedYou cannot reassign a new object:
user = {}; // ❌ not allowedFunction-scoped and older keyword.
var name = "Aye";- Not block scoped
- Can be redeclared
- Causes unexpected behavior due to hoisting
Example:
if (true) {
var x = 10;
}
console.log(x); // ✔ 10 (var ignores block scope)Use let or const instead.
Scope determines where a variable can be used.
- Block Scope (
let,const) - Function Scope (
var) - Global Scope
Example:
let globalVar = "I am global"; // Global scope
function exampleFunction() {
var functionVar = "I am function-scoped"; // Function scope (var)
if (true) {
let blockVar = "I am block-scoped"; // Block scope (let)
console.log(blockVar); // Accessible here
}
// console.log(blockVar); // Error: blockVar is not defined here
console.log(functionVar); // Accessible here
}
exampleFunction();
console.log(globalVar); // Accessible here
// console.log(functionVar); // Error: functionVar is not defined hereHoisting ဆိုတာ ➡️ JavaScript engine က code run မလုပ်ခင် ➡️ variable declarations (var, let, const) ➡️ function declarations တွေကို memory ထဲကို အရင် ထားသွားတဲ့ behavior ကို ဆိုလိုတာပါ။
console.log(x); // undefined
var x = 10;console.log(y); // ❌ Error
let y = 10;let x; // declaration
x = 5; // initialization
let y = 10; // declared + initializedVariable names must follow rules.
let name;
let _counter;
let $money;
let age2;let 1age; // cannot start with number
let @name; // symbols not allowed- Use camelCase →
userName - Use descriptive names →
totalPrice - Constants in ALL_CAPS →
MAX_USERS
| Feature | var | let | const |
|---|---|---|---|
| Scope | Function | Block | Block |
| Redeclare? | ✔ Yes | ❌ No | ❌ No |
| Reassign? | ✔ Yes | ✔ Yes | ❌ No |
| Hoisting | Yes (undefined) | TDZ | TDZ |
- Use const by default
- Use let when value will change
- Avoid var
Variables declared outside functions.
let a = 10; // globalGlobal variables can cause bugs — use only when needed.
let count = 1;
count = 2; // ✔ allowed
const PI = 3.14;
PI = 3.2; // ❌ not allowedJavaScript variables:
- Store values for reuse
- Declared using
var,let, orconst let&constare block-scopedvaris function-scoped and outdatedconstprevents reassignment- Hoisting affects how variables behave
Understanding variables helps you control data flow and avoid bugs.
Operators are symbols that tell JavaScript to perform some action (calculations, comparisons, assignments, logic, etc.).
Example:
let x = 10 + 5;Here:
=is an assignment operator+is an arithmetic operator
JavaScript has several categories of operators:
- Arithmetic Operators
- Assignment Operators
- Comparison Operators
- Logical Operators
- Unary Operators
- Ternary Operator
- String Operators
- Bitwise Operators
- Type Operators (
typeof,instanceof) - Optional Chaining & Nullish Coalescing Operators
| Operator | Name | Example |
|---|---|---|
+ |
Addition | 5 + 2 → 7 |
- |
Subtraction | 5 - 2 → 3 |
* |
Multiplication | 5 * 2 → 10 |
/ |
Division | 10 / 2 → 5 |
% |
Modulus (remainder) | 5 % 2 → 1 |
** |
Exponentiation | 2 ** 3 → 8 |
++ |
Increment | x++ |
-- |
Decrement | x-- |
Example:
let a = 10;
a++;
console.log(a); // 11| Operator | Meaning | Example |
|---|---|---|
= |
Assign | x = 10 |
+= |
Add and assign | x += 5 (x = x + 5) |
-= |
Subtract and assign | x -= 5 |
*= |
Multiply and assign | x *= 5 |
/= |
Divide and assign | x /= 5 |
%= |
Modulus and assign | x %= 5 |
**= |
Power and assign | x **= 2 |
These return true or false.
| Operator | Meaning | Example |
|---|---|---|
== |
Equal (loose) | 5 == "5" → true |
=== |
Strict equal | 5 === "5" → false |
!= |
Not equal | 5 != 3 |
!== |
Strict not equal | 5 !== "5" |
> |
Greater than | 10 > 5 |
< |
Less than | 5 < 10 |
>= |
Greater or equal | 10 >= 10 |
<= |
Less or equal | 5 <= 5 |
Example:
console.log(5 === "5"); // false| Operator | Meaning | Example |
| -------- | ------- | ------------------------- |
| `&&` | AND | `true && false` → `false` |
| `||` | OR | `true || false`→`true` |
| `!` | NOT | `!true` → `false` | Example:
let isLoggedIn = true;
let isAdmin = false;
console.log(isLoggedIn && isAdmin); // false| Operator | Meaning |
|---|---|
typeof |
Returns data type |
void |
Evaluates but returns undefined |
delete |
Removes object property |
+ |
Convert to number |
- |
Convert to negative number |
Example:
console.log(typeof 123); // "number"Shorthand for if/else.
condition ? valueIfTrue : valueIfFalse;Example:
let age = 18;
let msg = age >= 18 ? "Adult" : "Minor";
console.log(msg);The + operator is used for string concatenation.
let name = "Toe" + "Wai";
console.log(name); // "ToeWai"Returns the right-hand value when the left side is null or undefined.
let user;
console.log(user ?? "Guest"); // GuestAvoids errors when accessing properties of undefined or null.
let user = {};
console.log(user.address?.street); // undefined, no errorAdvanced topic — used for low-level operations.
| Operator | Meaning |
| -------- | --------------------- |
| `&` | AND |
| || | OR |
| `^` | XOR |
| `~` | NOT |
| `<<` | Left shift |
| `>>` | Right shift |
| `>>>` | Zero-fill right shift | Example:
2 + 3 * 4; // 14 (because * runs before +)Shortcut:
()parentheses highest- Then unary (
!,typeof) - Then
* / % - Then
+ - - Then comparisons
- Then logical
- Last: assignment
A complete guide to how decisions are made in JavaScript — using if, else, switch, ternary, truthy/falsy, and more.
Conditions allow JavaScript to make decisions based on true/false results.
Example:
let age = 18;
if (age >= 18) {
console.log("You are an adult");
}JavaScript supports:
ifstatementif...elsestatementelse ifchainswitchstatement- Ternary operator (
? :) &&and||short‑circuit conditions- Optional chaining (
?.) with conditions
Runs code only when the condition is true.
if (condition) {
// code
}Example:
let score = 80;
if (score > 50) {
console.log("Pass");
}Runs one block if true, another if false.
if (condition) {
// true block
} else {
// false block
}Example:
let isOnline = false;
if (isOnline) {
console.log("User is online");
} else {
console.log("User is offline");
}Checks multiple conditions one by one.
if (temperature > 30) {
console.log("Hot");
} else if (temperature > 20) {
console.log("Warm");
} else {
console.log("Cold");
}Used when checking one value against many possible cases.
switch (day) {
case "Mon":
console.log("Work day");
break;
case "Sat":
console.log("holiday");
case "Sun":
console.log("Weekend");
break;
default:
console.log("Unknown day");
}- Cleaner when many
else ifconditions - Great for checking a single variable
Short version of if...else.
condition ? valueIfTrue : valueIfFalse;Example:
let age = 18;
let message = age >= 18 ? "Adult" : "Minor";
console.log(message);Best used for simple decisions.
JavaScript treats some values as true or false automatically.
false0""(empty string)nullundefinedNaN
Everything else is truthy.
Example:
if ("") console.log("This won't run");
if ("hello") console.log("This will run");Runs only if both conditions are true.
if (isLoggedIn && isAdmin) {
console.log("Welcome Admin");
}Runs if at least one condition is true.
if (day === "Sat" || day === "Sun") {
console.log("Weekend");
}Reverses a boolean.
if (!isOnline) {
console.log("Offline");
}Avoids errors when checking nested properties.
if (user?.address?.city) {
console.log("City found");
}Example:
let age = 20;
let hasID = true;
if (age >= 18 && hasID) {
console.log("You may enter");
}if (x = 5) { } // WRONGThis assigns, not compares.
Correct:
if (x === 5) { }switch(x) {
case 1:
console.log("One");
case 2:
console.log("Two"); // Both run ❌
}Use conditions to:
- Make decisions
- Control program flow
- Validate data
- React to user input
Tools for conditions:
if,else,else ifswitch- Ternary operator
- Logical operators
- Truthy/falsy evaluation
A complete guide to loops in JavaScript — how to repeat actions, iterate data, and control flow efficiently.
Loops allow you to repeat code multiple times — automatically.
Example:
for (let i = 1; i <= 3; i++) {
console.log(i);
}Output:
1
2
3
JavaScript supports several loop types:
-
for loop
-
while loop
-
do...while loop
-
for...of loop (iterate arrays, strings, etc.)
-
for...in loop (iterate object keys)
-
Array iteration methods (not exactly loops but commonly used)
forEachmapfilterreduce
Most common and powerful loop.
for (initialization; condition; update) {
// code
}for (let i = 0; i < 5; i++) {
console.log("Number:", i);
}Runs as long as the condition is true.
let i = 0;
while (i < 3) {
console.log(i);
i++;
}Use when you don't know how many times to loop.
Runs at least once, even if the condition is false.
let i = 5;
do {
console.log(i);
i++;
} while (i < 3);Used for iterating iterables:
- Arrays
- Strings
- Maps
- Sets
let colors = ["red", "green", "blue"];
for (const c of colors) {
console.log(c);
}Used to iterate object keys.
let user = {
name: "Toe",
age: 18,
};
for (const key in user) {
console.log(key, user[key]);
}for...in for arrays.
These are not loops but often replace loops.
[1, 2, 3].forEach(n => console.log(n));let doubled = [1, 2, 3].map(n => n * 2);let even = [1, 2, 3, 4].filter(n => n % 2 === 0);let sum = [1, 2, 3].reduce((a, b) => a + b, 0);for (let i = 1; i <= 5; i++) {
if (i === 3) break;
console.log(i);
}for (let i = 1; i <= 5; i++) {
if (i === 3) continue;
console.log(i);
}while (true) {
console.log("This never stops");
}Make sure your loop condition eventually becomes false.
Loop inside a loop.
for (let i = 1; i <= 2; i++) {
for (let j = 1; j <= 3; j++) {
console.log(i, j);
}
}| Loop Type | Best Use |
|---|---|
for |
Known number of iterations |
while |
Unknown number of iterations |
do...while |
Run at least once |
for...of |
Arrays, strings, iterables |
for...in |
Object keys |
forEach |
Simple iteration (no break) |
map |
Transform array |
filter |
Filter array |
reduce |
Calculate a single value |
❌ Forgetting to update the counter
❌ Creating infinite loops
❌ Using for...in for arrays
❌ Expecting break inside forEach (it does not work)
Loops help you:
- Repeat actions
- Work with collections
- Automate repetitive tasks
- Process arrays/objects
You now know:
for,while,do...whilefor...of,for...in- Array iteration methods
- break/continue
A complete guide to JavaScript functions — definitions, types, parameters, return values, arrow functions, scopes, closures, and more.
A function is a reusable block of code designed to perform a task.
Example:
function greet() {
console.log("Hello!");
}Functions help you:
- Avoid repeating code
- Organize logic
- Make code cleaner
- Create modular programs
- Return values from operations
Also called a named function.
function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // 5- Hoisted (usable before declaration)
Function stored in a variable.
const multiply = function (a, b) {
return a * b;
};- Not hoisted
- Can be anonymous or named
Short syntax introduced in ES6.
const greet = () => {
console.log("Hi!");
};Short single-line form:
const square = n => n * n;- No
thisbinding - No
argumentsobject - Great for callbacks
Parameters → variables written in function definition Arguments → values passed when calling
Example:
function hello(name) { // parameter
console.log("Hello", name);
}
hello("Toe"); // argumentfunction greet(name = "Guest") {
console.log("Hello", name);
}Used when the number of arguments is unknown.
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}Functions can return a value.
function add(a, b) {
return a + b;
}If no return → returns undefined.
Functions without a name.
Used in callbacks:
setTimeout(function () {
console.log("Done");
}, 1000);A function passed as an argument to another function.
function process(callback) {
callback();
}
process(() => console.log("Running!"));Functions that:
- Take another function as an argument, or
- Return a function
Example:
function createMultiplier(x) {
return function (y) {
return x * y;
};
}
const double = createMultiplier(2);
console.log(double(5)); // 10Functions create their own scope.
function test() {
let x = 10;
}
// x is not accessible herelet&const→ block scopedvar→ function scoped
if (true) {
let a = 10; // block
var b = 20; // function
}
// b is still accessibleA closure is when a function remembers variables from its outer scope.
function outer() {
let count = 0;
return function () {
count++;
console.log(count);
};
}
const counter = outer();
counter(); // 1
counter(); // 2Closures are used in:
- Private variables
- Factory functions
- Module patterns
function sayHi() {}const sayHi = function() {}Runs immediately after creation.
(function () {
console.log("I am an IIFE");
})();- No side effects
- Same input → same output
function add(a, b) {
return a + b;
}let x = 1;
function addToX(y) {
x += y; // modifies outside variable
}Functions in JavaScript are first-class citizens:
- Can be stored in variables
- Can be passed as arguments
- Can be returned from functions
You learned:
- Function declarations & expressions
- Arrow functions
- Parameters, arguments, return values
- Scope & closures
- Callbacks & higher-order functions
- IIFE, pure functions, rest parameters
Functions are the foundation of JavaScript. Mastering them = mastering JS.
JavaScript objects are one of the most important parts of the language. They let you store data in key-value pairs and model real-world entities.
An object is a collection of related data and functions.
const user = {
name: "Alex",
age: 18,
isStudent: true,
};- Keys →
name,age,isStudent - Values → "Alex", 18, true
const car = {
brand: "Toyota",
model: "Vios",
year: 2020
};const obj = new Object();
obj.x = 10;
obj.y = 20;function Person(name, age) {
this.name = name;
this.age = age;
}
const p1 = new Person("John", 20);class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const u1 = new User("Alice", 25);console.log(user.name);console.log(user["age"]);Useful when:
- key contains spaces
- key is dynamic
user.email = "alex@example.com";user.age = 19;delete user.isStudent;const person = {
name: "Leo",
greet() {
console.log(`Hi, I am ${this.name}`);
}
};
person.greet();this refers to the current object.
const student = {
name: "Nyein",
address: {
city: "Yangon",
township: "Hlaing"
}
};for (let key in user) {
console.log(key, user[key]);
}console.log(Object.keys(user));console.log(Object.values(user));console.log(Object.entries(user));const copy = { ...user };const deepCopy = JSON.parse(JSON.stringify(user));const { name, age } = user;
console.log(name, age);Prevents errors when a property might be missing.
console.log(student.address?.city);Object.keys(obj)→ returns keysObject.values(obj)→ returns valuesObject.entries(obj)→ returns key/value pairsObject.assign(target, source)→ merges objects
const product = {
id: 1,
name: "Laptop",
price: 980000,
specs: {
cpu: "i5",
ram: "16GB"
},
getInfo() {
return `${this.name} - ${this.price} Ks`;
}
};- Objects store data in key/value pairs
- Methods = functions inside objects
- Dot & bracket notation for access
- Use destructuring for cleaner code
- Objects are used everywhere in JS (React, APIs, Node.js)
An array is a special data structure in JavaScript used to store ordered collections of values.
const numbers = [1, 2, 3];
const mixed = ["Hello", 42, true, null];Arrays are mutable, dynamic, and zero‑indexed.
- Index starts from 0
const fruits = ["apple", "banana", "mango"];
console.log(fruits[0]); // apple
console.log(fruits[2]); // mango- Accessing an out‑of‑range index returns undefined.
const arr = [1, 2, 3];const arr = new Array(5); // creates empty array of length 5| Action | Method | Example |
|---|---|---|
| Add end | push() |
arr.push(10) |
| Remove end | pop() |
arr.pop() |
| Add start | unshift() |
arr.unshift(5) |
| Remove start | shift() |
arr.shift() |
const nums = [1,2,3];
nums.push(4); // [1,2,3,4]
nums.pop(); // [1,2,3]| Method | Description |
|---|---|
indexOf() |
Returns index of value |
includes() |
Returns true/false |
const colors = ["red", "blue", "green"];
colors.includes("blue"); // true[1, 2, 3].map(n => n * 2); // [2, 4, 6][1, 2, 3, 4].filter(n => n % 2 === 0); // [2, 4][1, 2, 3].reduce((total, n) => total + n, 0); // 6for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}for (const item of arr) {
console.log(item);
}arr.forEach(item => console.log(item));const [a, b] = [10, 20];
console.log(a); // 10Skip items:
const [first, , third] = [1,2,3];const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4];function sum(...nums) {
return nums.reduce((a, b) => a + b);
}arr.slice(1, 3); // returns part of arrayarr.splice(1, 1); // removes item at index 1["a","b"].join("-"); // "a-b"[3,1,2].sort(); // [1,2,3][1,2,3].reverse(); // [3,2,1]const matrix = [
[1, 2],
[3, 4]
];
console.log(matrix[1][0]); // 3Use arrays when you need ordered data, such as:
- lists of items
- API responses
- user inputs
- numeric operations
- loops & transformations
JavaScript is single-threaded, but it can perform non-blocking operations using asynchronous programming.
Async JS allows tasks like:
- Fetching data from a server
- Reading files
- Timers
- Events
to run without blocking the main thread.
Without async code:
- Long operations freeze the page
- UI becomes unresponsive
- Slow APIs block execution
Async JS lets the browser handle tasks in the background.
The Event Loop is the system that manages asynchronous operations.
JavaScript uses:
- Call Stack → executes code
- Web APIs → timers, fetch, DOM
- Callback Queue → completed tasks
- Event Loop → sends tasks to stack when it's empty
This enables async behavior even though JS has one thread.
A callback is a function passed as an argument.
function getData(callback) {
setTimeout(() => {
callback("Done!");
}, 1000);
}
getData(result => {
console.log(result);
});Nested callbacks become hard to read:
a(() => {
b(() => {
c(() => {
d();
});
});
});A Promise represents a value that will be available in the future.
- pending
- fulfilled
- rejected
const promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("Success"), 1000);
});
promise.then(result => console.log(result));promise.catch(err => console.error(err));promise.finally(() => console.log("Done"));Introduced in ES2017, async/await lets you write asynchronous code like synchronous code.
async function loadData() {
const result = await fetch("/api/data");
const data = await result.json();
console.log(data);
}
loadData();async function run() {
try {
const res = await fetch("/invalid");
} catch (err) {
console.log("Error:", err);
}
}- Promise callbacks (
then,catch)
setTimeoutsetInterval
Execution order:
- Call Stack
- All microtasks
- One macrotask
- Repeat
setTimeout(() => console.log("Hi"), 1000);setInterval(() => console.log("Tick"), 1000);fetch("/api").then(res => res.json()).then(data => console.log(data));await task1();
await task2();await Promise.all([task1(), task2()]);Promise.race([task1(), task2()]);promise.catch(err => console.error(err));try {
await something();
} catch (err) {
console.error(err);
}async function getUsers() {
const res = await fetch("https://jsonplaceholder.typicode.com/users");
return res.json();
}const fs = require("fs/promises");
async function readFile() {
const data = await fs.readFile("text.txt", "utf8");
console.log(data);
}JavaScript is a dynamically typed language, meaning variables can change their type at runtime. Type casting (also called type coercion) is the process of converting one data type to another.
JavaScript performs two types of type casting:
- Implicit (Automatic) Type Coercion
- Explicit (Manual) Type Conversion
JavaScript automatically converts types during operations.
When one operand is a string → JS converts the other to string.
"5" + 3; // "53"
5 + "3"; // "53"When using -, *, /, %, JS converts both values to numbers.
"10" - 2; // 8
"6" * "2"; // 12
"20" / 5; // 4Values are converted to true/false in logical contexts.
Falsy values:
false, 0, "", null, undefined, NaN
Everything else → true
Boolean(0); // false
Boolean("Hi"); // trueYou convert types using built-in functions.
Use:
Number(value)parseInt(value)parseFloat(value)- Unary
+value
Number("10"); // 10
parseInt("10px"); // 10
parseFloat("9.5"); // 9.5
+"5"; // 5Number("hello"); // NaNUse:
String(value).toString()
String(123); // "123"
(100).toString(); // "100"Use:
Boolean(value)!!value
Boolean(1); // true
Boolean(0); // false
!!"hi"; // true- If one operand = string → convert to string
1 + "2"; // "12"JavaScript tries to convert values to the same type
"5" == 5; // true
true == 1; // true
false == 0; // trueNo type coercion
"5" === 5; // false| Expression | Result |
|---|---|
true + 1 |
2 |
false + 1 |
1 |
"5" * 2 |
10 |
"5" + 2 |
"52" |
null + 1 |
1 |
undefined + 1 |
NaN |
typeof "hello"; // "string"
typeof 50; // "number"
typeof true; // "boolean"
typeof null; // "object" (known JS bug)
typeof [] // "object"✔ Use explicit conversion instead of relying on coercion
✔ Avoid using loose equality (==)
✔ Use strict equality (===)
✔ Use Number() instead of parseInt() when possible
✔ Be careful with + → it triggers string coercion
JavaScript modules allow you to split your code into reusable, maintainable files. Each module can export variables/functions/classes and another file can import them.
Modules help with:
- Better code organization
- Reusability
- Avoiding global namespace pollution
- Easier maintenance
- Cleaner architecture
Modern JavaScript uses ES Modules (ESM).
The modern module system using:
import ... from "module";
export ...;Supported in:
- Browsers (using
<script type="module">) - Node.js (with
.mjsor package.json type: module)
Exports allow a file to expose code so other files can import it.
You can export multiple items.
// math.js
export const PI = 3.14;
export function add(a, b) {
return a + b;
}One file can have only one default export.
// greet.js
export default function greet(name) {
console.log(`Hello, ${name}`);
}import { PI, add } from "./math.js";
console.log(add(2, 3));import greet from "./greet.js";
greet("Koko");import { add as sum } from "./math.js";import * as math from "./math.js";
math.add(2, 3);
math.PI;You can mix named + default exports.
// utils.js
export default function log(msg) {
console.log(msg);
}
export const version = "1.0.0";import log, { version } from "./utils.js";- A module is executed only once, even if imported multiple times.
- Imports are read before code runs (top-level scope).
- Modules always run in strict mode.
<script type="module" src="/app.js"></script>Features:
- Modules load deferred automatically
importworks inside scripts
node app.mjs{
"type": "module"
}Then use:
import { add } from "./math.js";| Feature | CommonJS | ES Modules |
|---|---|---|
| Syntax | require/export | import/export |
| Loaded | runtime | compile-time |
| File Ext | .js | .mjs or js w/ type: module |
| Default | Node.js | Browser + Node |
const fs = require("fs");
module.exports = {};import fs from "fs";
export default {};Useful for lazy loading or conditional imports.
if (true) {
const module = await import("./math.js");
console.log(module.add(2, 3));
}project/
├─ utils/
│ ├─ math.js
│ └─ helpers.js
├─ components/
│ └─ navbar.js
└─ app.js
export function multiply(a, b) {
return a * b;
}import { multiply } from "./utils/math.js";
console.log(multiply(4, 5));✔ Use named exports when exporting many items ✔ Use default export when exporting a single main value ✔ Keep file names descriptive ✔ Group similar modules into folders ✔ Avoid circular imports ✔ Prefer ES Modules over CommonJS for new projects
Error handling in JavaScript allows you to catch and manage errors so your program doesn’t crash unexpectedly. Errors can happen due to:
- Invalid input
- Network failure
- Wrong code logic
- Unexpected API responses
- Missing files (Node.js)
JavaScript provides tools like try/catch, throw, finally, and error objects to manage these situations safely.
Code cannot run due to incorrect syntax.
console.log("Hello" // missing parenthesisUsing a variable that does not exist.
console.log(x); // x is not definedWrong operation on the wrong data type.
const num = 5;
num.toUpperCase(); // TypeErrorInvalid length or number range.
new Array(-2); // RangeErrorYou can throw your own custom errors.
throw new Error("Something went wrong!");Used to handle errors gracefully.
try {
const result = dangerousFunction();
} catch (error) {
console.log("Error happened:", error);
}Runs always, whether there's an error or not.
try {
console.log("Trying...");
} catch (err) {
console.log("Error!");
} finally {
console.log("Always runs");
}Use throw to trigger your own error.
function divide(a, b) {
if (b === 0) {
throw new Error("Cannot divide by zero");
}
return a / b;
}JavaScript error objects contain useful information:
try {
throw new Error("Failed to load");
} catch (e) {
console.log(e.name); // "Error"
console.log(e.message); // "Failed to load"
console.log(e.stack); // stack trace
}Common error types:
- Error
- TypeError
- ReferenceError
- SyntaxError
- RangeError
- EvalError
fs.readFile("test.txt", (err, data) => {
if (err) return console.error(err);
console.log(data);
});fetch("/api")
.then(res => res.json())
.catch(err => console.log("Error:", err));async function loadData() {
try {
const res = await fetch("/api/users");
const data = await res.json();
} catch (error) {
console.log("Failed to load:", error);
}
}window.onerror = function(message, source, line, column, error) {
console.log("Global Error: ", message);
};process.on("uncaughtException", (err) => {
console.log("Unhandled Exception:", err);
});Throw custom errors when data is invalid.
function register(user) {
if (!user.name) {
throw new Error("Name is required");
}
}✔ Log errors clearly ✔ Include timestamp ✔ Never show internal errors to users ✔ Use monitoring tools (Sentry, LogRocket, Datadog) ✔ Use custom error classes for clarity
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
throw new ValidationError("Invalid email format");✔ Use try/catch only where needed
✔ Throw meaningful error messages
✔ Clean and consistent error structure
✔ Handle async errors with try/catch or .catch()
✔ Avoid silent error handling
✔ Use custom errors for validation and logic problems
JavaScript supports Object-Oriented Programming (OOP) using prototypes and ES6 classes.
OOP is a programming paradigm that organizes code into objects — each object contains data (properties) and behavior (methods).
JavaScript implements OOP using:
- Objects
- Prototypes
- Constructor functions
- Classes (ES6)
A class is a blueprint for creating objects.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, my name is ${this.name}`);
}
}
const p1 = new Person("John", 20);
p1.greet();Objects are instances created from classes.
const user = new Person("Alice", 25);The constructor() method initializes object properties.
class Car {
constructor(brand, year) {
this.brand = brand;
this.year = year;
}
}Encapsulation hides internal details and protects data.
Modern JS supports private fields:
class BankAccount {
#balance = 0; // private
deposit(amount) {
this.#balance += amount;
}
getBalance() {
return this.#balance;
}
}Abstraction shows only essential features and hides complexity.
class CoffeeMachine {
start() {
this._heatWater();
console.log("Coffee ready!");
}
_heatWater() { // Pretend private
console.log("Heating...");
}
}One class can inherit properties & methods from another.
class Animal {
speak() {
console.log("Animal sound");
}
}
class Dog extends Animal {
speak() {
console.log("Woof!");
}
}
const d = new Dog();
d.speak();Child classes can override parent class methods.
Example above: Dog.speak() overrides Animal.speak().
Another example:
class Shape {
area() {
return 0;
}
}
class Circle extends Shape {
constructor(r) {
super();
this.r = r;
}
area() {
return Math.PI * this.r * this.r;
}
}this refers to the current object instance.
class User {
constructor(name) {
this.name = name; // "this" = current object
}
}Static methods belong to the class (not instances).
class MathUtils {
static add(a, b) {
return a + b;
}
}
MathUtils.add(5, 3); // OKBefore ES6 classes, OOP in JS used prototypes.
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
console.log("Hello " + this.name);
};| Concept | Description |
|---|---|
| Class | Blueprint for objects |
| Object | Instance of a class |
| Constructor | Initializes properties |
| Encapsulation | Hiding data, using private fields |
| Abstraction | Hiding complexity |
| Inheritance | Reusing parent class features |
| Polymorphism | Overriding methods |
| Static methods | Methods used on class, not object |
| Prototype | JS's underlying OOP system |
class User {
constructor(username) {
this.username = username;
}
login() {
console.log(this.username + " logged in");
}
}
class Admin extends User {
deleteUser(user) {
console.log(`Admin deleted ${user.username}`);
}
}
const admin = new Admin("Admin1");
const user = new User("Tom");
admin.login();
admin.deleteUser(user);JSON is one of the most important data formats in modern web development. It is used to store, exchange, and transport data between servers, APIs, and applications.
JSON stands for JavaScript Object Notation.
It is:
- A text-based data format
- Lightweight
- Easy for humans to read
- Easy for machines to parse
- Language-independent (not only for JavaScript)
Example JSON:
{
"name": "John",
"age": 25,
"isStudent": false,
"skills": ["HTML", "CSS", "JavaScript"]
}{
"name": "John",
"age": 25
}- Keys are always strings (double quotes)
- Cannot contain functions
- Only supports values: string, number, object, array, boolean, null
const user = {
name: "John",
age: 25,
greet() {
console.log("Hello");
}
};- Keys can be without quotes
- Can contain methods & variables
| Type | Example |
|---|---|
| String | "Hello" |
| Number | 10, 2.5 |
| Boolean | true / false |
| Object | { "a": 1 } |
| Array | [1, 2, 3] |
| Null | null |
⛔ JSON does not support:
- Functions
- Comments
- Undefined
- Date objects (must be a string)
const user = {
name: "Alice",
age: 20
};
const jsonData = JSON.stringify(user);
console.log(jsonData);
// "{"name":"Alice","age":20}""This is often used when:
- Sending data to a server
- Saving data in localStorage
const json = '{"name":"Alice","age":20}';
const obj = JSON.parse(json);
console.log(obj.name); // AliceUsed when:
- Receiving data from API
- Reading from localStorage
fetch("https://api.example.com/user")
.then(res => res.json()) // parse JSON response
.then(data => console.log(data));const user = { name: "Tom", age: 30 };
// Save
localStorage.setItem("user", JSON.stringify(user));
// Read
const data = JSON.parse(localStorage.getItem("user"));
console.log(data.name);{
'name': 'John' // ❌ invalid
}JSON requires double quotes.
{
"name": "John",
"age": 30, // ❌ invalid
}{
"name": "John" // ❌ comments not allowed
}const json = JSON.stringify(user, null, 2);
console.log(json);Output:
{
"name": "Alice",
"age": 20
}| Feature | Description |
|---|---|
| JSON | Data exchange format |
| stringify() | JS → JSON string |
| parse() | JSON string → JS object |
| Data types | string, number, object, array, boolean, null |
| Used in | APIs, databases, configs, localStorage |
The Fetch API is a modern, promise-based way to make HTTP requests in JavaScript. It is widely used in web development for calling APIs, sending data to servers, and retrieving JSON.
fetch() is a built-in browser function that allows you to request resources over the network.
Basic syntax:
fetch(url, options?)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));fetch("https://api.example.com/users")
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.log(err));async function getUsers() {
try {
const res = await fetch("https://api.example.com/users");
const data = await res.json();
console.log(data);
} catch (err) {
console.error(err);
}
}async function createUser() {
const newUser = {
name: "John",
age: 22
};
const res = await fetch("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(newUser)
});
const data = await res.json();
console.log(data);
}fetch("https://api.example.com/users/1", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "Updated User" })
})
.then(res => res.json())
.then(data => console.log(data));await fetch("https://api.example.com/users/1", {
method: "DELETE"
});fetch() does NOT throw errors for HTTP status codes like 404 or 500.
You must check them manually:
async function loadData() {
try {
const res = await fetch("https://api.example.com/data");
if (!res.ok) {
throw new Error(`HTTP Error: ${res.status}`);
}
const data = await res.json();
console.log(data);
} catch (error) {
console.error("Fetch Error:", error);
}
}fetch(url, {
headers: {
"Authorization": "Bearer token123",
"Content-Type": "application/json"
}
});const res = await fetch("/info.txt");
const text = await res.text();const res = await fetch("/image.png");
const blob = await res.blob();const formData = new FormData();
formData.append("photo", fileInput.files[0]);
await fetch("/upload", {
method: "POST",
body: formData
});Cancel a long-running request:
const controller = new AbortController();
fetch(url, { signal: controller.signal });
controller.abort();| Option | Description |
|---|---|
| method | GET, POST, PUT, DELETE |
| headers | Additional metadata (JSON, Auth, etc.) |
| body | Request payload |
| signal | AbortController for canceling |
async function loadPage(page) {
const res = await fetch(`/api/users?page=${page}`);
const data = await res.json();
console.log(data);
}export async function GET() {
const res = await fetch("https://api.example.com/products", {
cache: "no-store"
});
const data = await res.json();
return Response.json(data);
}fetch()is Promise-based- Supports GET, POST, PUT, DELETE
- Use
res.json()to convert API response - Must manually check
res.ok - Supports headers, FormData, Blob, File uploads
- Works great with async/await
ES6+ refers to ECMAScript 2015 (ES6) and all versions after it. It introduced many powerful features that make JavaScript cleaner, faster, and easier to write.
- Block scoped
- Can be reassigned
let age = 20;
age = 21;- Block scoped
- Cannot be reassigned
const name = "Alex";Shorter, cleaner syntax.
const add = (a, b) => a + b;Arrow functions do not have their own this.
Use backticks `, variable interpolation, and multiline strings.
const name = "John";
console.log(`Hello ${name}!`);function greet(name = "Guest") {
console.log(`Hello ${name}`);
}const user = { name: "Tom", age: 30 };
const { name, age } = user;const nums = [10, 20, 30];
const [a, b] = nums;const arr1 = [1,2];
const arr2 = [...arr1, 3, 4];const user = { name: "Alice" };
const newUser = { ...user, age: 22 };function sum(...nums) {
return nums.reduce((a, b) => a + b);
}const name = "John";
const age = 20;
const user = {
name,
age,
greet() {
console.log("Hello!");
}
};// math.js
export function add(a, b) { return a + b; }
// app.js
import { add } from "./math.js";class Person {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} speaks`);
}
}const getData = () => new Promise((resolve) => {
resolve("Done");
});Cleaner way to handle asynchronous code.
async function load() {
const data = await fetch("/api");
}Safer property access.
console.log(user?.address?.city);Returns right value only if left is null or undefined.
const username = input ?? "Guest";const set = new Set([1,2,2,3]);const map = new Map();
map.set("name", "John");for (const value of [10,20,30]) {
console.log(value);
}Unique identifier.
const id = Symbol("id");Large integers.
const n = 12345678901234567890n;import("./module.js").then(module => {
module.run();
});await Promise.all([p1, p2]);| Feature | Description |
|---|---|
| let/const | Block-scoped variables |
| Arrow functions | Shorter, no this |
| Template literals | Backtick strings |
| Destructuring | Extract values |
| Spread/Rest | Expand or collect |
| Classes | OOP support |
| Promises | Async operations |
| Async/await | Cleaner async |
| Optional chaining | Safe access |
| Modules | import/export |
Browser APIs (Application Programming Interfaces) are built-in features provided by web browsers that allow JavaScript to interact with the browser and the environment.
They let you:
- Manipulate the DOM
- Handle user events
- Store data
- Work with multimedia
- Access device features
- Fetch network resources
The DOM API lets JavaScript interact with HTML elements.
document.getElementById("title");
document.querySelector(".item");const title = document.querySelector("h1");
title.textContent = "Updated Title";
title.style.color = "blue";const div = document.createElement("div");
div.textContent = "Hello";
document.body.appendChild(div);Handle clicks, input, submit, keyboard, scroll, etc.
document.querySelector("button").addEventListener("click", () => {
console.log("Button clicked!");
});- Stores data permanently (until deleted)
localStorage.setItem("theme", "dark");
localStorage.getItem("theme");- Stores data for one tab session
sessionStorage.setItem("token", "123");Used to make HTTP requests.
fetch("/api/data")
.then(res => res.json())
.then(data => console.log(data));setTimeout(() => {
console.log("Runs once after 2 seconds");
}, 2000);
setInterval(() => {
console.log("Repeats every second");
}, 1000);Retrieve user location (with permission).
navigator.geolocation.getCurrentPosition(pos => {
console.log(pos.coords.latitude, pos.coords.longitude);
});Access camera/microphone.
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => console.log(stream));Control audio and video elements.
document.querySelector("video").play();
document.querySelector("audio").pause();Copy text to clipboard.
navigator.clipboard.writeText("Copied!");Paste (with permission):
navigator.clipboard.readText().then(text => console.log(text));Used for drawing graphics.
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 100, 100);Manage browser navigation.
history.pushState({ page: 1 }, "Title", "?page=1");Includes:
localStoragesessionStorageCookies(via document.cookie)
Real-time communication.
const socket = new WebSocket("ws://example.com");
socket.onmessage = event => console.log(event.data);Show system notifications.
Notification.requestPermission().then(() => {
new Notification("Hello!");
});Detect when elements enter the viewport.
const observer = new IntersectionObserver(entries => {
if (entries[0].isIntersecting) {
console.log("Element visible");
}
});
observer.observe(document.querySelector("#target"));const url = new URL(window.location);
console.log(url.searchParams.get("id"));| API | Purpose |
|---|---|
| DOM API | Work with HTML elements |
| Events API | User interactions |
| Storage API | localStorage / sessionStorage |
| Fetch API | Make network requests |
| Geolocation | Get location |
| MediaDevices | Camera/Mic access |
| Canvas | Draw graphics |
| WebSocket | Real-time data |
| Notification | System notifications |
| Timers | setTimeout, setInterval |
| URL API | Parse/manipulate URLs |
Hoisting ဆိုတာ JavaScript မှာ variable တွေနဲ့ function တွေကို code မ run ခင်
(Execution context တည်ဆောက်တဲ့အချိန်) memory ထဲမှာ နေရာကြိုယူထားတဲ့ သဘောတရားဖြစ်ပါတယ်။
ရိုးရိုးရှင်းရှင်းပြောရရင် သင်က variable တစ်ခုကို မကြေညာခင် (Declare မလုပ်ခင်) အပေါ်ကနေ လှမ်းသုံးလိုက်ရင်တောင်
JavaScript က error မတက်စေဘဲ variable declaration ကို code ရဲ့ ထိပ်ဆုံးကို ဆွဲတင်လိုက်သလိုမျိုး
ပြုမူတာကို ခေါ်တာပါ။
၁။ Function Hoisting
Function တွေက Hoisting မှာ အထူးအခွင့်အရေးရပါတယ်။ Function တစ်ခုလုံးကို memory ထဲ ကြိုတင်သိမ်းထားတဲ့အတွက်
သူ့ကို မရေးခင် (အပေါ်ကနေ) လှမ်းခေါ်လို့ ရပါတယ်။
sayHello(); // အလုပ်လုပ်တယ်: "မင်္ဂလာပါ"
function sayHello() {
console.log("မင်္ဂလာပါ");
}
၂။ Variable Hoisting (var, let, const)
Variable တွေမှာတော့ သူတို့ကို ကြေညာတဲ့ keyword ပေါ်မူတည်ပြီး အလုပ်လုပ်ပုံ ကွာခြားပါတယ်။
var: Hoisting ဖြစ်ပါတယ်။ ဒါပေမဲ့ variable ရဲ့ တန်ဖိုး (value) ကိုတော့ မသိသေးဘဲ undefined
အဖြစ်ပဲ မှတ်ထားပါတယ်။
let နှင့် const: သူတို့လည်း Hoisting ဖြစ်ပါတယ်။ ဒါပေမဲ့ သူတို့ကို memory ထဲမှာ နေရာယူထားရုံပဲ
ရှိပြီး code က သူတို့ဆီ မရောက်မချင်း အသုံးပြုခွင့် မပေးပါဘူး။ ဒါကို Temporal Dead Zone (TDZ) လို့ ခေါ်ပါတယ်။
** Temporal Dead Zone (TDZ) ဆိုတာ let နဲ့ const variable တွေမှာ ဖြစ်လေ့ရှိတဲ့ အပြုအမူတစ်ခုပါ။
variable ကို စတင်ကြေညာ (declare) တဲ့ code အကြောင်းဆီ မရောက်ခင် အပေါ်ကနေ လှမ်းသုံးမိရင်
ReferenceError တက်စေတဲ့ နယ်မြေ (Area) ကို ခေါ်တာ ဖြစ်ပါတယ်။**
| Keyword | Hoisted ဖြစ်လား | တန်ဖိုး (Initial Value) | Error တက်လား |
|---|---|---|---|
| var | ဖြစ်တယ် | undefined | မတက်ဘူး(undefined ပြမယ်) |
| let / const | ဖြစ်တယ် | မရှိဘူး (Uninitialized) | ReferenceError တက်မယ် |
Scope ဆိုတာ JavaScript မှာ variable တွေ၊ functions တွေနဲ့ objects တွေကို
"ဘယ်နေရာကနေ လှမ်းသုံးလို့ရသလဲ" ဆိုတဲ့ အတိုင်းအတာ သို့မဟုတ် နယ်နိမိတ်ကို ခေါ်တာ ဖြစ်ပါတယ်။
ရိုးရိုးရှင်းရှင်းပြောရရင် Variable တစ်ခုရဲ့ "သက်တမ်း" နဲ့ "မြင်နိုင်စွမ်း" (Visibility) ကို Scope က ဆုံးဖြတ်ပေးတာပါ။
၁။ Scope အမျိုးအစား (၃) မျိုး
JavaScript မှာ အဓိကအားဖြင့် အောက်ပါ Scope ၃ ခု ရှိပါတယ်-
(က) Global Scope
မည်သည့် function သို့မဟုတ် block ရဲ့ အပြင်ဘက်မှာမဆို ကြေညာထားတဲ့ variable တွေပါ။
ထူးခြားချက်: Code တစ်ခုလုံးရဲ့ ဘယ်နေရာကနေမဆို လှမ်းသုံးလို့ရပါတယ်။
ဥပမာ: const website = "Google"; (ဒါကို function ထဲကနေလည်း လှမ်းခေါ်လို့ ရပါတယ်)
(ခ) Function Scope (Local Scope)
Function တစ်ခုရဲ့ { } အတွင်းမှာ ကြေညာထားတဲ့ variable တွေပါ။
ထူးခြားချက်: အဲဒီ function အတွင်းမှာပဲ သုံးလို့ရပါတယ်။ Function အပြင်ဘက်ကနေ လှမ်းခေါ်ရင် Error တက်ပါလိမ့်မယ်။
var keyword နဲ့ ကြေညာရင် Function Scope ဖြစ်ပါတယ်။
(ဂ) Block Scope
if statement, for loop သို့မဟုတ် ရိုးရိုး curly braces { } အတွင်းမှာ ရှိတဲ့ နေရာပါ။
ထူးခြားချက်: let နဲ့ const ကို သုံးမှသာ Block Scope အလုပ်လုပ်ပါတယ်။ (အဲဒီ { } အပြင်ဘက်မှာ သုံးလို့မရပါ)
သတိထားရန်: var နဲ့ ကြေညာရင် block scope မရှိပါဘူး (Global သို့မဟုတ် Function scope ဆီကို ပေါက်ထွက်သွားပါလိမ့်မယ်)။
၂။ နှိုင်းယှဉ်ချက် ဥပမာ
// --- Global Scope ---
const user = "Aung Aung";
function sayHi() {
// --- Function Scope ---
const message = "Hello";
if (true) {
// --- Block Scope ---
const greeting = "Hi there";
var legacy = "I am everywhere"; // var သည် block scope ကို ဖောက်ထွက်နိုင်သည်
console.log(greeting); // အလုပ်လုပ်သည်
}
console.log(message); // အလုပ်လုပ်သည်
// console.log(greeting); // Error! (Block Scope အပြင်ဘက်ဖြစ်နေ၍)
console.log(legacy); // အလုပ်လုပ်သည် (var ဖြစ်သောကြောင့်)
}
sayHi();
// console.log(message); // Error! (Function Scope အပြင်ဘက်ဖြစ်နေ၍)
၃။ ဘာကြောင့် Scope က အရေးကြီးတာလဲ?
Security (လုံခြုံမှု): Variable တွေကို လိုအပ်တဲ့ နေရာမှာပဲ ထားခြင်းဖြင့် အခြား code တွေက မတော်တဆ
လာပြင်တာမျိုးကို တားဆီးနိုင်ပါတယ်။
Naming Collisions (နာမည်တူခြင်း): Scope မတူရင် variable နာမည်တူပေးလို့ ရပါတယ်။
(ဥပမာ- function A ထဲမှာလည်း x သုံး၊ function B ထဲမှာလည်း x သုံးလို့ ရတာမျိုး)
Memory Management: Function တစ်ခု အလုပ်ပြီးသွားရင် သူ့ထဲက Local variables တွေကို
memory ထဲကနေ ဖျက်ထုတ်ပေးတဲ့အတွက် memory သက်သာစေပါတယ်။
အနှစ်ချုပ်
Global Scope: လူတိုင်း မြင်နိုင်တဲ့ "လမ်းမပေါ်က ဆိုင်းဘုတ်" လိုမျိုးပါ။
Function Scope: အိမ်တစ်အိမ်ရဲ့ "ဧည့်ခန်း" လိုမျိုးပါ။ အိမ်ထဲဝင်မှ မြင်ရပါတယ်။
Block Scope: အိမ်ထဲကမှ "သေတ္တာအသေးလေး" ထဲ ထည့်ထားသလိုမျိုးပါ။ အဲဒီသေတ္တာကို ဖွင့်မှပဲ မြင်ရတာပါ။
Scope Chain ဆိုတာ JavaScript မှာ variable တစ်ခုကို ရှာဖွေတဲ့ "လှေကားထစ်" လိုမျိုး စနစ်တစ်ခု ဖြစ်ပါတယ်။
လက်ရှိရှိနေတဲ့ နေရာမှာ variable ကို ရှာလို့မတွေ့ရင် သူ့ရဲ့ အပြင်ဘက် (Parent Scope) ဆီကို အဆင့်ဆင့်
တက်ရှာသွားတဲ့ ဖြစ်စဉ်ကို ခေါ်တာပါ။
ဒီ concept ကို နားလည်ဖို့ Scopes အမျိုးအစားတွေကို အရင်သိထားဖို့ လိုပါတယ်။
၁။ Scopes အမျိုးအစား ၃ ခု
Global Scope: Code တစ်ခုလုံးရဲ့ အပြင်ဘက်ဆုံးနေရာ။ ဘယ်နေရာကမဆို လှမ်းသုံးလို့ရတယ်။
Function Scope: Function တစ်ခုအတွင်းမှာပဲ ရှိတဲ့နေရာ။
Block Scope: if သို့မဟုတ် for loop ရဲ့ { } brackets အတွင်းမှာပဲ ရှိတဲ့နေရာ (let နဲ့ const အတွက်သာ)။
၂။ Scope Chain ဘယ်လို အလုပ်လုပ်သလဲ?
JavaScript Engine က variable တစ်ခုကို တွေ့တဲ့အခါ အောက်ပါအစီအစဉ်အတိုင်း ရှာဖွေပါတယ်-
Local Scope: အရင်ဆုံး လက်ရှိ အလုပ်လုပ်နေတဲ့ နေရာ (Current Scope) မှာ ရှာပါတယ်။
Outer Scope: မတွေ့ရင် သူ့ကို ဝန်းရံထားတဲ့ အပြင်ဘက် Scope (Parent) ဆီကို သွားရှာပါတယ်။
Global Scope: အပြင်ဘက်အဆင့်ဆင့်မှာ ရှာရင်းနဲ့ နောက်ဆုံး Global Scope အထိ ရောက်သွားပါတယ်။
အဲဒီမှာမှ မတွေ့တော့ဘူးဆိုရင်တော့ ReferenceError ပြပါလိမ့်မယ်။
အရေးကြီးချက်: Scope Chain ဟာ အောက်ကနေ အပေါ်ကိုပဲ ရှာလို့ရပါတယ်။ အပေါ် (Global) ကနေ
အောက် (Local function) ထဲက variable ကို လှမ်းရှာလို့ မရပါဘူး။
၃။ Code ဥပမာဖြင့် ကြည့်ခြင်း
const globalVar = "Global";
function outerFunction() {
const outerVar = "Outer";
function innerFunction() {
const innerVar = "Inner";
console.log(innerVar); // ၁။ Local မှာတွေ့တယ် -> "Inner"
console.log(outerVar); // ၂။ Local မှာမတွေ့လို့ Parent (outerFunction) မှာသွားရှာတယ် -> "Outer"
console.log(globalVar); // ၃။ Parent မှာမတွေ့လို့ Global မှာသွားရှာတယ် -> "Global"
console.log(unknown); // ၄။ ဘယ်မှာမှမတွေ့လို့ -> ReferenceError
}
innerFunction();
}
outerFunction();
၄။ Lexical Scoping
Scope Chain ဟာ Lexical Scoping ပေါ်မှာ အခြေခံပါတယ်။ ဆိုလိုတာက variable တစ်ခုရဲ့ scope ကို
code ရေးကတည်းက (ဘယ်နေရာမှာ ရေးထားသလဲဆိုတာကို ကြည့်ပြီး) ဆုံးဖြတ်လိုက်တာပါ။ Function ကို
ဘယ်နေရာမှာ "ခေါ်သလဲ" ဆိုတာထက် ဘယ်နေရာမှာ "ရေးထားသလဲ" ဆိုတာက ပိုအရေးကြီးပါတယ်။
အကျဉ်းချုပ် (Analogy)
အိမ်တစ်အိမ်မှာ ပစ္စည်းတစ်ခု ရှာသလိုပါပဲ-
ကိုယ့်အခန်းထဲမှာ အရင်ရှာမယ် (Local Scope)။
မတွေ့ရင် ဧည့်ခန်းထဲထွက်ရှာမယ် (Outer Scope)။
မတွေ့ရင် အိမ်ရှေ့ကွင်းပြင်ထဲမှာ ထွက်ရှာမယ် (Global Scope)။
အပြင်မှာမှ မတွေ့ရင်တော့ အဲဒီပစ္စည်း မရှိဘူးလို့ သတ်မှတ်လိုက်တာပါပဲ။
JavaScript မှာ Lexical Scope (သို့မဟုတ် Static Scope) ဆိုသည်မှာ variable တစ်ခု၏
တည်ရှိမှုနယ်ပယ် (Scope) ကို ၎င်းအား code ရေးသားစဉ်က ထားရှိခဲ့သော နေရာ ပေါ်မူတည်၍
သတ်မှတ်ခြင်းကိုဆိုလိုပါသည်။
ရိုးရိုးရှင်းရှင်းပြောရရင် "Function တစ်ခုဟာ သူ့ရဲ့ အပြင်ဘက် (Parent) မှာရှိတဲ့ Variable တွေကို လှမ်းမြင်နိုင်တယ်"
ဆိုတာပါပဲ။
function outer() {
const name = "Aung Aung";
function inner() {
// inner function ထဲမှာ 'name' မရှိပေမဲ့
// သူ့ရဲ့ lexical parent ဖြစ်တဲ့ outer ဆီက variable ကို လှမ်းသုံးလို့ရတယ်
console.log(name);
}
inner();
}
outer(); // Output: Aung Aung
ဒီနေရာမှာ inner() function ကို outer() ရဲ့ အထဲမှာ ရေးထားတဲ့အတွက် inner ရဲ့ lexical environment
ထဲမှာ outer ရဲ့ variable တွေ ပါဝင်နေတာ ဖြစ်ပါတယ်။
အဓိက အချက်များ
အထဲကနေ အပြင်ကိုပဲ မြင်ရတယ်: Function အငယ်လေးတွေက သူတို့ကို ဝန်းရံထားတဲ့ အပြင်ဘက်
(Parent) scope တွေကို လှမ်းမြင်နိုင်ပေမဲ့၊ အပြင်ဘက်က function ကတော့ အထဲက function ထဲက variable
တွေကို လှမ်းမမြင်နိုင်ပါဘူး။
Static ဖြစ်တယ်: Function ကို ဘယ်နေရာမှာ "ခေါ်သလဲ" (Call-site) ဆိုတာက အရေးမကြီးပါဘူး။
ဘယ်နေရာမှာ "ကြေညာခဲ့သလဲ" (Definition-site) ဆိုတာကပဲ အရေးကြီးပါတယ်။
Lexical Scoping vs Dynamic Scoping
JavaScript ဟာ Lexical Scoping ကို သုံးပါတယ်။ တချို့ ဘာသာစကားတွေမှာ သုံးတဲ့ Dynamic Scoping နဲ့ မတူပါဘူး။
JavaScript
const x = 10;
function a() {
console.log(x);
}
function b() {
const x = 20;
a(); // x က ဘယ်လောက်ထွက်မလဲ?
}
b();
Lexical Scoping (JS): အဖြေက 10 ထွက်ပါမယ်။ ဘာလို့လဲဆိုတော့ a() ကို ကြေညာခဲ့တဲ့
နေရာရဲ့ အပြင်ဘက်မှာ x = 10 ပဲ ရှိလို့ပါ။
Dynamic Scoping: အဖြေက 20 ထွက်ပါလိမ့်မယ် (ဘာလို့လဲဆိုတော့ a() ကို ခေါ်လိုက်တဲ့ နေရာမှာ x က 20 ဖြစ်နေလို့ပါ)။
ဒါပေမဲ့ JS က ဒါမျိုး အလုပ်မလုပ်ပါဘူး။
Lexical Scoping ကို "မျိုးရိုးဗီဇ" လို မှတ်သားနိုင်ပါတယ်။ သင်ဟာ သင့်မိဘတွေဆီက အမွေ (Variables) တွေကို ရပိုင်ခွင့်ရှိပါတယ်။
သင် ဘယ်မြို့ကိုပဲ ရောက်သွားရောက်သွား (Function ကို ဘယ်မှာပဲ ခေါ်ခေါ်)၊ သင့်ရဲ့ မိဘက ဘယ်သူလဲဆိုတာ (Lexical Parent) မပြောင်းလဲတဲ့အတွက် အဲဒီအမွေတွေကို သင် ဆက်ပြီး သုံးစွဲခွင့် ရှိနေမှာ ဖြစ်ပါတယ်။
JavaScript မှာ Closure ဆိုတာက Function တစ်ခုဟာ သူ့ရဲ့အပြင်ဘက် scope (outer function scope)
က variable တွေကို သူကိုယ်တိုင်ပြီးဆုံးသွားရင်တောင် မှတ်မိနေပြီး ပြန်သုံးနိုင်တဲ့ စွမ်းရည် ကို ခေါ်တာဖြစ်ပါတယ်.
ရိုးရှင်းရှင်း ပြောရရင် "Function တစ်ခုက သူ့ကို ဖန်တီးခဲ့တဲ့ ပတ်ဝန်းကျင် (Outer Scope) မှာရှိတဲ့ Variable တွေကို အမြဲတမ်း မှတ်မိနေခြင်း" ကို ခေါ်တာပါ။
ပုံမှန်အားဖြင့် Function တစ်ခုက အလုပ်လုပ်ပြီးသွားရင် သူ့ထဲက variable တွေဟာ memory ထဲကနေ ပျောက်သွားရမှာပါ။
ဒါပေမဲ့ Closure ကြောင့် အဲဒီ variable တွေကို ဆက်ပြီး သိမ်းထားနိုင်တာ ဖြစ်ပါတယ်။
၁။ Closure ဘယ်လို ဖြစ်ပေါ်လာသလဲ?
Function တစ်ခုအတွင်းမှာ နောက်ထပ် Function တစ်ခု (Inner Function) ကို ထပ်ရေးပြီး အဲဒီ Inner function ကို
အပြင်ကို return ပြန်ထုတ်လိုက်တဲ့အခါ Closure ဖြစ်ပေါ်လာပါတယ်။
function outerFunction() {
let outerVariable = "I am outside!";
function innerFunction() {
console.log(outerVariable); // innerFunction က outerVariable ကို သုံးနေတယ်
}
return innerFunction; // function ကိုပြန်ထုတ်လိုက်တယ်
}
const myClosure = outerFunction();
myClosure(); // Output: "I am outside!"
ဘာဖြစ်သွားတာလဲ?
outerFunction() အလုပ်လုပ်ပြီးဆုံးသွားပေမယ့် myClosure() ကို ခေါ်လိုက်တဲ့အချိန်မှာ outerVariable ရဲ့ တန်ဖိုးကို ဆက်မှတ်မိနေဆဲဖြစ်ပါတယ်.
အလုပ်လုပ်ပုံ အဆင့်ဆင့် (Execution Context အရ)
Creation: outerFunction ကို ခေါ်လိုက်တဲ့အခါ သူ့အတွက် Memory နေရာတစ်ခု ရလာပါတယ်။
Returning: သူက innerFunction ကို ပြန်ပေးလိုက်တဲ့အခါ အဲဒီ inner function နဲ့အတူ သူ့ရဲ့
Scope Chain ပါ ပါသွားပါတယ်။
Persistence: Closure က count variable ကို Garbage Collector ကနေ မဖျက်ပစ်အောင်
တားဆီးထားလိုက်ပါတယ်။ ဒါကြောင့် counter() ကို ခေါ်တိုင်း count တန်ဖိုးက ဆက်ရှိနေတာပါ။
၄။ သတိထားရန်အချက်
Closures တွေက variable တွေကို memory ထဲမှာ ဆက်သိမ်းထားတဲ့အတွက် အသုံးမလိုဘဲ အများကြီး
သုံးရင် Memory Leak (Memory နေရာလွတ် မကျန်တော့ခြင်း) ဖြစ်တတ်ပါတယ်။ အလုပ်ပြီးသွားရင် reference
ကို null ပြန်လုပ်ပေးဖို့ လိုအပ်ရင် လိုအပ်ပါလိမ့်မယ်။
အနှစ်ချုပ် (Analogy)
Closure ဆိုတာ "ကျောပိုးအိတ်" နဲ့ တူပါတယ်။ Function က တစ်နေရာကို ခရီးထွက်သွားတဲ့အခါ
(Return ပြန်တဲ့အခါ) သူ့အိမ်မှာရှိတဲ့ ပစ္စည်းတွေကို ကျောပိုးအိတ်ထဲ ထည့်ယူသွားသလိုပါပဲ။ အဲဒီ ပစ္စည်းတွေ
(Variables) ကို သူရောက်တဲ့နေရာတိုင်းမှာ ပြန်ထုတ်သုံးလို့ ရနေတာမျိုး ဖြစ်ပါတယ်။