16 Powerful Modern JavaScript Features That Truly Surprised Me

13-May-26

คัมภีร์เทพ IT

See the original english version Click here!

 

JavaScript ในปัจจุบันไม่ได้เปลี่ยนแปลงแบบหวือหวาเหมือนยุค ES6 อีกต่อไป แต่กำลังค่อย ๆ พัฒนาไปในทิศทางที่ช่วยให้เขียน Code ที่อ่านง่าย และปลอดภัยมากขึ้นกว่าเดิม บทความนี้จะพาไปรู้จักกับ 16 JavaScript Features ที่ยุคใหม่ที่ช่วยให้เขียน Code ปลอดภัยและอ่านง่ายขึ้น ซึ่ง Dev หลายคนอาจยังไม่เคยใช้ แต่สามารถช่วยยกระดับคุณภาพของ Code ได้อย่างชัดเจนในการทำงานจริง

ES2022 — จุดเริ่มต้นของ JavaScript ยุคใหม่

1. Error.cause

คงมีหลายครั้ง ที่คุณพบว่า Error หนึ่งดันไปเป็นต้นเหตุทำให้เกิดอีก Error หนึ่ง และสุดท้ายบริบทของต้นตอจริง ๆ กลับหายไประหว่างทาง

ก่อนหน้านี้ เรามักเลือกอย่างใดอย่างหนึ่งระหว่าง เขียนทับ Error เดิม หรือใส่ Properties เพิ่มเข้าไปเองแบบ Manual ซึ่งที่จริงก็ไม่ได้ดีนัก

ตอนนี้สามารถใช้:

เราสามารถเชื่อมโยง Error ต้นทางเข้าไปได้โดยตรง

ตัวอย่าง:

ทำให้ Chain ของ Error จะถูกเก็บไว้ครบทั้งหมด

2. Object.hasOwn()

เมื่อก่อน ถ้าเราต้องการตรวจสอบว่า Object หนึ่งมี Property เหล่านี้จริง ๆ หรือไม่

เรามักเขียนแบบนี้:

ถ้าถามว่า มันอ่านง่ายไหม? คำตอบคือ ไม่เลย แล้วถ้าถามว่า มันจำง่ายไหม? คำตอบก็คือ ไม่ เช่นกัน

ตอนนี้สามารถใช้:

คุณจะเห็นว่า มันทั้งสั้นและชัดเจนกว่ามาก

ตัวอย่าง:

มันจะตรวจสอบเฉพาะ Property ของ Object นั้นจริง ๆ ไม่รวม Prototype Chain

3. Top-Level await

ก่อนหน้านี้ ถ้าเราอยากใช้ await เราจำเป็นต้องเขียนมันอยู่ภายใน async Function เท่านั้น

ดังนั้น ต่อให้เป็นงาน Setup ง่าย ๆ เราก็ยังต้อง Wrap ทุกอย่างไว้ใน async Function ซึ่งมันไม่ใช่เรื่องแย่อะไร แต่ก็เป็นขั้นตอนที่เกินความจำเป็น

ตอนนี้สามารถใช้:

ไม่ต้องมี Wrapper ไม่ต้องมี init() Function สามารถเขียน Logic ตรง ๆ ได้เลย

ตัวอย่างที่ 1 — Database Connection

มันเหมาะอย่างมากสำหรับ Backend Script หรือ Node.js Module

ตัวอย่างที่ 2 — Dynamic Imports

สามารถ Load เฉพาะส่วนที่ต้องใช้ โดยไม่ทำให้ Code ยุ่งเหยิง

ตัวอย่างที่ 3 — Load ค่า Environment

มันทำให้ Flow ตอน Startup อ่านง่ายขึ้นมาก

4. Private Class Fields (#)

พูดกันตรง ๆ เลยคือ JavaScript ไม่เคยมี Private Field จริง ๆ

ที่ผ่านมาเรามักตั้งชื่ออย่าง _something แล้วหวังว่าจะไม่มีใครมาแตะต้องมัน แต่นั่นไม่ใช่ Privacy จริง มันก็แค่เป็น Convention เท่านั้น

ตอนนี้สามารถใช้:

แต่ถ้าลองทำแบบนี้:

มันจะ Error ทันที

ตัวอย่าง — Private Methods

จะเห็นว่า Logic ภายในจะยังคงเป็นของภายในจริง ๆ

5. .at() — Relative Indexing

คำถามสุด Classic: จะดึงสมาชิกตัวสุดท้ายของ Array ได้อย่างไร?

พวกเราส่วนใหญ่ น่าจะจำวิธีนี้ได้:

ถึงมันจะใช้งานได้ แต่ก็ไม่สวยสักเท่าไร

ตอนนี้สามารถใช้:

จะเห็นว่า มันอ่านง่ายขึ้นเยอะ

ES2023 — ก้าวสำคัญสู่การจัดการข้อมูลที่ปลอดภัยขึ้น

6. toSorted()

Array.sort() มีประโยชน์มาก แต่ปัญหาคือ มันดันไปเปลี่ยนแปลง Array ต้นฉบับโดยตรง (Mutation) และถ้ามีคนลืมเรื่องนี้เพียงแค่ครั้งเดียว ก็อาจทำให้ State พังได้ในทันที เราก็เลยต้อง Clone Array เองตลอดเวลา

วิธีเดิม:

แม้มันจะใช้งานได้ แต่ต้องเขียนซ้ำ ๆ บ่อยมาก

ตอนนี้สามารถใช้:

จะเห็นว่า ไม่มี Mutation และไม่ต้อง Clone เอง

ตัวอย่าง:

สิ่งที่เปลี่ยนไป:

คุณจะได้ “สำเนาที่ถูก Sort แล้ว” โดยไม่แตะต้องข้อมูลต้นฉบับเลย

7. toReversed() และ toSpliced()

หลักการเดียวกับ toSorted(): มันจะทำการ “Copy” แทนที่จะ Mutation

Reverse (โดยไม่แตะต้อง Array เดิม):

แต่ถ้าใช้วิธีเดิม:

Splice (แต่ไม่ Mutation):

แต่ถ้าใช้วิธีเดิม:

ทำให้ตอนนี้ข้อมูลต้นฉบับ ยังคงปลอดภัย

8. findLast() / findLastIndex()

เราน่าจะใช้งาน find() กันมานานแล้ว แต่ถ้าเราต้องการ “สมาชิกตัวสุดท้าย” ที่ Match กับเงื่อนไขล่ะ

เมื่อก่อน มักต้องเขียนแบบนี้:

เริ่มจาก Clone, Reverse แล้วค่อย Find

ซึ่งที่จริง มันก็ไม่ได้เลวร้ายอะไรนัก แต่มันทั้งยุ่งยากและทำให้สับสนได้ง่าย (โดยเฉพาะสำหรับมือใหม่)

ตอนนี้สามารถใช้:

หรือถ้าต้องการตำแหน่งของมัน:

ไม่ต้อง Reverse ไม่ต้อง Clone แถมอ่านแล้วเข้าใจทันที ว่า Code ต้องการทำอะไร

ES2024 — การจัดการข้อมูลและ Async ที่ฉลาดขึ้น

9. Object.groupBy()

เมื่อก่อน ถ้าจะ Group Array เรามักต้องเขียน Reducer ที่ดูซับซ้อนกว่างานจริงเสียอีก

วิธีเดิม:

มันก็ใช้งานได้ แต่ครั้งแรกที่เห็น ก็ไม่ได้ทำให้รู้สึกว่า อ่านง่ายนัก

วิธีใหม่:

แค่นั้นเอง

ตัวอย่าง:

ผลลัพธ์:

10. Promise.withResolvers()

บางครั้งเราต้องการ Resolve หรือ Reject Promise จากภายนอก ซึ่งที่ผ่านมา วิธีทำมันดู… แปลก ๆ อยู่เสมอ

วิธีเดิม:

ถึงมันจะทำงานได้ แต่ก็ยังไม่ใช่วิธีที่ดีที่สุด

ตอนนี้สามารถใช้:

มันทั้ง ชัดเจน ตรงไปตรงมา แถมไม่ต้องใช้เทคนิคพิเศษอะไรเพิ่มเติม

ตัวอย่าง:

มันเหมาะมากสำหรับ Event-Driven Flow

11. Resizable ArrayBuffer

เมื่อก่อน ArrayBuffer มีขนาดตายตัว

เมื่อสร้างแล้วก็จะมีขนาดเท่านั้นเลย ไม่สามารถขยายและลดขนาดได้อีกแล้ว ซึ่งเป็นเรื่องที่น่าหงุดหงิดมากเวลาที่ต้องทำงานกับ Streaming Data, Workers หรือการทดลองทำอะไรกับข้อมูลแบบ Binary

ตอนนี้สามารถใช้:

เราสามารถ Resize ภายหลังได้แล้ว

ตราบใดที่ยังไม่เกิน maxByteLength

ES2025 — เมื่อ Functional Patterns กลายเป็นเรื่องปกติ

12. Iterator Helpers

Array Methods นั้นยอดเยี่ยมมาก แต่ทุกครั้งที่ใช้ .map(), .filter() หรือ .slice() มันจะสร้าง Array ใหม่เสมอ

ซึ่งสำหรับข้อมูลเล็ก ๆ แล้ว อาจจะไม่เป็นไร แต่ถ้ากับ Dataset ที่มีขนาดใหญ่ นั่นคือ ภาระที่เพิ่มขึ้นมาทันที

วิธีเดิม (สร้าง Array หลายรอบ):

แต่ละขั้นตอน จะมีการสร้าง Array ใหม่ขึ้นมา

วิธีใหม่ (Lazy Processing):

ข้อมูลจะยังไม่ถูก Process จนกว่าจะถูกใช้งานจริง

สิ่งที่มันเข้ามาแทนที่คือ:

  • การเขียน Generator Pipeline เองแบบ Manual
  • การ Chain Array หลายขั้นที่กิน Performance
  • การสร้าง Array ระหว่างทางโดยไม่จำเป็น

13. Set Methods ใหม่

เมื่อก่อน การทำงานกับ Set Operations มักต้องผ่านหลายขั้นตอน โดยเรามักต้อง:

  • Convert เป็น Array
  • เขียน Filter เอง
  • แล้วค่อยแปลงกลับไปเป็น Set

ซึ่งยังไม่ใช่วิธีที่ดูดีที่สุด

วิธีเดิม:

แม้จะอ่านเข้าใจได้ แต่ก็ค่อนข้างยาว

แต่ตอนนี้สามารถใช้:

จะเห็นว่ามันทั้งชัดเจน ตรงไปตรงมา และให้ความรู้สึกเหมือนนิยามทางคณิตศาสตร์จริง ๆ

ตัวอย่าง:

14. RegExp.escape()

การสร้าง Regex จาก Input ของ User เป็นเรื่องที่เสี่ยงมาตลอด

Character พิเศษอย่าง *, ., (, [ อาจทำให้ Pattern ผิดเพี้ยน หรือแย่กว่านั้นคือ อาจก่อให้เกิดปัญหาด้าน Security

วิธีเดิม:

ต้องเขียน Helper สำหรับ Escape เองแทบทุกครั้ง

ตอนนี้สามารถใช้:

จะเห็นว่า มันทั้งใช้งานง่าย, เป็น Built-in และปลอดภัยกว่าเดิม

15. Promise.try()

บางครั้งเราอยากจัดการ Sync และ Async Code ด้วยวิธีเดียวกัน เพราะ Function แบบ Sync อาจ Throw Error กลับมาทันที ในขณะที่ Async Function จะ Reject

แต่ปัญหาคือ พอมีทั้งสองแบบปนกัน ก็จะเริ่มมีความยุ่งยากในเรื่อง Error Handling

วิธีเดิม:

หรือ Wrap แบบ Manual เอง:

ซึ่งอาจดูแปลก ๆ อยู่บ้าง

ตอนนี้สามารถใช้:

ไม่ว่า Function จะ Return ตามปกติ หรือ Throw Error ก็ตาม มันจะถูกแปลงเป็น Promise ให้โดยอัตโนมัติ

ตัวอย่าง:

จะเห็นว่า ตอนนี้ไม่ต้องสนใจแล้วว่า Function นั้นจะ Throw Error หรือ Reject

16. Float16 Support

ปกติ Number ของ JavaScript จะเป็นแบบ 64-bit ซึ่งก็เหมาะกับงานส่วนใหญ่ แต่สำหรับงานที่เน้น Performance สูง มันอาจเกินความจำเป็น

ที่ผ่านมาเรามี Float32Array อยู่แล้ว แต่ตอนนี้ JavaScript ลดลงไปอีกขั้น

มันมีการรองรับ Half-Precision Floating Point แบบ 16-bit แล้ว

สิ่งที่มันหมายถึงจริง ๆ คือ:

  • ใช้พื้นที่เก็บข้อมูลน้อยลง (16-bit)
  • ลดการใช้ Memory
  • ส่งข้อมูลไป GPU / ML ได้เร็วขึ้น
  • Buffer มีขนาดกะทัดรัดขึ้น

ตัวอย่าง:

เมื่อทำงานกับ Dataset ขนาดใหญ่ ความแตกต่างในเรื่องของขนาดจะเริ่มเห็นได้ชัดเจนมากขึ้น

ถ้าลองถอยออกมา เพื่อมองภาพรวม เราจะเห็น Pattern ที่ชัดมากขึ้น:

  • Mutation น้อยลง
  • จุดประสงค์ของ Code แต่ละส่วนชัดเจนขึ้น
  • Async Control ปลอดภัยขึ้น
  • การจัดการข้อมูลเริ่มไปทาง Functional มากขึ้น

JavaScript ไม่ได้กำลังเข้าสู่ยุค “ปฏิวัติครั้งใหญ่” แต่กำลังถูกพัฒนาปรับปรุงในสิ่งที่มีขนาดเล็กลง แต่สามารถใช้งานได้จริง เช่น

  • Methods ขนาดเล็ก
  • API ที่ Clean ขึ้น
  • Default ที่ดีขึ้น

แม้จะไม่มีอะไรที่หวือหวามากมาย แต่เป็นการอัปเกรดเล็ก ๆ น้อย ๆ ในการใช้งานประจำวันที่ช่วยให้ Code อ่านง่าย, ดูแลรักษาง่าย และทำความเข้าใจได้ง่ายขึ้น

สรุป

และนี่ก็เป็น 16 JavaScript Features ยุคใหม่ที่ช่วยให้เขียน Code ปลอดภัยและอ่านง่ายขึ้น ซึ่งสิ่งที่น่าสนใจของ JavaScript ยุคใหม่ ไม่ใช่การเพิ่ม Syntax ที่ซับซ้อนขึ้น แต่เป็นการออกแบบ Feature เล็ก ๆ ที่ช่วยลด Mutation ทำให้ Intent ของ Code ชัดขึ้น และทำให้การจัดการข้อมูลหรือ Async Flow เป็นธรรมชาติมากกว่าเดิม และเมื่อรวมกัน Features เหล่านี้ก็คืออีกหนึ่งก้าวสำคัญที่ช่วยให้ Dev เขียน Code ได้ปลอดภัย อ่านง่าย และดูแลรักษาได้ง่ายขึ้นในระยะยาว

ที่มา:  https://medium.com/
 

 

รับตำแหน่งงานไอทีใหม่ๆ ด้วยบริการ IT Job Alert

 

อัพเดทบทความจากคนวงในสายไอทีทาง LINE ก่อนใคร
อย่าลืมแอดไลน์ @techstarth เป็นเพื่อนนะคะ

เพิ่มเพื่อน

 

บทความล่าสุด