Best Practices ในการเขียน JavaScript
หลังจากที่เราได้เรียนรู้พื้นฐานของ JavaScript, การใช้งาน Promises, Async/Await, การจัดการ Error, Modules และกระทั่งการทำ Unit Test ด้วย Jest แล้ว สิ่งที่สำคัญไม่แพ้กันคือการเขียนโค้ดให้มีคุณภาพ อ่านง่าย บำรุงรักษาได้ง่าย และมีประสิทธิภาพสูง ซึ่งบทความนี้จะกล่าวถึงแนวทางปฏิบัติที่ดี (Best Practices) ในการเขียน JavaScript เพื่อให้โค้ดของคุณทั้งสวยงามและแข็งแกร่ง
Code Style
Code Style คือชุดของกฎเกณฑ์ที่กำหนดรูปแบบการเขียนโค้ด เพื่อให้โค้ดมีความสอดคล้องกัน อ่านง่าย และเข้าใจได้ง่าย ไม่ว่าใครก็ตามที่เข้ามาอ่านโค้ดของคุณก็จะสามารถเข้าใจได้ทันทีว่าโค้ดนี้ทำงานอย่างไร
การใช้ Linters และ Formatters
Linters และ Formatters เป็นเครื่องมือที่จะช่วยให้เราเขียนโค้ดตาม Code Style ที่กำหนดได้อย่างอัตโนมัติ
- ESLint: เป็น Linter ที่ได้รับความนิยมมากที่สุดใน JavaScript ช่วยตรวจสอบโค้ดของเราว่ามีข้อผิดพลาดหรือไม่ และแนะนำแนวทางการแก้ไข
- Prettier: เป็น Code Formatter ที่ช่วยจัดรูปแบบโค้ดของเราให้สวยงามและสอดคล้องกัน
การใช้ ESLint และ Prettier ร่วมกันจะช่วยให้เราเขียนโค้ดที่มีคุณภาพสูงได้ง่ายขึ้น
// ตัวอย่างการใช้งาน ESLint และ Prettier
// ไม่ดี:
function myFunction( param1,param2 ) {
if(param1>param2){
return param1;
}else{
return param2;}
}
// ดี:
function myFunction(param1, param2) {
if (param1 > param2) {
return param1;
} else {
return param2;
}
}
การตั้งชื่อตัวแปรและฟังก์ชัน
การตั้งชื่อตัวแปรและฟังก์ชันให้สื่อความหมายเป็นสิ่งสำคัญอย่างยิ่ง เพราะจะช่วยให้ผู้อื่น (รวมถึงตัวเราเองในอนาคต) เข้าใจได้ง่ายว่าตัวแปรหรือฟังก์ชันนั้นมีหน้าที่อะไร
- ตัวแปร: ควรใช้ camelCase เช่น `firstName`, `userAge`
- ค่าคงที่ (const): ควรใช้ UPPER_SNAKE_CASE เช่น `API_KEY`, `MAX_USERS`
- ฟังก์ชัน: ควรใช้ camelCase และตั้งชื่อให้สื่อถึงการกระทำ เช่น `calculateTotal`, `getUserData`
- Class: ควรใช้ PascalCase เช่น `UserProfile`, `OrderDetails`
หลีกเลี่ยงการใช้ชื่อตัวแปรหรือฟังก์ชันที่สั้นเกินไป หรือไม่สื่อความหมาย เช่น `x`, `y`, `foo`, `bar`
// ไม่ดี:
const x = 10;
function f(a, b) {
return a + b;
}
// ดี:
const numberOfItems = 10;
function calculateSum(num1, num2) {
return num1 + num2;
}
การเขียน Comments
Comments เป็นสิ่งจำเป็นในการอธิบายโค้ดที่ซับซ้อน หรืออธิบายเหตุผลเบื้องหลังการตัดสินใจบางอย่างในการเขียนโค้ด
- เขียน Comments เฉพาะเมื่อจำเป็นเท่านั้น ไม่จำเป็นต้อง Comment ทุกบรรทัด
- เขียน Comments ที่อธิบาย "ทำไม" มากกว่า "อะไร"
- รักษา Comments ให้เป็นปัจจุบันเสมอ เมื่อมีการแก้ไขโค้ด ก็ควรแก้ไข Comments ให้สอดคล้องกัน
// ไม่ดี:
// กำหนดค่า x เป็น 10
let x = 10;
// ดี:
// กำหนดจำนวนสูงสุดของรายการที่อนุญาต
const MAX_ITEMS = 10;
Performance Optimization
การเขียนโค้ด JavaScript ที่มีประสิทธิภาพสูงเป็นสิ่งสำคัญอย่างยิ่ง โดยเฉพาะอย่างยิ่งเมื่อเราพัฒนา Web Applications ที่มีผู้ใช้งานจำนวนมาก หรือทำงานบนอุปกรณ์ที่มีทรัพยากรจำกัด
การหลีกเลี่ยง Global Variables
การใช้ Global Variables มากเกินไปอาจทำให้เกิดปัญหา Performance ได้ เนื่องจาก Global Variables ถูกเก็บไว้ใน Global Scope ซึ่งการเข้าถึง Global Variables จะช้ากว่าการเข้าถึง Local Variables
นอกจากนี้ Global Variables ยังอาจทำให้เกิดปัญหา Namespace Collision ได้ ซึ่งหมายถึงการที่ตัวแปรสองตัวที่มีชื่อเดียวกันอยู่ใน Scope เดียวกัน ทำให้เกิดข้อผิดพลาดในการทำงานของโปรแกรม
// ไม่ดี:
let globalVariable = "Hello";
function myFunction() {
globalVariable = "World";
}
// ดี:
function myFunction() {
let localVariable = "World";
// ...
}
การใช้ Loops อย่างมีประสิทธิภาพ
Loops เป็นส่วนสำคัญของการเขียนโปรแกรม แต่การใช้ Loops อย่างไม่มีประสิทธิภาพอาจทำให้โปรแกรมทำงานช้าลงได้
- หลีกเลี่ยงการคำนวณค่าคงที่ภายใน Loop
- ใช้ `for` loop แทน `forEach` loop เมื่อต้องการประสิทธิภาพสูงสุด
- ใช้ `while` loop เมื่อไม่ทราบจำนวนรอบที่แน่นอน
// ไม่ดี:
const array = [1, 2, 3, 4, 5];
for (let i = 0; i < array.length; i++) {
// คำนวณ array.length ทุกครั้งที่วนซ้ำ
console.log(array[i]);
}
// ดี:
const array = [1, 2, 3, 4, 5];
const arrayLength = array.length;
for (let i = 0; i < arrayLength; i++) {
// คำนวณ arrayLength เพียงครั้งเดียว
console.log(array[i]);
}
การใช้ Memoization
Memoization เป็นเทคนิคในการ Cache ผลลัพธ์ของการคำนวณที่ซับซ้อน เพื่อนำกลับมาใช้ใหม่ในภายหลัง โดยไม่ต้องคำนวณซ้ำ
// ตัวอย่างการใช้ Memoization
function memoize(func) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
} else {
const result = func(...args);
cache[key] = result;
return result;
}
};
}
function fibonacci(n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
const memoizedFibonacci = memoize(fibonacci);
console.log(memoizedFibonacci(10)); // คำนวณครั้งแรก
console.log(memoizedFibonacci(10)); // ดึงจาก Cache
Security Considerations
การรักษาความปลอดภัยของ Web Applications เป็นสิ่งสำคัญอย่างยิ่ง เพื่อป้องกันการโจมตีจากผู้ไม่หวังดี
การป้องกัน Cross-Site Scripting (XSS)
XSS เป็นการโจมตีที่ผู้ไม่หวังดีแทรก Script ที่เป็นอันตรายลงใน Web Applications ของเรา เพื่อขโมยข้อมูล หรือเปลี่ยนแปลงพฤติกรรมของ Web Applications
วิธีการป้องกัน XSS คือการ Escape ข้อมูลที่รับมาจากผู้ใช้ ก่อนที่จะนำไปแสดงผลใน Web Applications
// ตัวอย่างการ Escape ข้อมูล
function escapeHtml(str) {
let div = document.createElement('div');
div.appendChild(document.createTextNode(str));
return div.innerHTML;
}
const userInput = "<script>alert('XSS')</script>";
const escapedInput = escapeHtml(userInput);
// นำ escapedInput ไปแสดงผลใน Web Applications
document.getElementById("output").innerHTML = escapedInput;
การป้องกัน Cross-Site Request Forgery (CSRF)
CSRF เป็นการโจมตีที่ผู้ไม่หวังดีปลอมแปลง Request จากผู้ใช้ เพื่อกระทำการบางอย่างในนามของผู้ใช้
วิธีการป้องกัน CSRF คือการใช้ CSRF Token ซึ่งเป็น Token ที่ Generate ขึ้นมาแบบสุ่ม และส่งไปพร้อมกับ Request ทุกครั้ง
// ตัวอย่างการใช้ CSRF Token (ฝั่ง Server)
// สร้าง CSRF Token
const csrfToken = generateCsrfToken();
// ส่ง CSRF Token ไปยัง Client
res.cookie('csrfToken', csrfToken);
// ตรวจสอบ CSRF Token ใน Request
if (req.body.csrfToken !== req.cookies.csrfToken) {
return res.status(403).send('Invalid CSRF token');
}
การหลีกเลี่ยงการใช้ `eval()`
ฟังก์ชัน `eval()` เป็นฟังก์ชันที่อันตราย เพราะสามารถ Execute Code ที่เป็น String ได้ ซึ่งอาจทำให้เกิดช่องโหว่ด้านความปลอดภัยได้
หลีกเลี่ยงการใช้ `eval()` หากไม่จำเป็นจริงๆ และถ้าจำเป็นต้องใช้ `eval()` จริงๆ ควรตรวจสอบ Input ให้ดีก่อนที่จะนำไป Execute
// ไม่ดี:
const userInput = "alert('Hello')";
eval(userInput);
// ดีกว่า:
// ใช้วิธีอื่นที่ไม่ต้องใช้ eval()
การปฏิบัติตาม Best Practices เหล่านี้จะช่วยให้คุณเขียน JavaScript ที่มีคุณภาพสูง มีประสิทธิภาพ และปลอดภัย ซึ่งจะส่งผลดีต่อการพัฒนา Web Applications ในระยะยาว