Skip to content
← All Skills
🟡

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

bash
# 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 กลุ่มหลัก:

  • Primitivesstring, number, boolean, null, undefined, bigint, symbol
  • Objectsobject, array, function

สิ่งที่ต้องระวังคือ type coercion — JavaScript จะแปลง type ให้อัตโนมัติเมื่อเปรียบเทียบด้วย == ดังนั้นใช้ === เสมอเพื่อเปรียบเทียบทั้ง type และ value

Functions

JavaScript มีหลายวิธีเขียน function:

  • Arrow functionconst add = (a, b) => a + b สั้น กระชับ ไม่มี this ของตัวเอง
  • Function declarationfunction add(a, b) มี hoisting (ใช้ก่อนประกาศได้)
  • Closures — function ที่จำตัวแปรของ scope ที่สร้างมัน ใช้สำหรับ data privacy
  • IIFE(function() ...)() run ทันที ใช้สร้าง scope แยก

Object & Destructuring

เทคนิคจัดการ objects ที่ใช้ทุกวัน:

  • Shorthand{ name, age } แทน { name: name, age: age }
  • Destructuringconst { name, age } = user ดึง property ออกมาเป็นตัวแปร
  • Spread{ ...obj, newProp: val } copy + merge object
  • Optional chaininguser?.address?.city ไม่ error ถ้า property ไม่มี
  • Nullish coalescingval ?? 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:

  • Ternarycondition ? valueA : valueB เลือกค่าตามเงื่อนไข
  • Logical ANDisReady && doSomething() ทำเมื่อ true
  • Logical ORvalue || "default" ใช้ default ถ้า value เป็น falsy
  • Nullish coalescingvalue ?? "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
  • Restconst [first, ...rest] = arr ดึงตัวแรก เก็บที่เหลือใน rest
  • ใช้ได้กับ function parameters: function sum(...nums) รับ arguments กี่ตัวก็ได้

JSON

JSON ใช้แปลงข้อมูลระหว่าง JavaScript objects กับ strings — ใช้ทุกวันกับ API:

  • JSON.parse(str) — แปลง JSON string เป็น object
  • JSON.stringify(obj) — แปลง object เป็น JSON string
  • JSON.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 เสมอ ไม่ว่าจะสำเร็จหรือ error
  • Promise.all([...]) — รอทุกตัวเสร็จ (parallel)
  • Promise.allSettled([...]) — รอทุกตัว ไม่ว่าจะสำเร็จหรือ fail

Async / Await

วิธีเขียน async code ที่อ่านง่ายที่สุด — เหมือนเขียน code ปกติแต่รอผลลัพธ์ได้:

  • async function บอกว่า function นี้ return Promise
  • await รอ 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 queuesetTimeout, setInterval (ทำทีหลัง)

เมื่อ call stack ว่าง event loop จะหยิบ microtasks มา run ก่อน แล้วค่อย macrotasks

Concepts สำคัญ

this Keyword

this ใน JavaScript เปลี่ยนไปตามวิธีเรียก function:

  • Method call (obj.fn()) — this = object นั้น
  • Regular functionthis = 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 เรียก parent
  • static methods, #private fields (ES2022)

Modules

วิธีแบ่ง code เป็นไฟล์แยก:

  • ES Modules (ESM)import / export เป็น standard ใหม่ รองรับ tree shaking
  • CommonJSrequire / module.exports ใช้ใน Node.js เดิม
  • Node.js ใช้ ESM ได้ด้วย "type": "module" ใน package.json

Error Handling

  • try / catch / finally — จับ errors ทั้ง sync และจาก await
  • throw 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
  • Generatorfunction* + 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 Promise
  • querySelector / addEventListener — จัดการ DOM
  • localStorage / sessionStorage — เก็บข้อมูลฝั่ง client
  • IntersectionObserver — ตรวจจับ 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 แทน varlet เป็น 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