- การประกาศฟังก์ชันใน JavaScript มีได้หลายรูปแบบ เช่น การประกาศด้วยคีย์เวิร์ด
function, function expression, และ arrow function
- function declaration ได้รับผลของ hoisting จึงสามารถอ้างอิงได้จากตำแหน่งใดก็ได้ในโค้ด
- Arrow function มีข้อดีคือ ไวยากรณ์ที่กระชับ แต่ก็มีความแตกต่างสำคัญ เช่น ไม่มีการ bind
this/arguments/super
- constructor function, generator, method ไม่เหมาะกับการใช้ arrow function
- callback แบบง่ายหรือ anonymous function เหมาะกับ arrow function มากกว่า
Function Declarations, Function Expressions, and Arrow Functions
- ใน JavaScript สามารถนิยามฟังก์ชันได้ 3 แบบ คือ function declaration (statement), function expression, และ arrow function
- function declaration จะ bind ชื่อโดยตรง เช่น
function isVowel(chr) { ... } และ สามารถอ้างอิงได้จากทุกตำแหน่งในโค้ด (hoisting) อีกทั้งยังแสดงชื่อฟังก์ชันอย่างชัดเจนใน stack trace และระหว่าง debugging
- function expression คือรูปแบบที่กำหนด anonymous function ให้กับตัวแปร เช่น
const takeWhile = function(predicate, arr) { ... }
- function expression สามารถตั้งชื่อภายในได้เช่นกัน แต่ ชื่อนั้นจะไม่ถูก bind ในสโคปภายนอก และมักใช้เพื่อ ช่วยติดตามข้อผิดพลาดใน stack trace
Hoisting and Naming
- function declaration จะถูก hoist โดย JavaScript engine จึงยังทำงานได้แม้จะเรียกใช้ก่อนตำแหน่งที่ประกาศ
- anonymous function expression จะเรียกใช้ได้ก็ต่อเมื่อมีการกำหนดค่าให้ตัวแปรแล้วเท่านั้น
- เพื่อการ debug การ ตั้งชื่อฟังก์ชันอย่างชัดเจน อาจช่วยให้ stack trace อ่านง่ายขึ้น
Arrow Functions
Practical Example: this, constructor และ generator
- มีตัวอย่างแสดงความแตกต่างของการจัดการ
this ระหว่างฟังก์ชันปกติกับ arrow function
- เมื่อใช้เป็นเมธอดภายในอ็อบเจ็กต์ ฟังก์ชันปกติจะมี
this ชี้ไปที่ตัวอ็อบเจ็กต์เอง แต่ arrow function จะชี้ไปที่ undefined หรือ this จากสโคปภายนอก
- หากนิยาม constructor function ด้วย arrow function จะเกิด TypeError
- generator function จำเป็นต้องใช้ไวยากรณ์
function* เท่านั้น
ควรเลือกใช้ไวยากรณ์ฟังก์ชันแบบไหนเมื่อไร?
- ต้องการ generator (ใช้
yield) → ใช้ function*
- ต้องใช้
this → ใช้คีย์เวิร์ด function หรือ class method
- ต้องการ hoisting หรืออยากให้โค้ดระดับบนอ่านง่าย → ใช้ function declaration
- หากไม่เข้าข่ายข้างต้น → เขียนด้วย arrow function จะกระชับกว่า
บทสรุป
- ฟังก์ชันใน JavaScript ควรเลือกไวยากรณ์ตามจุดประสงค์การใช้งาน ความจำเป็นของ
this และการเป็น constructor/generator
- callback ทั่วไปหรือฟังก์ชันง่าย ๆ เหมาะกับ arrow function มากที่สุด
- object method/constructor/generator จำเป็นต้องใช้ไวยากรณ์
function
- หากต้องการ hoisting หรือความยืดหยุ่นในลำดับการประกาศ function declaration จะได้เปรียบ
3 ความคิดเห็น
เรื่องความมีหรือไม่มี prototype ก็สำคัญพอๆ กับพื้นฐาน ...
รวมถึงวิธีอ้างอิงของฟังก์ชันลำดับสูงที่ถูกสร้างขึ้นด้วย ...
const a = (a: () => null): (() => () => null) =>() => a
() => ❤️