JavaScript
ภาษาพื้นฐานของ web — async programming, DOM, runtime concepts ทั้ง browser และ Node.js
What I Can Do
- เขียน modern JavaScript (ES2015+) สำหรับทั้ง frontend และ backend
- จัดการ asynchronous code ด้วย Promise, async/await
- เข้าใจ JavaScript runtime — event loop, call stack, memory management
- Debug performance issues ด้วย browser DevTools และ Node.js profiler
- ใช้ JavaScript ecosystem — npm, bundlers, transpilers
Commands I Use Daily
# run script ด้วย Node.js
node src/index.js
# run ด้วย watch mode (Node 18+)
node --watch src/index.js
# REPL สำหรับทดสอบ code
node
# จัดการ packages
npm install
npm run dev
npm run build
# ดู outdated packages
npm outdated
# debug ด้วย Chrome DevTools
node --inspect src/index.jsพื้นฐาน
Variables & Scope
ตัวแปรใน JavaScript มี 3 แบบ:
const— ค่าไม่เปลี่ยน (ใช้เป็น default)let— ค่าเปลี่ยนได้var— หลีกเลี่ยง เพราะ scope ไม่ชัดเจน
let กับ const เป็น block scope (อยู่แค่ใน {} ที่ประกาศ) ส่วน var เป็น function scope ถึงแม้ประกาศใน if ก็เข้าถึงได้ข้างนอก
Data Types
JavaScript มี 2 กลุ่มหลัก:
- Primitives —
string,number,boolean,null,undefined,bigint,symbol - Objects —
object,array,function
สิ่งที่ต้องระวังคือ type coercion — JavaScript จะแปลง type ให้อัตโนมัติเมื่อเปรียบเทียบด้วย == ดังนั้นใช้ === เสมอเพื่อเปรียบเทียบทั้ง type และ value
Functions
JavaScript มีหลายวิธีเขียน function:
- Arrow function —
const add = (a, b) => a + bสั้น กระชับ ไม่มีthisของตัวเอง - Function declaration —
function add(a, b)มี hoisting (ใช้ก่อนประกาศได้) - Closures — function ที่จำตัวแปรของ scope ที่สร้างมัน ใช้สำหรับ data privacy
- IIFE —
(function() ...)()run ทันที ใช้สร้าง scope แยก
Object & Destructuring
เทคนิคจัดการ objects ที่ใช้ทุกวัน:
- Shorthand —
{ name, age }แทน{ name: name, age: age } - Destructuring —
const { name, age } = userดึง property ออกมาเป็นตัวแปร - Spread —
{ ...obj, newProp: val }copy + merge object - Optional chaining —
user?.address?.cityไม่ error ถ้า property ไม่มี - Nullish coalescing —
val ?? defaultใช้ default เมื่อค่าเป็นnullหรือundefined
Loops
JavaScript มีหลายแบบ loop:
for...of— วน values ใน array, string, Map, Set เช่นfor (const item of items)for...in— วน keys ของ object (ระวัง: วน prototype chain ด้วย)for— loop แบบคลาสสิกfor (let i = 0; i < n; i++)while/do...while— loop ตามเงื่อนไข
ส่วนใหญ่ใช้ for...of หรือ array methods แทน for loop ธรรมดา
Ternary & Short-circuit
เทคนิค conditional ที่ใช้เยอะมากใน React/JSX:
- Ternary —
condition ? valueA : valueBเลือกค่าตามเงื่อนไข - Logical AND —
isReady && doSomething()ทำเมื่อ true - Logical OR —
value || "default"ใช้ default ถ้า value เป็น falsy - Nullish coalescing —
value ?? "default"ใช้ default เฉพาะเมื่อเป็นnull/undefined(ดีกว่า||เพราะ0กับ""ไม่นับเป็น nullish)
Array Methods
Methods ที่ใช้แทน for loop — ไม่ mutate array เดิม:
map— แปลงทุก element เช่นusers.map(u => u.name)filter— กรองเอาเฉพาะที่ตรงเงื่อนไขfind— หา element แรกที่ตรงreduce— รวม array เป็นค่าเดียวsome/every— ตรวจว่ามีบ้าง / ทุกตัวตรงไหมflat/flatMap— ยุบ nested arrays
ใช้ forEach เฉพาะเมื่อต้องการ side effects เท่านั้น
Spread & Rest (Arrays)
- Spread —
[...arr1, ...arr2]รวม arrays,[...arr]copy array - Rest —
const [first, ...rest] = arrดึงตัวแรก เก็บที่เหลือในrest - ใช้ได้กับ function parameters:
function sum(...nums)รับ arguments กี่ตัวก็ได้
JSON
JSON ใช้แปลงข้อมูลระหว่าง JavaScript objects กับ strings — ใช้ทุกวันกับ API:
JSON.parse(str)— แปลง JSON string เป็น objectJSON.stringify(obj)— แปลง object เป็น JSON stringJSON.stringify(obj, null, 2)— format ให้อ่านง่าย (เว้น 2 spaces)- ระวัง:
undefined, functions,Symbolจะหายไปเมื่อ stringify
Template Literals
ใช้ backtick สร้าง string ที่มี expression ข้างใน:
- รองรับ multiline ไม่ต้อง
\n - ใส่ตัวแปรได้ด้วย dollar + curly braces
- String methods ที่ใช้บ่อย:
includes,startsWith,endsWith,padStart,repeat
Async Programming
Promises
Promise คือ object ที่เป็นตัวแทนของ "ค่าที่จะมีในอนาคต" — ใช้จัดการ async operations:
.then()— เมื่อสำเร็จ.catch()— เมื่อ error.finally()— run เสมอ ไม่ว่าจะสำเร็จหรือ errorPromise.all([...])— รอทุกตัวเสร็จ (parallel)Promise.allSettled([...])— รอทุกตัว ไม่ว่าจะสำเร็จหรือ fail
Async / Await
วิธีเขียน async code ที่อ่านง่ายที่สุด — เหมือนเขียน code ปกติแต่รอผลลัพธ์ได้:
async functionบอกว่า function นี้ return Promiseawaitรอ Promise resolve แล้วได้ค่ากลับมา- ใช้
try/catchจัดการ errors แทน.catch() await Promise.all([...])สำหรับ run หลาย async tasks พร้อมกัน
Event Loop
JavaScript เป็น single-threaded — มี thread เดียว แต่รองรับ concurrency ผ่าน event loop:
- Call stack — ที่ run code ปัจจุบัน (ทีละอัน)
- Microtask queue — Promise callbacks (ทำก่อน)
- Macrotask queue —
setTimeout,setInterval(ทำทีหลัง)
เมื่อ call stack ว่าง event loop จะหยิบ microtasks มา run ก่อน แล้วค่อย macrotasks
Concepts สำคัญ
this Keyword
this ใน JavaScript เปลี่ยนไปตามวิธีเรียก function:
- Method call (
obj.fn()) —this= object นั้น - Regular function —
this=undefined(strict mode) - Arrow function — ไม่มี
thisของตัวเอง ใช้thisของ scope ข้างนอก - bind / call / apply — กำหนด
thisเองได้
Prototypes & Classes
ทุก object ใน JavaScript มี prototype chain — เวลาเรียก property ถ้าไม่เจอจะไล่หาขึ้นไปตาม chain
- Classes (ES2015) — syntax ที่อ่านง่ายกว่า แต่ทำงานบน prototypes เหมือนเดิม
extendsสำหรับ inheritance,superเรียก parentstaticmethods,#privatefields (ES2022)
Modules
วิธีแบ่ง code เป็นไฟล์แยก:
- ES Modules (ESM) —
import/exportเป็น standard ใหม่ รองรับ tree shaking - CommonJS —
require/module.exportsใช้ใน Node.js เดิม - Node.js ใช้ ESM ได้ด้วย
"type": "module"ใน package.json
Error Handling
try / catch / finally— จับ errors ทั้ง sync และจากawaitthrow new Error("msg")— สร้าง error เอง- สร้าง custom error class ด้วย
extends Errorสำหรับ error ที่เฉพาะเจาะจง
Data Structures
Map & Set
- Map — เก็บ key-value pairs, keys เป็น type อะไรก็ได้ (object ธรรมดา keys เป็นแค่ string)
- Set — เก็บค่าที่ไม่ซ้ำกัน
- WeakMap / WeakSet — keys เป็น objects เท่านั้น, ไม่กัน garbage collection
Iterators & Generators
- Iterator — object ที่มี
next()method return ค่าทีละตัว ใช้กับfor...of - Generator —
function*+yieldสร้าง values แบบ lazy (ไม่สร้างทั้งหมดพร้อมกัน)
Advanced
Proxy & Reflect
- Proxy — ดัก operations บน object (get, set, delete) ใช้สร้าง reactive systems, validation
- Reflect — API มาตรฐานสำหรับ object operations ใช้คู่กับ Proxy
- Vue 3 ใช้ Proxy เป็นหัวใจของ reactivity system
Web APIs ที่ใช้บ่อย
fetch()— ส่ง HTTP requests, return PromisequerySelector/addEventListener— จัดการ DOMlocalStorage/sessionStorage— เก็บข้อมูลฝั่ง clientIntersectionObserver— ตรวจจับ element เข้า/ออก viewport (ดีกว่า scroll event)
Regular Expressions
/pattern/flags สำหรับ text matching — test() ตรวจว่า match ไหม, match() ดึงค่า, replace() แทนที่ flags ที่ใช้บ่อย: g (ทุกตัว), i (ไม่สนตัวเล็กใหญ่), m (multiline)
Memory & Performance
- JavaScript ใช้ garbage collection อัตโนมัติ — ระวัง memory leaks จาก event listeners ที่ไม่ remove, closures ที่ hold references
- Debounce / Throttle — ลดความถี่ของ event handlers
- Web Workers — run code หนักๆ แยก thread ไม่บล็อก UI
- requestAnimationFrame — animate ได้ smooth ที่ 60fps
ปัญหาที่เจอบ่อย & วิธีแก้
Cannot read properties of undefined
ปัญหาอันดับ 1 ของ JavaScript — พยายาม access property ของค่าที่เป็น undefined หรือ null
สาเหตุ: API return ข้อมูลไม่ครบ, object ยังไม่ถูก initialize, typo ในชื่อ property
วิธีแก้:
- ใช้ optional chaining:
user?.address?.cityแทนuser.address.city - ตรวจก่อนใช้:
if (user && user.address)หรือสั้นกว่าif (user?.address) - ตั้ง default value:
const city = user?.address?.city ?? "Unknown" - ถ้าเป็น array:
items?.length > 0ก่อน map
undefined is not a function
พยายามเรียก function ที่ไม่มีอยู่จริง
สาเหตุ: typo ในชื่อ function, import ผิด, method ไม่มีใน type นั้น, callback เป็น undefined
วิธีแก้:
- ตรวจ import ว่าถูกไหม — named export ต้อง destructure
import { fn } from ... - ตรวจว่า method มีจริง —
console.log(typeof obj.method)ก่อนเรียก - ใช้ optional call:
callback?.()ถ้า callback อาจจะไม่มี
this เป็น undefined
this หายเมื่อส่ง method เป็น callback
สาเหตุ: เอา method ไป pass เป็น callback เช่น setTimeout(obj.method, 100) — this จะหลุด
วิธีแก้:
- ใช้ arrow function:
setTimeout(() => obj.method(), 100)— arrow function ไม่มี this ของตัวเอง - ใช้
bind:setTimeout(obj.method.bind(obj), 100) - ใน class ใช้ arrow function เป็น property แทน method
Unhandled Promise Rejection
async operation fail แต่ไม่มีใครจัดการ error
สาเหตุ: ลืม catch, ลืม try/catch ครอบ await, Promise chain ไม่มี .catch() ตอนท้าย
วิธีแก้:
awaitต้องอยู่ในtry/catchเสมอ- Promise chain ต้องมี
.catch()ตอนท้าย - เพิ่ม global handler:
window.addEventListener("unhandledrejection", handler)สำหรับจับ errors ที่หลุด
Shallow Copy ทำให้ข้อมูลเปลี่ยน
Spread ... copy แค่ชั้นแรก — nested objects ยังอ้างอิงตัวเดิม
สาเหตุ: const copy = { ...original } แล้วแก้ copy.nested.value — original เปลี่ยนด้วย
วิธีแก้:
- ใช้
structuredClone(obj)สำหรับ deep copy (modern browsers + Node 17+) - ถ้า data ไม่ซับซ้อน:
JSON.parse(JSON.stringify(obj))(ข้อจำกัด: ไม่รองรับ functions, Date, undefined) - ที่ดีที่สุด: ใช้ immutable update pattern — สร้าง object ใหม่ทุกชั้นที่แก้
Event Listener Memory Leak
เพิ่ม listener แต่ไม่ remove — ทำให้ memory โตเรื่อยๆ
สาเหตุ: addEventListener ใน component ที่ mount/unmount บ่อย โดยไม่ cleanup
วิธีแก้:
- ใน React: return cleanup function จาก
useEffect - ใน vanilla JS: เก็บ reference แล้ว
removeEventListenerเมื่อไม่ใช้ - ใช้
AbortController— สร้าง controller แล้วส่งsignalไปกับaddEventListenerเมื่อจะ cleanup เรียกcontroller.abort()ลบทุก listener ที่ผูกกับ signal นั้น
Loop + Closure ได้ค่าผิด
ใช้ var ใน loop แล้วค่าใน callback เป็นค่าสุดท้ายทุกตัว
สาเหตุ: var เป็น function scope — ทุก iteration share ตัวแปรเดียวกัน
วิธีแก้:
- ใช้
letแทนvar—letเป็น block scope แต่ละ iteration ได้ตัวแปรแยก - กฎง่ายๆ: ไม่ใช้
varเลย ใช้constเป็น default,letเมื่อต้องเปลี่ยนค่า
== vs === ได้ผลไม่ตรง
== ทำ type coercion ก่อนเปรียบเทียบ ผลลัพธ์คาดเดายาก
ตัวอย่างที่พลาดบ่อย:
0 == ""ได้true(ทั้งสองถูกแปลงเป็น 0)null == undefinedได้true(กฎพิเศษ)[] == falseได้true(array ถูกแปลงเป็น string เป็น number)
วิธีแก้: ใช้ === เสมอ — เปรียบเทียบทั้ง type และ value ไม่มี coercion
Related Skills
- TypeScript — type-safe superset ของ JavaScript
- Next.js — React framework ที่ build บน JavaScript/TypeScript
- Node.js — JavaScript runtime สำหรับ backend