Concise Object Methods และ ArrowFunctions

Concise Object Methods

Concise Object Methods คือฟีเจอร์ที่อนุญาติให้คุณตัดคำว่า “:function” ออกจาก code ได้

ดังตัวอย่างต่อไปนี้

สามารถเปลี่ยนเป็น

ดูสวยกว่ามั๊ยครับ (ผมว่าสวยกว่านะ)

Arrow functions

ฟีเจอร์อันโด่งดังของ ES6 ที่ผมเคยเกลียดมันอยู่นาน แต่พอทำความคุ้นเคยกับมันได้แล้ว ก็เริ่มรักมันนิดๆ

สาเหตุที่ทำไมถึงต้องมีเจ้าตัว Arrow Function อยู่ภายใน ES6 ด้วยนั้น เพราะเหตุผลสำคัญประการเดียวเลยครับนั่นคือ มันช่วยในเรื่องการใช้ “this” ใน scope อื่นๆ ให้เป็น “this” ตัวเดียวกับ scope ของแม่มัน (หรือพูดให้สั้นๆ ว่า เป็น scope ของแม่ม!!!)

บางคนบอกว่า Arrow Function มันช่วยให้ code ดูง่ายขึ้น และสื่อความดีขึ้น ซึ่งอันนี้ผมเฉยๆ เพราะหลายคนไม่ได้รู้สึกแบบนั้น โดยเฉพาะอย่างยิ่งคนที่ไม่เคยรู้จัก ES6 มาก่อน จะต้องร้องออกมาดังๆ เมื่อเห็น Arrow Function ว่า “เชี่ย อะไรวะเนี่ย”

เอ้า มาดูตัวอย่างจาก code ของจริงกันเลยดีกว่า โดยเราจะตั้งต้นจาก code ตัวนี้

code ข้างบนมี error คุณผู้อ่านหาเจอมั๊ย?

กุญแจอยู่ตรงนี้ประโยคที่ว่า

ปัญหาของประโยคนี้ก็คือ มันถูกวางอยู่ภายใต้ this.state.friends.map(function… ซึ่งถือเป็น scope ของ callback function แปลว่า this ภายใต้ callback function จะไม่ใช่ this ของตัวแม่มัน ดังนั้น การเขียน this.onAddFriend จะต้องเกิด error วิธีแก้ขั้นต้นก็คือ ให้เติม .bind(this) เข้าไปต่อท้ายของ callback function ตัวนี้

แต่ ES6 มีวิธีแก้ปัญหาที่สวยงามกว่านั้นครับ นั่นคือ การใช้ Arrow Function ด้วยเหตุที่ว่า Arrow Function นั้นจะไม่กำหนด scope ใหม่ขึ้นมาเหมือน callback function ทั่วไป ดังนั้น this ที่อยู่ภายใต้ arrow function จะเป็น this ตัวเดียวกับที่อยู่ภายนอกฟังก์ชั่น map

โดยวิธีเขียนสามารถเขียนได้ดังนี้

Arrow Function ยังมีประโยชน์อีกข้อนึงนั่นคือ หากนำ code ภายใต้ arrow function เขียนไว้บนบรรทัดเดียวกัน โดยตัด { } และคำว่า return ออกไป arrow function จะทำการ return สิ่งที่เราเขียนไว้ในบรรทัดดังกล่าวโดยอัตโนมัติให้ ซึ่งสามารถเขียนได้ดังนี้

จาก code ข้างต้น หากทำ arrow function แบบบรรทัดเดียว มันจะทำการ return ค่าดังต่อไปนี้โดยปริยาย

Project refactoring

ได้เวลานำหลักการ Concise Object และ Arrow Function มาใช้เพื่อ reactor ระบบของเราแล้ว

เริ่มต้นจากไฟล์ app/components/Loading.js ให้แก้ code เพื่อให้เป็นไปตามหลัก concise ดังนี้

จากนั้นให้ทำการปรับแก้ code ในฟังก์ชั่น componentDidMount ให้เป็นไปตามหลักของ Arrow Function ดังนี้

สังเกตมั๊ยครับว่า code มันดูสะอาดขึ้น (นิสนึง) ตรงที่ไม่มีตัว .bind(this) มาให้รกสายตาแล้ว แต่มันก็ต้องแลกมากับ syntax ประหลาดๆ อย่าง () => { ซึ่งหากเรารู้จัก arrow function แล้วก็ไม่น่าจะใช่เรื่องใหญ่อะไรมากมาย

จากนั้นให้เปิดไฟล์ app/components/Main.js แล้วแก้ code ให้เป็นดังนี้

นั่นคือการแก้ให้ฟังก์ชั่น render มีความเป็น concise มากขึ้น

จากนั้นให้เปิดไฟล์ app/containers/ConfirmBattleContainer.js แล้วปรับให้ทุกฟังก์ชั่นเป็น concise object ดังนี้

และในฟังก์ชั่น componentDidMount ให้ปรับแก้ code ให้กลายเป็น arrow function ดังนี้

จากนั้นให้เปิดไฟล์ app/containers/ResultsContainer.js ขึ้นมา แล้วปรับแก้ดังนี้

จากนั้นให้เปิดไฟล์ app/utils/githubHelper.js ขึ้นมา แล้วให้เริ่มทำการแก้ทีละฟังก์ชั่นดังนี้

เริ่มจากฟังก์ชั่น getTotalStarts ก่อน

จะเห็นว่า การใช้ arrow function จะช่วยลดจำนวน code ไปได้เยอะพอควร โดยอาศัยเพียงข้อแม้เดียวเท่านั้นคือ สมาชิกภายในทีมของเราต้องเข้าใจ code แบบนี้ด้วย

ต่อมาแก้ที่ getPlayersData

นี่คือการเขียน Arrow Function ในแบบที่ยังคงโครงสร้างเดิมไว้ นั่นคือ มี { } ครอบไว้ และมีการ return

และตัวสุดท้าย พระเอกของเรา const helpers

ถามจริงๆ เลยนะครับ code มันดูอ่านง่ายขึ้น และสะอาดตาขึ้นมั๊ยครับ ที่สำคัญ code มันดูกระชับและลดโอกาสเกิด bug กว่าเดิมด้วย

แก้ทั้งหมดแล้ว อย่าลืมลองทดสอบระบบจริงดูนะครับ ว่าการ refactor ของเรากระทบกับระบบหรือไม่

สำหรับใครที่อยากได้ code ต้นแบบ สามารถเข้าไปดูได้ที่

https://github.com/himaeng/react-fun-course/tree/master/ES03-arrow-functions

สรุป

เนื้อหาในตอนนี้จะพูดถึงฟีเจอร์ของ ES6 สองตัวนั่นคือ Concise Object Method หรือการตัดคำว่า :function ออกจาก code นั่นเอง

และ Arrow function ที่ช่วยในเรื่องของการจัดการ this ให้มันดูง่ายขึ้น โดยไม่ต้องใช้ .bind(this) สำหรับ callback function แล้ว อีกทั้งยังสามารถช่วยลดรูปของฟังก์ชั่นจนมี code ที่กระชับขึ้นได้อีกด้วย

1 COMMENT