Array & Callback
การจัดการ array คือหัวใจของการเขียน JS สมัยใหม่ — โยนฟังก์ชันเข้าไปแล้วให้ array จัดการวนซ้ำให้เอง แทนการเขียน for ทุกครั้ง
Array vs Object
| Array | Object | |
|---|---|---|
| ใช้เครื่องหมาย | [ ] | { } |
| เข้าถึงด้วย | index ที่เป็นตัวเลข | ชื่อ key |
let user = { name: 'A' };
user.name // A
user["name"] // A
// ซ้อนกันเป็นต้นไม้ได้
const shop = [
{ name: "แซลมอน", type: [ {grade:"A", price:10}, {grade:"ธรรมดา", price:1} ] },
{ name: ["หมูทะ", "หมูจุ่ม"], price: 1 }
];
Destructuring
// array const name = ["a", "b"]; const [a, b] = name; // a="a", b="b" const vehicles = ['mustang', 'f-150', 'expedition']; const [car, , suv] = vehicles; // car='mustang', suv='expedition' — เว้นตำแหน่งได้ // object const vehicleOne = { brand:'Ford', model:'Mustang', type:'car', year:2021, color:'red' }; const { type, color, brand, model } = vehicleOne; // destructure ที่พารามิเตอร์ของฟังก์ชันได้เลย function myVehicle({ type, color, brand, model }) { return 'My ' + type + ' is a ' + color + ' ' + brand + ' ' + model; } myVehicle(vehicleOne); // รับหลายค่าที่ return มาเป็น array function calculate(a, b) { return [a+b, a-b, a*b, a/b]; } const [add, subtract, multiply, divide] = calculate(4, 7);
push / pop / shift / unshift
4 เมธอดพื้นฐานที่ข้อสอบถามบ่อยที่สุด
const fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.push("Kiwi"); // เพิ่มท้าย → ...,Mango,Kiwi
fruits.push("Kiwi", "Lemon"); // เพิ่มหลายตัวได้
fruits.pop(); // เอาตัวท้ายออก
fruits.shift(); // เอาตัวแรกออก → Orange,Apple,Mango
fruits.unshift("Lemon","Pineapple");// เพิ่มที่ตัวแรก
splice / slice / delete
splice(index ที่จะลบ, จำนวนที่จะลบ) splice(index ที่จะลบ, จำนวนที่จะลบ, ค่าที่จะแทรกเข้าไปแทน) slice(index เริ่ม, index สุดท้าย - 1) // ตัดออกมาเป็น array ใหม่ // ลบตามค่าที่ค้นเจอ const array = [2, 5, 9]; const index = array.indexOf(5); if (index > -1) { array.splice(index, 1); // ลบ 1 ตัวที่ตำแหน่งนั้น } delete fruits[2]; // ลบค่าแต่ทิ้งช่องว่างไว้ (ไม่แนะนำ)
join / concat
const fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.join(); // "Banana,Orange,Apple,Mango" fruits.join(" and "); // "Banana and Orange and Apple and Mango" const arr1 = ["Cecilie", "Lone"]; const arr2 = ["Emil", "Tobias"]; arr1.concat(arr2); // ["Cecilie","Lone","Emil","Tobias"]
indexOf / find / findIndex
| เมธอด | รับอะไร | คืนอะไร |
|---|---|---|
.indexOf(ค่า) | ค่าที่จะค้น | index ถ้าเจอ, -1 ถ้าไม่เจอ |
.find(fn) | ฟังก์ชันเงื่อนไข | ค่าตัวแรกที่ตรง, undefined ถ้าไม่เจอ |
.findIndex(fn) | ฟังก์ชันเงื่อนไข | index ของตัวแรกที่ตรง |
const a = ["a", "b"];
a.find(value => value === "b"); // "b" — array เดิมไม่เปลี่ยน
Callback function
JS โยนฟังก์ชันเป็น parameter ให้ฟังก์ชันอื่นได้
// แบบ sequence — เรียกตรง ๆ ไม่ใช่ callback function myCalculator(num1, num2) { let sum = num1 + num2; myDisplayer(sum); } myCalculator(5, 5); // แบบ callback — โยนฟังก์ชันเข้าไปเป็นพารามิเตอร์ function myDisplayer(some) { document.getElementById("demo").innerHTML = some; } function myCalculator(num1, num2, myCallback) { let sum = num1 + num2; myCallback(sum); } myCalculator(5, 5, myDisplayer);
สังเกตว่าตอนส่งเข้าไปเขียน
myDisplayer เฉย ๆ ไม่ใส่วงเล็บ —
ถ้าใส่วงเล็บจะกลายเป็นการเรียกใช้แล้วส่ง "ผลลัพธ์" เข้าไปแทนmap — แปลงค่าทุกตัว
const numbers = [4, 9, 16, 25];
const newArr = numbers.map(Math.sqrt); // [2, 3, 4, 5]
const numbers2 = [65, 44, 12, 4];
const newArr2 = numbers2.map((num) => { return num + 10; });
ฟังก์ชันที่โยนเข้า map ต้อง return ค่า และ map ได้ array ใหม่ — array เดิมไม่เปลี่ยน
filter — คัดกรอง
const words = ['spray', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter((word) => word.length > 6);
// ['exuberant', 'destruction', 'present']
ฟังก์ชันที่โยนเข้า filter ต้องเป็นเงื่อนไข (คืน true/false)
reduce — ยุบ array ให้เหลือค่าเดียว
array.reduce((prev, curr) => { ... }, ค่าเริ่มต้น)
reduce สะสมค่าไปเรื่อย ๆ จนจบ array
let price = [42, 32, 20]; // ผลรวม let sum = price.reduce(function (prev, curr) { return prev + curr; }, 0); // 94 (ถ้าเริ่มที่ -1 จะได้ 93) // หาค่ามากสุด let max = price.reduce(function (prev, curr) { return prev < curr ? curr : prev; }); // 42 // reduce ใช้แทน filter ได้ let filtered = price.reduce(function (prev, curr) { if (curr > 20) { return [...prev, curr]; } return [...prev]; }, []); // [42, 32] // รวมราคาสินค้าในตะกร้า const cart = [{name:"แซลมอน", price:10}, {name:"หมูทะ", price:1}]; const total = cart.reduce((value, data) => value + data.price, 0); // 11
sort — กับดักที่ต้องระวัง
const numbers = [2, 10, 1, 100, 20];
numbers.sort(); // [1, 10, 100, 2, 20] ← ผิด! เรียงแบบ string
ค่าปริยายของ sort คือแปลงเป็น string ก่อนแล้วเรียงตามตัวอักษร
// วิธีที่ถูก — ใส่ฟังก์ชันเปรียบเทียบ numbers.sort((a, b) => a - b); // น้อยไปมาก [1,2,10,20,100] numbers.sort((a, b) => b - a); // มากไปน้อย
| ผลของ a - b | ความหมาย |
|---|---|
| ค่าลบ | a มาก่อน b |
| ค่าบวก | b มาก่อน a |
| 0 | เท่ากัน คงลำดับเดิม |
JavaScript engine V8 ใช้อัลกอริทึม Timsort ในการ sort ซึ่งเป็นการผสมระหว่าง
Merge Sort + Insertion Sort