ประกาศตัวแปรด้วย let และ const

ใน Javascript เวลาจะทำการประกาศตัวแปร เราจะประกาศโดยใช้ var เพียงอย่างเดียวเท่านั้น ปัญหาของการใช้ var ก็คือ มันจะทำให้คุณงงสุดๆ เมื่อเจอกับข้อจำกัดด้าน scope ของ javascript ดังตัวอย่างต่อไปนี้

ภายใน code ข้างต้นนั้น มี 3 scope ได้แก่ scope ของ Global, scope ของ firstFunction และ scope ของ secondFunction

คราวนี้ลองมาดูว่า var มันสร้างความงงให้กับชีวิตของ dev. ยังไงบ้าง

จะเห็นว่า console.log(secondNum) นั้น อยู่ภายนอก scope ของ if (num >= 0) แต่กลับสามารถ access ค่าของ secondNum ได้ ทั้งๆ ที่ตามสามัญสำนึกแล้ว ไม่ควรจะเป็นแบบนั้นได้เลย

ความเข้าใจในเรื่องของ scope นั้น จะช่วยให้เราสามารถทำความเข้าใจในเรื่องความแตกต่างระหว่างการประกาศตัวแปรด้วย var กับ let ได้ง่ายขึ้น

let คือการประกาศตัวแปรที่อ้างอิง scope เป็นหลัก แบบเดียวกันกับมาตรฐานของภาษาอื่น มาดูตัวอย่างกันเลยดีกว่า

จะเห็นว่า ตัวแปร secondNum ถูกประกาศด้วย let ภายใต้ scope ของ if (num >= 0) ทำให้การเรียกใช้งาน secondNum นอก scope ดังกล่าวไม่สามารถทำได้ (แต่ var อนุญาติให้ทำได้) ซึ่งแบบนี้ทำให้คนที่มีพื้นมาจากภาษาอื่นไม่งง เพราะชาวบ้านเขาก็ทำแบบนี้กันหมดอยู่แล้ว มีแต่ javascript นี่แหละ ที่มันแปลกๆ โชคดีที่ตอนนี้เรามี let มาช่วยชีวิตเราไว้แล้ว

ต่อมาก็เรื่องของการประกาศตัวแปรด้วย const

const นั้นมีคุณสมบัติเหมือนกับ let ทุกอย่างยกเว้นเพียงเรื่องเดียวก็คือ มันเป็นตัวแปรที่จะไม่สามารถเปลี่ยนแปลงค่าได้อีก (const ก็ย่อมาจาก constant นั่นแหละ)

แต่หากเป็นกรณีที่ตัวแปรแบบ const ถูก assign ด้วย object ที่ไม่ใช่ primitive value จะมีข้อยกเว้นบางอย่าง กล่าวคือ ถึงแม้ตัวแปรที่ประกาศด้วย const จะไม่สามารถเปลี่ยน reference ของมันให้ไปชี้ที่ object ใหม่ได้อีก แต่ไม่ได้หมายความว่าตัวออบเจ็กท์นั้นจะเปลี่ยนแปลงไม่ได้ งงมั๊ย!

มาดูตัวอย่างกัน

การเขียนแบบ code ข้างบนนั้นถูกต้องทุกประการ เพราะเราไม่ได้เปลี่ยน reference ของ customer ให้ชี้ไปที่ object ใหม่ เพียงแต่มีการแก้ไขข้อมูลภายใน customer object เท่านั้น

แต่หากเราเขียน code ดังต่อไปนี้

คราวนี้ javascript จะแสดง exception “customer is already defined” ออกมา เนื่องจากเราได้พยายามที่ทำการเปลี่ยน reference ของ customer ซึ่งเป็นตัวแปรแบบ const หรือตัวแปรที่เป็นค่าคงที่นั่นเอง

คำถามก็คือ แล้วเราจะใช้ตัวไหนดี? โดยปรกติแล้ว ส่วนใหญ่มักจะเริ่มต้นด้วยการใช้ const แล้วเมื่อใดที่รู้ว่าตัวแปรนั้นๆ จะต้องมีการเปลี่ยนแปลงในภายหลัง ก็ค่อยเปลี่ยนมาเป็น let ส่วน var หากเลิกใช้ได้ ก็ควรเลิกใช้ไปซะ

เขียน code ให้สั้นลงด้วย Object Destructuring

คำว่า Object Destructuring คือการ “ทุบโครงสร้าง” ของ object ให้แตกออก (ฟังแล้วงงกว่าเดิมมั๊ยครับ)

เอางี้ เรามาดูตัวอย่าง code กันเลยดีกว่า

props คือ object ตัวหนึ่ง หากมองด้วยตาเปล่าแล้ว เราไม่มีทางรู้หรอกว่า props มีอะไรอยู่ข้างในบ้าง ดังนั้น หากเราเขียนฟังก์ชั่นแบบประกาศให้ผู้อ่านรู้กันโต้งๆ ไปเลยว่า props มันมีอะไรอยู่ภายในนั้นบ้างก็คงจะดีไม่น้อย

สมมตินะครับสมมติ สมมติว่า React ยังไม่ PropTypes แต่เราดันอยากแสดงข้อมูลต่างๆ ของ props เราก็อาจจะเขียน function แบบนี้

ดีขึ้นมั๊ยครับ ปัญหาคือ แม่งเป็นฟังก์ชั่นที่โคตรน่าเกลียดเลย

อย่างที่บอกไปในตอนต้นแล้วว่า Object Destructuring คือการทุบโครงสร้างของ object ออกมา แล้วเอาสิ่งที่อยู่ภายในมาประกาศให้โลกภายนอกได้รู้

เราสามารถเอา Object Destructuring มา “ศัลยกรรม” code ข้างบนให้ดูดีขึ้นได้ ดังนี้

คราวนี้ดูดีขึ้นมั๊ยครับ วิธีการนั้นง่ายมาก ก็แค่เอา object ซักตัวที่เราอยากจะ “ทุบ” มา assign ใส่ properties หลายๆ ตัวที่มีชื่อเดียวกัน และในขณะเดียวกัน properties เหล่านั้นก็จะกลายมาเป็น local variable ไปในตัวอีกด้วย

ที่จริงเราสามารถเขียน code ให้สั้นลงได้อีก โดยเอาตัว destructuring ไปแปะไว้ในตำแหน่งของ parameter เลย ตามตัวอย่างต่อไปนี้

ถือเป็นการ destructuring กันตรงตำแหน่งที่ต้องการใช้เลย ส่วนผู้ใช้จะพูดแบบไหน ก็ขึ้นอยู่กับรสนิยมของ dev. แล้วล่ะครับ

หากดูดีๆ syntax ของการทำ destructuring จะคล้ายกับการทำ named import อันเป็นเนื้อหาในตอนที่แล้ว อย่างเช่น

Styles refactoring

คราวนี้เราจะมาทำการ refactor ให้กับ style ของเรากัน

เปิดไฟล์ app/styles/index.js ขึ้นมาครับ แล้วแก้ code ให้เป็นดังนี้

จะเห็นว่า คราวนี้เราไม่ต้องเอา styles มาครอบ แต่ export เป็น const ออกไปตรงๆ ทีละตัวเลย ดังนั้น module ตัวนี้จะมี const ออกไป 2 ตัวคือ transparentBg และ space

คราวนี้ก็ได้เวลาไล่แก้การ import ในไฟล์ทุกแห่งที่ import styles ไปใช้ โดยให้แก้จาก code ดังต่อไปนี้

ให้กลายเป็น

โดยให้ไปแก้ในไฟล์ดังต่อไปนี้

app/components/MainContainer.js

app/components/Results.js

app/components/ConfirmBattle.js

จากนั้นก็ให้ลองเป็นโปรแกรมมาลองทดสอบดู หากไม่พบข้อผิดพลาดก็เป็นอันจบงานนี้

const refactoring

คราวนี้ให้เราไล่เปิด module ทั้งหมดใน project แล้วแก้ไขส่วนการประกาศตัวแปรแบบ var ให้มาเป็น const ซึ่งจะมีไฟล์ดังต่อไปนี้ที่เข้าข่ายต้องถูก refactor

app/components/Loading.js

app/components/Main.js

app/components/Results.js

app/config/routes.js

app/containers/ConfirmBattleContainer.js

app/containers/PromptContainer.js

app/containers/ResultsContainer.js

app/utils/githubHelpers.js

เมื่อเสร็จแล้ว ให้ทดสอบในโปรแกรมดูอีกครั้งหนึ่ง

Destructuring refactoring

ได้เวลาเอาความรู้เรื่อง Object Destructuring มาใช้กันแล้ว

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

วิธีการ refactor ในครั้งนี้คือ ดูว่าภายใน code property เป็นหลัก ซึ่งคำตอบก็คือ user.score และ user.info ดังนั้น ก็ให้เราทำการ “ทุบ” user object แล้ว “ควัก” เอา score กับ info ออกมา โดยแทนที่จะรับ parameter เป็น user ก็ให้ลงเป็น {score, info}

ลองอีกซักตัวอย่างนึงละกันนะครับ

เปิดไฟล์ app/containers/ConfirmBattleContainer.js แล้วแก้ code ดังนี้

อันนี้คือการ destructuring ตัว this.props.location object แล้วดึงมาแค่ property ตัวเดียว นั่นคือ query

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

https://github.com/himaeng/react-fun-course/tree/master/ES02-const-destructuring

สรุป

บทนี้เราคุยกันในเรื่องของการประกาศตัวแปรสามชนิดอันได้แก่ var, let และ const โดย var นั้นเป็นวิธีประกาศตัวแปรแบบดั้งเดิมของ javascript มีข้อเสียคือ ไม่สนใจเรื่อง scope ทำให้คนที่มาจากภาษาอื่นอาจงงได้ let กับ const มีลักษณะเหมือนกันคือ เป็นวิธีประกาศตัวแปรที่ทำให้ตัวแปรนั้น สามารถ access ได้จากภายใน scope ของตัวเอง หรือ scope ลูกๆ ของมันได้ แต่ const ต่างจาก let ตรงที่ว่า const คือค่าคงที่ เมื่อ assign ค่าใดๆ ให้กับตัวแปรแบบนี้แล้ว จะทำการ re-assign ไม่ได้อีก

นอกจากนี้เรายังพูดถึงฟีเจอร์ Object Destructuring ที่เป็นการ “ทุบ” Object แล้ว “ควัก” เอา properties หรือ function ต่างๆ ภายใน object ออกมา assign ให้กับ local variable ได้โดยตรง ทำให้ลดจำนวนบรรทัดของการ code ลง

 

 

1 COMMENT