บทนำ JavaScript
JavaScript เป็นภาษาโปรแกรมมิ่งที่ทำงานบนเบราว์เซอร์ (และบน servers ด้วย Node.js) ใช้สำหรับสร้าง interactivity, การประมวลผลข้อมูล, validation forms, และการสร้าง web applications ที่ซับซ้อน รวมกับ HTML (โครงสร้าง) และ CSS (ออกแบบ) ทำให้เว็บไซต์เต็มไปด้วยชีวิต
JavaScript คืออะไร
ความหมาย
- ภาษาโปรแกรมมิ่ง - มี logic, loops, conditions
- Client-side scripting - ทำงานบนเบราว์เซอร์ของผู้ใช้
- Interpreted language - ไม่ต้อง compile
- Dynamic typing - ประเภทข้อมูลเปลี่ยนแปลงได้
ใช้สำหรับ
- ✅ Interactivity (ตัวอบสนอง)
- ✅ Validation forms
- ✅ Animation
- ✅ API calls (Fetch data)
- ✅ Real-time updates
- ✅ Web applications
- ✅ Backend servers (Node.js)
วิธีใช้ JavaScript
1. Inline JavaScript
<button onclick="alert('Hello!')">Click me</button>
2. Internal JavaScript
<head>
<script>
console.log("Hello from JavaScript");
</script>
</head>
3. External JavaScript (แนะนำ)
<script src="script.js" defer></script>
Data Types
JavaScript มี 2 หมวดหมู่หลักของประเภทข้อมูล: Primitive Types (ข้อมูลพื้นฐาน) และ Reference Types (ข้อมูลอ้างอิง) แต่ละประเภทมีคุณสมบัติและการใช้งานที่แตกต่างกัน
1. Primitive Types (ข้อมูลพื้นฐาน)
Primitive types คือ ข้อมูลพื้นฐานที่เก็บค่าโดยตรง เมื่อเปรียบเทียบจะเปรียบเทียบค่า:
String - ข้อความ
// String - ข้อความใดๆ
let name = "John";
let city = 'Bangkok';
let message = `Hello, ${name}`; // Template literals (backticks)
// Template literals ช่วยให้งานง่าย
const greeting = `Hi, I'm ${name} from ${city}`;
// String methods
name.length; // 4
name.toUpperCase(); // "JOHN"
name.toLowerCase(); // "john"
name.includes("oh"); // true
name.slice(0, 2); // "Jo"
Number - ตัวเลข
// Number - ตัวเลขทั้ง integer และ decimal
let age = 25; // Integer
let price = 99.99; // Decimal (Float)
let negative = -50; // Negative
let infinity = Infinity; // Special value
// Math operations
age + 5; // 30
price * 2; // 199.98
Math.round(99.5); // 100
Math.max(10, 20, 5); // 20
Math.random(); // 0-1 random number
Boolean - จริง/เท็จ
// Boolean - true หรือ false เท่านั้น
let isActive = true;
let isDeleted = false;
// ใช้กับ conditions
if (isActive) {
console.log("User is active");
}
// Comparison ให้ boolean
10 > 5; // true
"hello" === "hello"; // true
age < 18; // false
Null & Undefined - ค่าว่าง
// Null - ค่าว่างที่ intentional (ตั้งใจ)
let x = null; // assigned null
// Undefined - ค่าว่างอัตโนมัติ (ไม่ได้ assign)
let y; // undefined
let z = undefined; // explicit undefined
// Difference
const empty = null; // intentionally empty
const notAssigned = undefined; // not yet assigned
// Check for null/undefined
if (x === null) { } // Check null
if (y === undefined) { } // Check undefined
2. Reference Types (ข้อมูลอ้างอิง)
Reference types คือ ข้อมูลที่เก็บเป็นการอ้างอิง เมื่อเปรียบเทียบจะเปรียบเทียบ reference ไม่ใช่ค่า:
Object - วัตถุข้อมูล
// Object - collection ของ key-value pairs
const person = {
name: "John",
age: 25,
city: "Bangkok",
isActive: true,
// Method ในส่วนของ object
greet() {
console.log(`Hello, I'm ${this.name}`);
}
};
// Access properties
person.name; // "John"
person["age"]; // 25
// Modify properties
person.age = 26;
person.email = "john@example.com"; // Add new property
// Object methods
Object.keys(person); // ["name", "age", "city", ...]
Object.values(person); // ["John", 26, "Bangkok", ...]
Object.entries(person); // [["name", "John"], ["age", 26], ...]
Array - ลิสต์ข้อมูล
// Array - collection ของข้อมูล (ต่อเนื่องกัน)
let fruits = ["Apple", "Banana", "Orange"];
let numbers = [1, 2, 3, 4, 5];
let mixed = ["John", 25, true, null]; // Can mix types
// Access elements (0-indexed)
fruits[0]; // "Apple"
fruits[1]; // "Banana"
fruits.length; // 3
// Array methods
fruits.push("Mango"); // Add to end
fruits.pop(); // Remove from end
fruits.shift(); // Remove from start
fruits.unshift("Grape"); // Add to start
fruits.includes("Apple"); // true
fruits.indexOf("Banana"); // 1
Function - ฟังก์ชัน
// Function - โค้ดที่นำมาใช้ใหม่ได้
const add = (a, b) => a + b; // Arrow function
const multiply = (a, b) => a * b; // Arrow function
// Function declaration
function subtract(a, b) {
return a - b;
}
// Call/invoke function
add(5, 3); // 8
multiply(4, 2); // 8
subtract(10, 3); // 7
📊 Primitive vs Reference Comparison
| ลักษณะ | Primitive Types | Reference Types |
|---|---|---|
| ประเภท | String, Number, Boolean, Null, Undefined | Object, Array, Function |
| การเก็บข้อมูล | เก็บค่าโดยตรง | เก็บ reference (address) |
| การเปรียบเทียบ | เปรียบเทียบค่า | เปรียบเทียบ reference ไม่ใช่ค่า |
| Example | 5 === 5 → true | {} === {} → false (ต่าง reference) |
| Assignment | Copy ค่า | Copy reference ไม่ใช่ค่า |
Variables - ตัวแปร
ตัวแปร คือ ที่เก็บข้อมูล ใน JavaScript มี 3 วิธีสำหรับประกาศตัวแปร: const, let, และ var แต่ละวิธีมีข้อดีข้อเสียต่างกัน
1. const (แนะนำ - ใช้ที่สุด)
const ใช้สำหรับค่าคงที่ (constant) ที่ไม่เปลี่ยนแปลง ไม่สามารถ reassign ได้ แต่สามารถแก้ไขคุณสมบัติ (ถ้า object/array):
// Declare constant
const PI = 3.14159;
const MAX_USERS = 100;
const APP_NAME = "MyApp";
// Cannot reassign
// PI = 3.14; // ❌ Error: Assignment to constant variable
// But can modify properties (if object/array)
const person = { name: "John" };
person.name = "Jane"; // ✅ OK: modifying property
person.age = 25; // ✅ OK: adding property
// Cannot reassign the variable itself
// person = {}; // ❌ Error
// Block scope
{
const x = 10;
console.log(x); // 10
}
// console.log(x); // ❌ Error: not defined
2. let (ใช้เมื่อต้องการ reassign)
let ใช้สำหรับตัวแปรที่จะเปลี่ยนแปลง สามารถ reassign ได้ แต่ไม่สามารถ redeclare ได้ มี block scope:
// Declare variable with let
let x = 10;
x = 30; // ✅ OK: can reassign
x = 50; // ✅ OK: can reassign again
// Block scope
if (true) {
let message = "Inside block";
console.log(message); // ✅ Works
}
// console.log(message); // ❌ Error: not defined
// Loop counter (best practice)
for (let i = 0; i < 5; i++) {
console.log(i);
}
// console.log(i); // ❌ Error: i is not defined outside loop
// Cannot redeclare
let y = 10;
// let y = 20; // ❌ Error: Identifier 'y' has already been declared
3. var (เลิกใช้แล้ว - หลีกเลี่ยง)
var ใช้ในยุก JavaScript เก่า แต่ไม่แนะนำให้ใช้ในโค้ดใหม่ เพราะมี quirks และ confusing scoping rules:
// var - old way (avoid in modern code)
var old = 5; // Function scope, not block scope
old = 10; // ✅ Can reassign
// var ไม่มี block scope (problematic!)
if (true) {
var x = 20;
}
console.log(x); // 20 (leaked out of if block) - ❌ Unexpected!
// ❌ ไม่ดี - unpredictable behavior
var age = 25;
var age = 30; // ✅ Can redeclare (confusing! shouldn't allow)
// ✅ ดี - use const/let instead
const name = "John";
// const name = "Jane"; // ❌ Error: cannot redeclare
📊 const vs let vs var Comparison
| ลักษณะ | const | let | var |
|---|---|---|---|
| Reassign | ❌ ไม่ได้ | ✅ ได้ | ✅ ได้ |
| Redeclare | ❌ ไม่ได้ | ❌ ไม่ได้ | ✅ ได้ (confusing) |
| Scope | Block scope | Block scope | Function scope |
| Hoisting | Temporal Dead Zone | Temporal Dead Zone | Hoisted (undefined) |
| ใช้เมื่อ | ค่าคงที่ (default) | ตัวแปรที่เปลี่ยนแปลง | ❌ หลีกเลี่ยง |
- ใช้ const โดยค่าเริ่มต้น - ป้องกันการเปลี่ยนแปลงโดยไม่ตั้งใจ
- ใช้ let เมื่อต้องการ reassign - สำหรับตัวแปรที่เปลี่ยนแปลง
- หลีกเลี่ยง var ในโค้ดใหม่ - มี confusing behaviors
Operators - ตัวดำเนินการ
Operators คือ สัญลักษณ์ที่ใช้สำหรับดำเนินการกับข้อมูล เช่น การบวก การเปรียบเทียบ การตรรกะ เป็นต้น
1. Arithmetic Operators (ตัวดำเนินการทางคณิตศาสตร์)
ใช้สำหรับการคำนวณทางคณิตศาสตร์:
let a = 10, b = 3;
a + b; // 13 (addition)
a - b; // 7 (subtraction)
a * b; // 30 (multiplication)
a / b; // 3.33 (division)
a % b; // 1 (modulo - remainder)
a ** b; // 1000 (exponent - power)
// Increment/Decrement
let x = 5;
x++; // 6 (increment by 1)
x--; // 5 (decrement by 1)
++x; // Pre-increment
x++; // Post-increment (difference in expressions)
2. Comparison Operators (ตัวดำเนินการเปรียบเทียบ)
ใช้สำหรับเปรียบเทียบค่า ผลลัพธ์เป็น boolean (true/false):
// Equality
5 === "5"; // false (strict equality - type matters)
5 == "5"; // true (loose equality - type coercion)
5 !== "5"; // true (strict inequality)
5 != "5"; // false (loose inequality)
// Greater/Less than
10 > 5; // true (greater than)
10 >= 10; // true (greater than or equal)
5 < 10; // true (less than)
5 <= 5; // true (less than or equal)
// Best practice: always use === instead of ==
// === checks both value AND type (safer)
3. Logical Operators (ตัวดำเนินการตรรกะ)
ใช้สำหรับรวมหลายเงื่อนไขเข้าด้วยกัน:
// AND operator (&&) - true ถ้าทั้ง 2 เป็น true
true && false; // false
true && true; // true
(10 > 5) && (20 > 15); // true
// OR operator (||) - true ถ้า 1 ใน 2 เป็น true
true || false; // true
false || false; // false
(10 > 5) || (20 < 15); // true
// NOT operator (!) - กลับค่า
!true; // false
!false; // true
!(10 < 5); // true
// Short-circuit evaluation
const user = null;
user && user.name; // null (doesn't check user.name)
user || "Guest"; // "Guest" (returns "Guest" if user is falsy)
4. Assignment Operators (ตัวดำเนินการการกำหนด)
let x = 10; // Simple assignment
x += 5; // x = x + 5 (15)
x -= 3; // x = x - 3 (12)
x *= 2; // x = x * 2 (24)
x /= 4; // x = x / 4 (6)
x %= 2; // x = x % 2 (0)
x **= 2; // x = x ** 2 (0)
📊 Operators Comparison Table
| ประเภท | Operator | ตัวอย่าง | ผลลัพธ์ |
|---|---|---|---|
| Arithmetic | +, -, *, /, %, ** | 10 + 3 | 13 |
| Comparison | ===, !==, >, <, >=, <= | 10 > 5 | true |
| Logical | &&, ||, ! | true && false | false |
| Assignment | =, +=, -=, *=, /= | x += 5 | x = x + 5 |
- ❌ ใช้ == แทน === → อาจสร้าง type coercion ที่ไม่คาดคิด
- ❌ ลืม && หรือ || → เงื่อนไขจะไม่ทำงานตามที่ต้องการ
- ❌ สับสนระหว่าง = (assignment) กับ === (comparison)
Control Flow - การไหลของโปรแกรม
Control flow คือ ลำดับการทำงานของโปรแกรม ใช้ if/else, switch, loops เพื่อควบคุมว่าโค้ดส่วนไหนควรทำงาน
1. if...else (เงื่อนไข)
ใช้สำหรับตัดสินใจว่าจะทำส่วนไหนของโค้ด:
// Simple if
if (age >= 18) {
console.log("Adult");
}
// if...else
if (age >= 18) {
console.log("Adult");
} else {
console.log("Minor");
}
// if...else if...else (multiple conditions)
if (age < 13) {
console.log("Child");
} else if (age < 18) {
console.log("Teenager");
} else {
console.log("Adult");
}
// Ternary operator (short form)
const status = age >= 18 ? "Adult" : "Minor";
console.log(status);
2. switch (หลายตัวเลือก)
ใช้เมื่อต้องตัดสินใจจากค่าเพียงค่าเดียว:
// Switch statement
switch (day) {
case 1:
console.log("Monday");
break; // Important: ต้องใช้ break หรือจะไป execute case ถัดไป
case 2:
console.log("Tuesday");
break;
case 3:
console.log("Wednesday");
break;
default:
console.log("Unknown day");
}
// Switch กับ multiple cases
const status = "active";
switch (status) {
case "active":
case "pending":
console.log("User is active or pending");
break;
case "inactive":
console.log("User is inactive");
break;
default:
console.log("Unknown status");
}
3. Loops (วนซ้ำ)
ใช้สำหรับทำงานซ้ำๆ หลายครั้ง:
for Loop - วนซ้ำตามจำนวน
// Traditional for loop
for (let i = 0; i < 5; i++) {
console.log(i); // 0, 1, 2, 3, 4
}
// for loop กับ array
const fruits = ["Apple", "Banana", "Orange"];
for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
}
for...of Loop - วนซ้ำค่า (ES6+)
// for...of - วนซ้ำค่าของ array
const fruits = ["Apple", "Banana", "Orange"];
for (let fruit of fruits) {
console.log(fruit); // Apple, Banana, Orange
}
// for...of กับ string
const name = "John";
for (let char of name) {
console.log(char); // J, o, h, n
}
while Loop - วนซ้ำตามเงื่อนไข
// While loop - วนซ้ำจนกว่าเงื่อนไขเป็น false
let count = 0;
while (count < 5) {
console.log(count);
count++;
}
// do...while - ทำงานอย่างน้อย 1 ครั้ง
let x = 0;
do {
console.log(x);
x++;
} while (x < 5);
break และ continue
// break - ออกจาก loop
for (let i = 0; i < 10; i++) {
if (i === 5) {
break; // ออกจาก loop เมื่อ i = 5
}
console.log(i); // 0, 1, 2, 3, 4
}
// continue - ข้ามไปรอบถัดไป
for (let i = 0; i < 5; i++) {
if (i === 2) {
continue; // ข้ามค่า 2
}
console.log(i); // 0, 1, 3, 4
}
📊 Control Flow Comparison
| ประเภท | ใช้เมื่อ | ตัวอย่าง |
|---|---|---|
| if...else | เงื่อนไขหลายตัว | age < 13, age < 18, else |
| switch | ค่าเดียว หลายตัวเลือก | day = 1, 2, 3, default |
| for | วนซ้ำตามจำนวน | i = 0 to 10 |
| for...of | วนซ้ำค่าในarray | for (item of array) |
| while | วนซ้ำตามเงื่อนไข | while (x < 10) |
Functions - ฟังก์ชัน
Function คือ โค้ดที่ทำงานเฉพาะเจาะจง และนำมาใช้ใหม่ได้หลายครั้ง ทำให้โค้ดเป็นระเบียบและป้องกันการทำซ้ำ
1. Function Declaration - ประกาศฟังก์ชัน
// Traditional function declaration
function add(a, b) {
return a + b;
}
// Call the function
add(5, 3); // 8
add(10, 20); // 30
// Function with multiple statements
function greet(name) {
const message = `Hello, ${name}`;
console.log(message);
return message;
}
greet("John"); // Hello, John
2. Arrow Function (ES6+) - ฟังก์ชันลูกศร
Arrow function เป็นวิธีเขียน function ที่กระชับและสั้นกว่า:
// Arrow function - short syntax
const add = (a, b) => a + b;
const square = (x) => x * x;
const greet = (name) => `Hello, ${name}`;
// Call them
add(5, 3); // 8
square(5); // 25
greet("John"); // Hello, John
// Arrow function กับ multiple statements
const calculateAge = (birthYear) => {
const currentYear = new Date().getFullYear();
return currentYear - birthYear;
};
calculateAge(1990); // 34
// Without parameters
const random = () => Math.random();
// One parameter (parentheses optional)
const double = x => x * 2;
const double = (x) => x * 2; // Same thing
3. Parameters & Arguments - พารามิเตอร์และอาร์กิวเมนต์
// Default parameters
function greet(name = "Guest", age = 18) {
console.log(`Hi ${name}, age ${age}`);
}
greet(); // Hi Guest, age 18
greet("John"); // Hi John, age 18
greet("John", 25); // Hi John, age 25
// Rest parameters (...) - รับพารามิเตอร์หลายตัว
function sum(...numbers) {
let total = 0;
for (let num of numbers) {
total += num;
}
return total;
}
sum(1, 2, 3); // 6
sum(1, 2, 3, 4, 5); // 15
// Rest parameter กับ spread operator
const arr = [1, 2, 3];
sum(...arr); // 6
4. Closures - ความสัมพันธ์ระหว่างฟังก์ชัน
Closure คือ ฟังก์ชันภายในสามารถเข้าถึงตัวแปรของฟังก์ชันภายนอก:
// Closure example
function createCounter() {
let count = 0; // Local variable
return function () {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
// Each counter is independent
const counter2 = createCounter();
console.log(counter2()); // 1 (separate from counter)
// Practical closure example - makeGreeter
function makeGreeter(greeting) {
return function (name) {
console.log(`${greeting}, ${name}!`);
};
}
const sayHello = makeGreeter("Hello");
const sayHi = makeGreeter("Hi");
sayHello("John"); // Hello, John!
sayHi("Jane"); // Hi, Jane!
5. Function Methods - ฟังก์ชันที่อยู่ใน Object
// Object with methods
const calculator = {
value: 0,
add(num) {
this.value += num;
return this;
},
subtract(num) {
this.value -= num;
return this;
},
getResult() {
return this.value;
}
};
// Method chaining
calculator.add(10).subtract(3).add(5);
console.log(calculator.getResult()); // 12
📊 Function Types Comparison
| ประเภท | ไวยากรณ์ | ใช้เมื่อ | ตัวอย่าง |
|---|---|---|---|
| Declaration | function name() {} | ฟังก์ชันปกติ | function add(a, b) { return a + b; } |
| Arrow | const name = () => {} | ฟังก์ชันสั้น, callbacks | const add = (a, b) => a + b; |
| Closure | function() { return function() {} } | ข้อมูล private, factory | createCounter() |
| Method | object: { method() {} } | ฟังก์ชันใน object | person.greet() |
- ✅ ใช้ meaningful function names
- ✅ Keep functions small (single responsibility)
- ✅ ใช้ const สำหรับ arrow functions
- ✅ Return values instead of console.log
Objects & Arrays - วัตถุและลิสต์
Objects และ Arrays เป็นประเภท Reference ที่ใช้เก็บข้อมูลหลายตัว Objects เก็บ key-value pairs ส่วน Arrays เก็บลำดับของค่า
1. Objects - วัตถุข้อมูล
Objects ใช้สำหรับเก็บข้อมูลที่เกี่ยวข้องกันในรูป key-value pairs:
// Create object
const person = {
name: "John",
age: 25,
email: "john@example.com",
isActive: true,
// Methods (functions ใน object)
greet() {
console.log(`Hello, I'm ${this.name}`);
},
getInfo() {
return `${this.name} is ${this.age} years old`;
}
};
// Access properties
person.name; // "John"
person["age"]; // 25
// Modify properties
person.age = 26;
person.email = "john.doe@example.com";
// Add new property
person.phone = "0881234567";
// Object methods
Object.keys(person); // ["name", "age", "email", "isActive", ...]
Object.values(person); // ["John", 26, "john.doe@example.com", true, ...]
Object.entries(person); // [["name", "John"], ["age", 26], ...]
// Method chaining example
person.greet(); // Hello, I'm John
console.log(person.getInfo()); // John is 26 years old
2. Destructuring - แตกส่วน
Destructuring ให้สามารถแยกค่าจาก Objects หรือ Arrays ออกมาเป็นตัวแปรแต่ละตัว:
// Object destructuring - แตกส่วน object
const person = { name: "John", age: 25, city: "Bangkok" };
const { name, age } = person;
console.log(name); // "John"
console.log(age); // 25
// Rename properties
const { name: fullName, age: userAge } = person;
// Default values
const { country = "Thailand" } = person;
console.log(country); // "Thailand" (default value)
// Array destructuring - แตกส่วน array
const colors = ["red", "green", "blue"];
const [first, second, third] = colors;
console.log(first); // "red"
console.log(second); // "green"
// Skip elements
const [primary, , tertiary] = colors;
console.log(primary); // "red"
console.log(tertiary); // "blue"
// Rest operator
const [a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(rest); // [3, 4, 5]
3. Array Methods - เมธอดของ Array
Array มีเมธอดมากมายที่ช่วยในการจัดการข้อมูล นี่คือเมธอดที่สำคัญที่สุด:
const numbers = [1, 2, 3, 4, 5];
const fruits = ["Apple", "Banana", "Orange"];
// map() - transform each element
const doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// filter() - keep only matching elements
const evens = numbers.filter(n => n % 2 === 0);
console.log(evens); // [2, 4]
// reduce() - combine all elements into one
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(sum); // 15
// find() - return first matching element
const first = numbers.find(n => n > 3);
console.log(first); // 4
// some() - check if any element matches
const hasEven = numbers.some(n => n % 2 === 0);
console.log(hasEven); // true
// every() - check if all elements match
const allPositive = numbers.every(n => n > 0);
console.log(allPositive); // true
// includes() - check if contains value
console.log(fruits.includes("Banana")); // true
// sort() - sort array
const sorted = numbers.sort((a, b) => a - b);
console.log(sorted); // [1, 2, 3, 4, 5]
// reverse() - reverse array
const reversed = [...numbers].reverse();
console.log(reversed); // [5, 4, 3, 2, 1]
DOM Manipulation - การจัดการ DOM
DOM (Document Object Model) คือ โครงสร้างของ HTML page ใน JavaScript เราสามารถใช้ DOM API เพื่อเลือก, แก้ไข, เพิ่ม, ลบ elements ได้
1. Selecting Elements - เลือก Element
มีหลายวิธีในการเลือก elements จาก HTML:
// By ID - เลือกตามชื่อ id
const el = document.getElementById("myId");
// By class - เลือกตามชื่อ class
const els = document.getElementsByClassName("myClass");
// By tag - เลือกตามชื่อ tag
const paragraphs = document.getElementsByTagName("p");
// Query Selector (modern way - แนะนำ)
const first = document.querySelector(".myClass"); // ได้ element แรกเท่านั้น
const all = document.querySelectorAll(".myClass"); // ได้ทั้งหมด
// Advanced selectors
const elem = document.querySelector("div.active > p"); // ระบุได้ละเอียด
const items = document.querySelectorAll("li.item"); // หลาย elements
2. Modifying Content - แก้ไขเนื้อหา
เปลี่ยนข้อความหรือ HTML ของ element:
const el = document.querySelector("#myElement");
// Change text content (safe - ไม่รันตัว script)
el.textContent = "New text";
// Change HTML (ระวัง - ถ้ากำหนดจากนอก อาจมี XSS risk)
el.innerHTML = "<strong>Bold text</strong>";
// Get current content
console.log(el.textContent); // Get text only
console.log(el.innerHTML); // Get HTML
// Append text/HTML
el.textContent += " additional text";
el.innerHTML += "<p>new paragraph</p>";
3. Modifying Attributes - แก้ไขแอตทริบิวต์
const img = document.querySelector("img");
// Get attribute
console.log(img.getAttribute("src"));
// Set attribute
img.setAttribute("src", "new-image.jpg");
img.setAttribute("alt", "New description");
// Direct property access
img.src = "another-image.jpg";
img.alt = "Another description";
// Remove attribute
img.removeAttribute("alt");
// Check if has attribute
if (img.hasAttribute("src")) {
console.log("Image has src attribute");
}
4. Modifying Classes - แก้ไข Class
ใช้ classList เพื่อจัดการ CSS classes:
const el = document.querySelector(".box");
// Add class
el.classList.add("active"); // เพิ่ม class
el.classList.add("red", "large"); // เพิ่มหลาย class
// Remove class
el.classList.remove("inactive");
// Toggle class (เปลี่ยนสลับ)
el.classList.toggle("highlight");
// Check if has class
if (el.classList.contains("active")) {
console.log("Element is active");
}
// Replace class
el.classList.replace("old-class", "new-class");
5. Modifying Styles - แก้ไขสไตล์
const el = document.querySelector(".box");
// Inline styles
el.style.backgroundColor = "red";
el.style.width = "300px";
el.style.padding = "20px";
// Get computed style (current CSS)
const bgColor = window.getComputedStyle(el).backgroundColor;
// Multiple styles at once (better approach)
Object.assign(el.style, {
backgroundColor: "blue",
color: "white",
padding: "15px",
fontSize: "16px"
});
6. Creating & Removing Elements - สร้างและลบ Element
// Create new element
const newDiv = document.createElement("div");
newDiv.textContent = "Hello!";
newDiv.classList.add("greeting");
// Add to page
document.body.appendChild(newDiv); // เพิ่มต่อท้าย
const container = document.querySelector("#container");
container.appendChild(newDiv);
// Add before element
const referenceEl = document.querySelector(".reference");
referenceEl.parentElement.insertBefore(newDiv, referenceEl);
// Remove element
newDiv.remove();
// หรือ
newDiv.parentElement.removeChild(newDiv);
// Clone element
const clone = newDiv.cloneNode(true); // true = clone ลูกด้วย
container.appendChild(clone);
Events - เหตุการณ์
Events คือ สิ่งที่เกิดขึ้นบน page เช่น การคลิก, พิมพ์, scroll เป็นต้น เราสามารถ "listen" เหตุการณ์เหล่านั้นและทำสิ่งใดสิ่งหนึ่งเมื่อเหตุการณ์เกิดขึ้น
1. Event Listeners - ฟังการเกิดเหตุการณ์
ใช้ addEventListener() เพื่อฟังเหตุการณ์:
const button = document.querySelector("button");
// Listen to click event
button.addEventListener("click", () => {
console.log("Button clicked!");
});
// Listen to input event
const input = document.querySelector("input");
input.addEventListener("input", (event) => {
console.log("User typed:", event.target.value);
});
// Listen to keyboard event
document.addEventListener("keydown", (event) => {
console.log("Key pressed:", event.key);
console.log("Key code:", event.code);
});
// Access event object
button.addEventListener("click", (event) => {
console.log(event.target); // element ที่ triggered event
console.log(event.type); // ประเภท event
console.log(event.timeStamp); // เวลา event เกิด
});
2. Common Events - เหตุการณ์ทั่วไป
| ประเภท | Event | เมื่อไร | ตัวอย่าง |
|---|---|---|---|
| Mouse | click, dblclick, mouseover, mouseout, mouseenter, mouseleave | ใช้เมื่อผู้ใช้ใช้เมาส์ | button.addEventListener("click", ...) |
| Keyboard | keydown, keyup, keypress | ใช้เมื่อผู้ใช้กด keyboard | input.addEventListener("keydown", ...) |
| Form | submit, change, input, focus, blur | ใช้เมื่อ form เปลี่ยนแปลง | form.addEventListener("submit", ...) |
| Document/Window | load, unload, scroll, resize | ใช้เมื่อ page เปลี่ยนแปลง | window.addEventListener("scroll", ...) |
| Custom | กำหนดเองได้ | สร้าง event เอง | element.dispatchEvent(new Event("custom")) |
3. Practical Event Examples - ตัวอย่างจริง
// Example 1: Form submission
const form = document.querySelector("form");
form.addEventListener("submit", (event) => {
event.preventDefault(); // ป้องกัน default behavior (submit)
const name = document.querySelector("input[name='name']").value;
const email = document.querySelector("input[name='email']").value;
console.log("Name:", name);
console.log("Email:", email);
// Send to server
});
// Example 2: Input validation (real-time)
const passwordInput = document.querySelector("input[type='password']");
const strength = document.querySelector(".strength");
passwordInput.addEventListener("input", (event) => {
const value = event.target.value;
if (value.length < 6) {
strength.textContent = "Weak";
strength.style.color = "red";
} else if (value.length < 10) {
strength.textContent = "Medium";
strength.style.color = "orange";
} else {
strength.textContent = "Strong";
strength.style.color = "green";
}
});
// Example 3: Event delegation (listen to many elements)
const list = document.querySelector(".item-list");
list.addEventListener("click", (event) => {
// ตรวจสอบว่าคลิกที่ element ไหน
if (event.target.classList.contains("item-btn")) {
const item = event.target.closest(".item");
console.log("Clicked item:", item.textContent);
}
});
// Example 4: Remove event listener
function handleClick() {
console.log("Clicked!");
}
button.addEventListener("click", handleClick);
// Remove listener
button.removeEventListener("click", handleClick);
4. Event Properties - คุณสมบัติของ Event
document.addEventListener("click", (event) => {
// Basic info
console.log(event.type); // "click"
console.log(event.target); // element ที่คลิก
console.log(event.currentTarget); // element ที่มี listener
// Mouse info
console.log(event.clientX); // X position relative to window
console.log(event.clientY); // Y position relative to window
console.log(event.pageX); // X position relative to page
console.log(event.pageY); // Y position relative to page
// Keyboard info (for keyboard events)
console.log(event.key); // ตัวอักษรที่กด
console.log(event.code); // รหัส key
console.log(event.shiftKey); // true ถ้ากด Shift
console.log(event.ctrlKey); // true ถ้ากด Ctrl
console.log(event.altKey); // true ถ้ากด Alt
// Prevention
event.preventDefault(); // ป้องกัน default behavior
event.stopPropagation(); // ป้องกัน event bubbling
});
Asynchronous JavaScript
Asynchronous หมายถึง โค้ดที่ไม่ต้องรอให้เสร็จแล้วค่อยทำสิ่งต่อไป เช่น การดึงข้อมูลจาก server อาจใช้เวลา เราไม่อยากให้ page รอ ดังนั้นจึงใช้ async code
1. Callbacks - ฟังก์ชันที่ส่งผ่าน
วิธีเก่า: ส่งฟังก์ชันเป็น parameter เพื่อเรียกใหม่เมื่อเสร็จ:
// Callback - old way (callback hell)
function fetchData(callback) {
setTimeout(() => {
const data = { name: "John", age: 25 };
callback(data); // เรียก callback function
}, 1000);
}
fetchData((result) => {
console.log("Data received:", result);
});
// Nested callbacks (callback hell)
fetchData((user) => {
fetchUserPosts(user.id, (posts) => {
fetchPostComments(posts[0].id, (comments) => {
console.log(comments);
// ยากเข้าใจและ maintain
});
});
});
2. Promises - สัญญา
Promise ทำให้ async code อ่านง่ายขึ้น แต่ยังดีกว่า callbacks:
// Create a promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve("Success!"); // ส่งผลลัพธ์กลับ
} else {
reject("Error!"); // ส่ง error กลับ
}
}, 1000);
});
// Use the promise
promise
.then(result => {
console.log("Result:", result);
})
.catch(error => {
console.log("Error:", error);
})
.finally(() => {
console.log("Done!");
});
// Promise chaining
fetch("https://api.example.com/users")
.then(response => response.json())
.then(data => {
console.log("Users:", data);
return fetch(`https://api.example.com/users/${data[0].id}`);
})
.then(response => response.json())
.then(user => console.log("First user:", user))
.catch(error => console.log("Error:", error));
3. Async/Await - วิธีใหม่ (แนะนำ)
Async/Await ทำให้ async code อ่านเหมือน synchronous code:
// Define async function
async function fetchUserData() {
try {
// await บอก JavaScript ให้รอให้เสร็จ
const response = await fetch("https://api.example.com/users");
const data = await response.json();
console.log("Users:", data);
return data;
} catch (error) {
console.log("Error:", error);
} finally {
console.log("Request completed!");
}
}
// Call async function
fetchUserData();
// Async with multiple requests
async function getUserWithPosts(userId) {
try {
// Fetch user
const userResponse = await fetch(`https://api.example.com/users/${userId}`);
const user = await userResponse.json();
// Fetch posts
const postsResponse = await fetch(`https://api.example.com/posts?userId=${userId}`);
const posts = await postsResponse.json();
return { user, posts };
} catch (error) {
console.log("Error:", error);
}
}
// Parallel requests (faster)
async function fetchMultiple() {
try {
// Run requests in parallel using Promise.all()
const [users, posts, comments] = await Promise.all([
fetch("https://api.example.com/users").then(r => r.json()),
fetch("https://api.example.com/posts").then(r => r.json()),
fetch("https://api.example.com/comments").then(r => r.json())
]);
console.log("Users:", users);
console.log("Posts:", posts);
console.log("Comments:", comments);
} catch (error) {
console.log("Error:", error);
}
}
4. Fetch API - ดึงข้อมูล
Fetch API ใช้สำหรับส่ง HTTP requests (GET, POST, PUT, DELETE):
// GET request (default)
fetch("https://api.example.com/users")
.then(response => response.json())
.then(data => console.log("Users:", data))
.catch(error => console.log("Error:", error));
// GET with async/await
async function getUsers() {
try {
const response = await fetch("https://api.example.com/users");
const data = await response.json();
console.log("Users:", data);
} catch (error) {
console.log("Error:", error);
}
}
// POST request
async function createUser(userData) {
try {
const response = await fetch("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(userData) // Convert object to JSON string
});
const result = await response.json();
console.log("Created:", result);
} catch (error) {
console.log("Error:", error);
}
}
createUser({ name: "John", email: "john@example.com" });
// PUT request (update)
async function updateUser(userId, updatedData) {
const response = await fetch(`https://api.example.com/users/${userId}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(updatedData)
});
return response.json();
}
// DELETE request
async function deleteUser(userId) {
const response = await fetch(`https://api.example.com/users/${userId}`, {
method: "DELETE"
});
return response.json();
}
Error Handling - การจัดการข้อผิดพลาด
Error Handling ช่วยให้โปรแกรมไม่ขัดข้อง เมื่อมีปัญหา ให้จัดการได้อย่างถูกต้อง:
1. Try/Catch/Finally
ใช้สำหรับจับและจัดการข้อผิดพลาด:
// Basic try/catch
try {
// โค้ดที่อาจเกิด error
const result = JSON.parse("invalid json");
console.log(result);
} catch (error) {
// จับและจัดการ error
console.log("Caught error:", error.message);
} finally {
// รันเสมอ ไม่ว่าจะมี error หรือไม่
console.log("Done!");
}
// With finally
try {
const data = someUndefinedFunction();
} catch (error) {
console.log("Error occurred");
} finally {
console.log("Cleanup complete");
}
// Multiple catch blocks
try {
const file = readFile("data.txt");
} catch (error) {
if (error instanceof FileNotFoundError) {
console.log("File not found");
} else if (error instanceof PermissionError) {
console.log("Permission denied");
} else {
console.log("Unknown error:", error);
}
}
2. Error Types - ประเภทของ Error
JavaScript มี error types ต่างๆ แต่ละประเภทแสดงปัญหาคนละแบบ:
| Error Type | ความหมาย | ตัวอย่าง |
|---|---|---|
| SyntaxError | โค้ดผิดไวยากรณ์ | let x = 5 (missing semicolon) |
| ReferenceError | ตัวแปรไม่มีอยู่ | console.log(undefinedVar); |
| TypeError | ใช้ค่าผิด type | let x = 5; x.toUpperCase(); |
| RangeError | ค่านอกขอบเขต | new Array(-1); |
| Error | Generic error | throw new Error("Custom error") |
3. Throwing Errors - โยน Error เอง
บางครั้งเราต้อง throw error เองเมื่อเงื่อนไขไม่ถูก:
// Throw custom error
function divide(a, b) {
if (b === 0) {
throw new Error("Cannot divide by zero!");
}
return a / b;
}
try {
const result = divide(10, 0);
} catch (error) {
console.log("Error:", error.message);
}
// Throw specific error type
function validateAge(age) {
if (age < 0) {
throw new RangeError("Age cannot be negative");
}
if (typeof age !== "number") {
throw new TypeError("Age must be a number");
}
return true;
}
try {
validateAge(-5);
} catch (error) {
if (error instanceof RangeError) {
console.log("Range error:", error.message);
}
}
// Error with details
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
try {
throw new ValidationError("Invalid email", "email");
} catch (error) {
console.log(error.message); // Invalid email
console.log(error.field); // email
}
4. Best Practices - วิธีที่ถูก
✅ ทำให้ error handling มีประสิทธิภาพและง่ายต่อ maintain:
// ✅ ดี: ให้ message ที่ชัดเจน
try {
const user = await fetchUser(userId);
} catch (error) {
console.error("Failed to fetch user:", error.message);
// Show error to user หรือ retry
}
// ❌ ไม่ดี: silent fail
try {
const user = await fetchUser(userId);
} catch (error) {
// ปล่อยไป ไม่ทำอะไร
}
// ✅ ดี: Handle different error types
async function processData(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
return response.json();
} catch (error) {
if (error instanceof TypeError) {
console.error("Network error:", error.message);
} else if (error instanceof SyntaxError) {
console.error("Invalid JSON:", error.message);
} else {
console.error("Unknown error:", error.message);
}
throw error; // Re-throw to parent
}
}
// ✅ ดี: Finally for cleanup
function readFile(path) {
let file = null;
try {
file = openFile(path);
return parseData(file);
} catch (error) {
console.error("Error reading file:", error);
} finally {
// รันเสมอ ให้ปิด file
if (file) {
file.close();
}
}
}
ES6+ Features - ฟีเจอร์ใหม่
ES6 (ECMAScript 2015) และ ES6+ (2016 ขึ้นไป) นำเอาฟีเจอร์ใหม่ๆ มาให้ JavaScript อ่านง่ายและมีประสิทธิภาพขึ้น:
1. Template Literals - String ด้วย backticks
ใช้ backticks (`) แทน quotes ปกติ สามารถ embed variables ได้:
// Old way (concatenation)
const name = "John";
const age = 25;
const message = "Hello, " + name + "! You are " + age + " years old.";
// New way (template literals)
const messageNew = `Hello, ${name}! You are ${age} years old.`;
console.log(messageNew);
// Multi-line string
const bio = `
Name: John Doe
Age: 25
Occupation: Developer
`;
console.log(bio);
// Expressions in template literals
const x = 10;
const y = 20;
console.log(`${x} + ${y} = ${x + y}`);
// Function calls in template literals
function getFullName(first, last) {
return `${first} ${last}`;
}
const greeting = `Welcome, ${getFullName("John", "Doe")}!`;
console.log(greeting);
2. Arrow Functions - ลัดขนัด
วิธีเขียน function แบบสั้นและสะดวก:
// Old way (regular function)
const add = function(a, b) {
return a + b;
};
// Arrow function (basic)
const addArrow = (a, b) => {
return a + b;
};
// Arrow function (single line)
const addShort = (a, b) => a + b;
// Arrow function (single parameter)
const square = x => x * x;
// Arrow function (no parameters)
const greet = () => "Hello!";
// Difference: 'this' keyword
const person = {
name: "John",
sayHello: function() {
console.log(`Hello, I'm ${this.name}`); // ✅ this works
},
sayHelloArrow: () => {
console.log(`Hello, I'm ${this.name}`); // ❌ this doesn't work (global this)
}
};
person.sayHello(); // "Hello, I'm John"
person.sayHelloArrow(); // "Hello, I'm undefined"
3. Classes - Object-Oriented Programming
ใช้ class เพื่อ organize code และ reuse logic:
// Define a class
class Animal {
// Constructor - รันเมื่อ new Animal()
constructor(name, age) {
this.name = name;
this.age = age;
}
// Method
speak() {
console.log(`${this.name} makes a sound`);
}
// Static method (belongs to class, not instance)
static info() {
console.log("This is an Animal class");
}
}
// Create instance
const dog = new Animal("Buddy", 5);
dog.speak(); // "Buddy makes a sound"
Animal.info(); // "This is an Animal class"
// Inheritance (extends)
class Dog extends Animal {
constructor(name, age, breed) {
super(name, age); // Call parent constructor
this.breed = breed;
}
speak() {
console.log(`${this.name} barks!`);
}
getInfo() {
return `${this.name} is a ${this.breed}`;
}
}
const myDog = new Dog("Max", 3, "Golden Retriever");
myDog.speak(); // "Max barks!"
console.log(myDog.getInfo()); // "Max is a Golden Retriever"
4. Destructuring - แยกค่า
วิธีสั้นๆ ดึงค่าจาก objects และ arrays:
// Object destructuring
const person = {
name: "John",
age: 25,
city: "Bangkok"
};
// Old way
const name = person.name;
const age = person.age;
// New way
const { name, age } = person;
console.log(name); // "John"
// With default values
const { name, country = "Thailand" } = person;
console.log(country); // "Thailand" (uses default)
// Array destructuring
const colors = ["red", "green", "blue"];
// Old way
const first = colors[0];
const second = colors[1];
// New way
const [first, second, third] = colors;
// Skipping elements
const [primary, , secondary] = colors;
console.log(primary); // "red"
console.log(secondary); // "blue"
// Rest operator (...)
const [head, ...tail] = colors;
console.log(head); // "red"
console.log(tail); // ["green", "blue"]
5. Spread Operator - กระจาย
ใช้ ... เพื่อ copy หรือ merge arrays/objects:
// Spread with arrays
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
// Copy array
const original = [1, 2, 3];
const copy = [...original]; // [1, 2, 3] (separate array)
// Merge arrays
const array1 = [1, 2];
const array2 = [3, 4];
const merged = [...array1, ...array2]; // [1, 2, 3, 4]
// Spread with objects
const obj1 = { name: "John", age: 25 };
const obj2 = { ...obj1, city: "Bangkok" };
// { name: "John", age: 25, city: "Bangkok" }
// Override properties
const base = { color: "red", size: "large" };
const custom = { ...base, color: "blue" };
// { color: "blue", size: "large" }
// Rest parameter in function
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
6. let และ const - ตัวแปรใหม่
var ยุค่า scope ใหญ่เกินไป ให้ใช้ let/const แทน:
// var - ❌ Avoid (function scoped)
function oldWay() {
if (true) {
var x = 5;
}
console.log(x); // 5 (accessible outside block)
}
// let - ✅ Block scoped
function newWay() {
if (true) {
let x = 5;
}
console.log(x); // ❌ ReferenceError (not accessible)
}
// const - ✅ Block scoped + can't reassign
const PI = 3.14159;
// PI = 3.14; // ❌ Error: reassignment not allowed
// But const object properties CAN change
const user = { name: "John", age: 25 };
user.age = 26; // ✅ Allowed
// user = {}; // ❌ Error: can't reassign whole object
7. Default Parameters - ค่า default
Set ค่าเริ่มต้นสำหรับ function parameters:
// Old way (check for undefined)
function greet(name) {
name = name || "Guest";
console.log(`Hello, ${name}`);
}
// New way (default parameter)
function greetNew(name = "Guest") {
console.log(`Hello, ${name}`);
}
greetNew(); // "Hello, Guest"
greetNew("John"); // "Hello, John"
// Can use expressions as defaults
function createUser(name = "Anonymous", age = 18) {
return { name, age };
}
console.log(createUser());
// { name: "Anonymous", age: 18 }
Best Practices - วิธีที่ถูกต้อง
Best Practices ช่วยให้โค้ดอ่านได้ง่าย บำรุงรักษาได้ง่าย และมีประสิทธิภาพ:
1. Meaningful Names - ใช้ชื่อที่มีความหมาย
ชื่อตัวแปร/function ต้องบอกว่า มันทำอะไร:
// ❌ Bad names (unclear)
let a = 25;
let fn = (x) => x * 2;
let d = new Date();
let calc = (p, r, t) => p * r * t;
// ✅ Good names (clear intent)
let userAge = 25;
let doubleNumber = (number) => number * 2;
let currentDate = new Date();
let calculateInterest = (principal, rate, time) => principal * rate * time;
// ✅ Good boolean names (predicate)
let isActive = true;
let hasPermission = false;
let canDelete = true;
let shouldRetry = false;
2. Keep Functions Small - ฟังก์ชั่นเล็ก
แต่ละ function ทำเพียงหนึ่งสิ่ง (Single Responsibility):
// ❌ Bad: Function does too much
function processUser(user) {
// Validate
if (!user.email) throw new Error("Email required");
// Format
user.name = user.name.toUpperCase();
user.email = user.email.toLowerCase();
// Save
database.save(user);
// Send email
sendEmail(user.email, "Welcome!");
}
// ✅ Good: Separate concerns
function validateUser(user) {
if (!user.email) throw new Error("Email required");
if (!user.name) throw new Error("Name required");
return true;
}
function formatUser(user) {
return {
...user,
name: user.name.toUpperCase(),
email: user.email.toLowerCase()
};
}
function saveUser(user) {
return database.save(user);
}
// Main flow: clear and easy to understand
async function registerUser(userData) {
validateUser(userData);
const formatted = formatUser(userData);
await saveUser(formatted);
await sendEmail(formatted.email, "Welcome!");
}
3. Handle Errors - จัดการ Error อย่างถูกต้อง
ไม่ให้โปรแกรมขัดข้อง ต้องจัดการ error:
// ❌ Bad: Ignore error (silent fail)
function parseJSON(jsonString) {
try {
return JSON.parse(jsonString);
} catch (error) {
// Do nothing - program might break later
}
}
// ✅ Good: Log and handle error
function parseJSON(jsonString) {
try {
return JSON.parse(jsonString);
} catch (error) {
console.error("Invalid JSON:", error.message);
return null; // Return safe default
}
}
// ✅ Better: Return result object
function parseJSONSafe(jsonString) {
try {
const data = JSON.parse(jsonString);
return { success: true, data };
} catch (error) {
return { success: false, error: error.message };
}
}
// Usage
const result = parseJSONSafe(userInput);
if (result.success) {
console.log("Data:", result.data);
} else {
console.log("Error:", result.error);
}
4. Performance - ประสิทธิภาพ
เขียนโค้ดที่รวดเร็วและไม่เสียเวลา:
// ❌ Bad: Query DOM multiple times (slow)
for (let i = 0; i < 1000; i++) {
document.getElementById("output").textContent += i;
}
// ✅ Good: Access DOM once (fast)
const output = document.getElementById("output");
let result = "";
for (let i = 0; i < 1000; i++) {
result += i;
}
output.textContent = result;
// ❌ Bad: Nested loops O(n²)
const users = [{ id: 1 }, { id: 2 }, { id: 3 }];
const ids = [1, 2, 3, 4, 5];
for (let user of users) {
for (let id of ids) {
if (user.id === id) {
console.log(user);
}
}
}
// ✅ Good: Use Set for O(n) lookup
const users = [{ id: 1 }, { id: 2 }, { id: 3 }];
const idSet = new Set([1, 2, 3, 4, 5]);
for (let user of users) {
if (idSet.has(user.id)) {
console.log(user);
}
}
5. DRY (Don't Repeat Yourself) - ไม่ซ้ำซ้อน
ถ้า copy-paste code 2 ครั้ง ให้สร้าง function:
// ❌ Bad: Repetitive code
const firstName = "John";
const lastName = "Doe";
const middleName = "Michael";
const firstInitial = firstName.charAt(0).toUpperCase();
const lastInitial = lastName.charAt(0).toUpperCase();
const middleInitial = middleName.charAt(0).toUpperCase();
// ✅ Good: Reusable function
function getInitial(name) {
return name.charAt(0).toUpperCase();
}
const firstInitial = getInitial(firstName);
const lastInitial = getInitial(lastName);
const middleInitial = getInitial(middleName);
// Or even better: map
const names = ["John", "Doe", "Michael"];
const initials = names.map(getInitial);
6. Comments - ความเห็น
เขียน comments ที่อธิบาย "ทำไม" ไม่ใช่ "อะไร":
// ❌ Bad: Obvious comment
const age = 25; // Set age to 25
const users = []; // Create empty array
// ✅ Good: Explains why or complex logic
// Cache user preferences locally to reduce API calls
const userPreferences = localStorage.getItem("prefs");
// Retry 3 times because API sometimes fails temporarily
async function fetchWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fetch(url);
} catch (error) {
if (i === maxRetries - 1) throw error;
await delay(1000 * Math.pow(2, i)); // Exponential backoff
}
}
}
7. Use Const by Default - ใช้ const ก่อน
ลำดับความสำคัญ: const > let > var (ไม่ใช้ var เลย):
// ✅ Hierarchy
const user = { name: "John" }; // Use const by default
let count = 0; // Use let when value changes
let index = 0;
for (const item of items) { // Use const in loops too
console.log(item);
}
// ✅ Const prevents accidental reassignment
const PI = 3.14159;
const MAX_USERS = 100;
const API_URL = "https://api.example.com";
// ❌ Avoid
var oldVar = 5; // Don't use var
8. Async/Await over Callbacks - ใช้ async/await
Async/Await อ่านง่ายกว่า promise chains:
// ❌ Bad: Callback hell
function fetchUserData(userId, callback) {
fetchUser(userId, (user) => {
fetchPosts(user.id, (posts) => {
fetchComments(posts[0].id, (comments) => {
callback({ user, posts, comments });
});
});
});
}
// Better: Promise chaining
function fetchUserData(userId) {
return fetchUser(userId)
.then(user =>
fetchPosts(user.id)
.then(posts => ({ user, posts }))
)
.then(data =>
fetchComments(data.posts[0].id)
.then(comments => ({ ...data, comments }))
);
}
// ✅ Best: Async/Await (reads like synchronous)
async function fetchUserData(userId) {
const user = await fetchUser(userId);
const posts = await fetchPosts(user.id);
const comments = await fetchComments(posts[0].id);
return { user, posts, comments };
}
🎯 สรุปประเด็นสำคัญทั้งหมด
- ✅ Variables: ใช้ const by default, let เมื่อต้อง reassign
- ✅ Naming: ใช้ชื่อที่ชัดเจนและมีความหมาย
- ✅ Functions: ทำหนึ่งสิ่งให้ดี (Single Responsibility)
- ✅ Errors: จัดการ error ด้วย try/catch
- ✅ DOM: Access DOM element เพียงครั้งเดียว
- ✅ Async: ใช้ async/await แทน callbacks
- ✅ DRY: ไม่ copy-paste code ซ้ำไป
- ✅ Comments: อธิบาย "ทำไม" ไม่ใช่ "อะไร"
📚 บทสรุป
- ✅ JavaScript ทำให้เว็บ interactive และ dynamic
- ✅ ใช้ ES6+ features (const/let, arrow functions, classes)
- ✅ DOM manipulation เปลี่ยนหน้า HTML
- ✅ Event listeners ทำให้เว็บตอบสนอง user
- ✅ Asynchronous code สำหรับ API calls
- ✅ Error handling ป้องกันโปรแกรมขัด
- ✅ Write clean, readable, maintainable code
- ✅ Practice and experiment!