สรุปสั้น

  • ใช้ const เป็นค่าเริ่มต้น ใช้ let เมื่อต้องเปลี่ยนค่า เลิกใช้ var
  • เปรียบเทียบด้วย === เสมอ
  • object/array ถูกส่งต่อแบบ อ้างอิง (reference) แก้ตัวหนึ่ง อีกตัวเปลี่ยนตาม
  • งานที่ต้องรอ (เรียก API, อ่านไฟล์) ใช้ async/await และครอบด้วย try/catch
  • ถ้าต้องดึงข้อมูลจากฐานข้อมูลฝั่ง backend ดูต่อที่ พื้นฐาน PHP และ พื้นฐาน SQL

1. ตัวแปร: const, let, var

const name = "Somchai"   // เปลี่ยนค่าไม่ได้ (แต่ของข้างใน object ยังแก้ได้)
let count = 0            // เปลี่ยนค่าได้
count++
 
const user = { age: 20 }
user.age = 21            // ได้ เพราะไม่ได้เปลี่ยนตัวแปร user แค่แก้ของข้างใน
ขอบเขต (scope)ประกาศซ้ำใช้ก่อนประกาศ
varทั้งฟังก์ชันได้ได้ค่า undefined (hoisting)
let / constภายใน { }ไม่ได้error (Temporal Dead Zone)

อย่าใช้ var ในโค้ดใหม่

var มองข้ามขอบเขตของ { } ทำให้เกิดบั๊กแปลก ๆ โดยเฉพาะใน loop

2. ชนิดข้อมูลและการเปรียบเทียบ

ชนิดพื้นฐาน (primitive): string, number, bigint, boolean, undefined, null, symbol
นอกนั้นเป็น object ทั้งหมด (รวม array และ function)

typeof "hi"        // "string"
typeof 42          // "number"
typeof null        // "object"  ← บั๊กเก่าของภาษา จำไว้
typeof []          // "object"  → เช็ก array ด้วย Array.isArray([])

== กับ ===

0 == ""        // true   ← แปลงชนิดให้ก่อนเทียบ งง
0 === ""       // false  ← เทียบทั้งค่าและชนิด
null == undefined   // true
null === undefined  // false

ใช้ === และ !== เสมอ

ค่าที่ถือว่า “เท็จ” (falsy)

false, 0, "", null, undefined, NaN นอกนั้นถือว่า “จริง” ทั้งหมด รวมถึง [] และ {}

?. และ ??

const city = user?.address?.city      // ไม่ error ถ้า address ไม่มี ได้ undefined
const limit = input ?? 10             // ใช้ 10 เฉพาะเมื่อ input เป็น null/undefined
const limit2 = input || 10            // ใช้ 10 เมื่อ input เป็น falsy ทุกแบบ (รวม 0!)

3. ฟังก์ชัน

function add(a, b) { return a + b }          // function declaration
const add2 = (a, b) => a + b                 // arrow function
const greet = (name = "เพื่อน") => `สวัสดี ${name}`   // ค่าเริ่มต้น + template string

this ใน arrow function

arrow function ไม่มี this ของตัวเอง มันใช้ this ของที่ที่มันถูกเขียนไว้ เหมาะกับ callback แต่ไม่เหมาะเป็น method ของ object

Closure: ฟังก์ชันจำตัวแปรรอบตัวได้

function makeCounter() {
  let count = 0
  return () => ++count
}
const next = makeCounter()
next() // 1
next() // 2  ← count ยังอยู่ แม้ makeCounter จบไปแล้ว

4. Object และ Array

Destructuring และ Spread

const { name, age = 18 } = user           // ดึง property ออกมาเป็นตัวแปร
const [first, ...rest] = [1, 2, 3]        // first = 1, rest = [2, 3]
 
const updated = { ...user, age: 30 }      // copy แล้วแก้บาง field
const merged = [...arr1, ...arr2]

Method ของ array ที่ใช้บ่อยที่สุด

const prices = [100, 250, 80]
 
prices.map(p => p * 1.07)              // แปลงทุกตัว → array ใหม่
prices.filter(p => p > 90)             // กรอง → array ใหม่
prices.reduce((sum, p) => sum + p, 0)  // รวมเป็นค่าเดียว → 430
prices.find(p => p > 90)               // ตัวแรกที่ตรง → 100
prices.some(p => p > 200)              // มีสักตัวไหม → true
prices.includes(80)                    // มีค่านี้ไหม → true

map, filter ไม่แก้ array เดิม แต่ sort, push, splice แก้ของเดิม ถ้าไม่อยากให้เดิมเปลี่ยน ใช้ toSorted() แทน sort()

Reference: กับดักอันดับหนึ่ง

const a = { score: 1 }
const b = a          // b ชี้ไปที่ object เดียวกัน ไม่ได้ copy
b.score = 99
a.score              // 99 !
 
const shallow = { ...a }            // copy แค่ชั้นแรก
const deep = structuredClone(a)     // copy ทุกชั้น

5. Asynchronous: Promise และ async/await

JavaScript ทำงานทีละคำสั่ง (single thread) งานที่ต้องรอ เช่น เรียก API จะถูกฝากไว้ แล้วกลับมาทำต่อเมื่อเสร็จ ผ่านกลไกที่เรียกว่า event loop

async function loadUser(id) {
  try {
    const res = await fetch(`/api/users/${id}`)
    if (!res.ok) throw new Error(`HTTP ${res.status}`)
    return await res.json()
  } catch (err) {
    console.error("โหลดผู้ใช้ไม่สำเร็จ", err)
    return null
  }
}

ทำหลายงานพร้อมกัน แทนที่จะรอทีละอัน:

const [user, orders] = await Promise.all([loadUser(1), loadOrders(1)])

fetch ไม่ throw เมื่อได้ 404 หรือ 500

ต้องเช็ก res.ok เอง ไม่อย่างนั้นจะได้ข้อมูล error ไปใช้ต่อแบบไม่รู้ตัว

6. Module: import / export

// math.js
export const add = (a, b) => a + b
export default function multiply(a, b) { return a * b }
 
// app.js
import multiply, { add } from "./math.js"

7. DOM และ Event (ฝั่งเบราว์เซอร์)

const button = document.querySelector("#save")
button.addEventListener("click", (event) => {
  event.preventDefault()
  document.querySelector("#status").textContent = "บันทึกแล้ว"
})

ใช้ textContent เมื่อแสดงข้อความจากผู้ใช้ อย่าใช้ innerHTML กับข้อมูลที่ผู้ใช้กรอก เพราะเปิดช่องให้ฝังสคริปต์ (XSS)

จุดที่มักพลาด

  • 0.1 + 0.2 === 0.3 เป็น false เพราะทศนิยมแบบ floating point → เรื่องเงินให้เก็บเป็นหน่วยสตางค์ (จำนวนเต็ม)
  • NaN === NaN เป็น false → เช็กด้วย Number.isNaN(x)
  • ลืม await ได้ Promise แทนข้อมูลจริง
  • parseInt("08") ได้ 8 แต่ parseInt("1,000") ได้ 1 → ลบ , ก่อนแปลง
  • [10, 9, 1].sort() ได้ [1, 10, 9] เพราะเรียงแบบข้อความ → ใช้ .sort((a, b) => a - b)

แหล่งอ้างอิง