Data binding ของ JavaScript และการใช้งาน “this” keyword

บทความนี้จะมาอธิบายการทำงานของ “this” ปกติ “this” เราจะอ้างถึง properties ของคลาสนั่นๆ แต่ JavaScript แต่ต่างออกไปนิดหน่อยและการใช้ “this” นั้นทำได้หลายหลายวิธีมากขึ้นอยู่กับการ binding Properties ของเราครับ วันนี้จะมาสอนการใช้ “this” ให้ถูกวิธีกัน

ขอยกตัวอย่างภาษา Java ก่อนนะเพื่อให้เห็นว่า “this” ทำงานยังไง

การใช้ “this” ใน Java นั่นจะเห็นว่าเราจะว่าเป็นการอ้างถึง properties ในคลาส ซึ่งเราจะไม่สามารถทำการเรียก int x , y , width , height จากที่อื่นได้นอกจากเราจะสร้าง Method เพื่อรับและส่งค่า แล้ว JavaScript ละ ? 

ในการ Binding ของ JavaScript นั่นจะมีอยู่ 4 แบบหลักๆ

  1. Window Binding / Default Binding

  2. Implicit Binding

  3. Explicit Binding

  4. New Binding

Window Binding / Default Binding

มันก็คือการที่เราใช้ “this” เพื่อไปเรียกอ๊อฟเจ๊ตหรือตัวแปรของ window ในบราวเซอร์นั่นเอง ในโค้ดผมเขียนฟังก์ชันปกติทั่วไป ดูตัวอย่าง

แต่สิ่งที่ได้กลับไปเรียก var a ที่อยู่ข้างนอกออกมาให้เรา เพราะมันไปเรียกคำสั่งนี้มาทำงานแทนครับ window.a และ “this” ที่อ้างถึงก็ไม่ใช้อะไรอื่นแต่เป็น window นั่นเองครับ อธิบายเพิ่มเติมก็คือตัวแปรต่างที่เราปรกาศมาอย่าง var a จะได้รับ scope เป็น global ซึ่งจะเก็บไว้ใน window ครับ เหมือนกับเราประกาศ window.a = 2 แล้ว window คืออะไรมันคือ Object ที่ได้รับมาจากบราวเซอร์อีกทีนึงครับ 

ถ้าเราไม่ต้องการให้มันไปเรียก window มาละ เรามีวิธีแก้ครับ คือใช้ strict mode แบบนี้

ฟังก์ชันของเราก็จะไม่ไปเรียก window มาทำงานแล้ว และก็จะได้ Error กลับมาเพราะมันไม่รู้จัก this.a 

 

Implicit Binding

อธิบายสั่นๆ คือการอ้างไปถึง Object หรือ Properties ที่อยู่ใน Context ของตัวมันเองครับ

หรือจะเขียนอีกแบบ

หรืออีกตัวอย่างนึงซับซ้อนไปอีกนิดนึง

จะเห็นว่าในทุกๆ แบบเราสามารถใช้ “this” เรียกเอา Properties ของตัวมันเองแบบไม่มีปัญหาเลย ลองมาดูอีกแบบนึง

กลับมาอีกแล้วครับ window ที่เป็นแบบนี้ก็เพราะว่า foo() มันประกาศอยู่นอก obj นั่นเองดังนั่น context มันเลยเปลี่ยนไปเป็น window ถึงแม้เราจะเรียกใน obj ก็ตาม แต่เราสามารถแก้ปัญหานี้ได้ครับ ลองมาดูหัวข้อถัดไป

 

Explicit Binding

ถ้าว่าง่ายๆ หลักการไม่เยอะมันคือการทำให้ฟังก์ชันของเราใช้ “this” ไปชี้ที่ใน scope ของมันเองครับ ไม่ชี้ที่ window หรือ context อื่นๆ นอกจากตัวมัน บางคนอาจจะเคยเห็นฟังก์ชันสามตัวนี้มาแล้ว call(), bind(), apply() เพราะการทำ explicit binding เราจะเอาสามฟังก์ชันที่ว่าเอามาใช้งาน ซึ่งฟังก์ชันพวกนี้จะผูกติดมากับฟังก์ชันทุกๆ ตัวที่เราสร้างบน JavaScript โดยปริยาย เราสามารถเรียกใช้ได้ตลอดเวลา

เพื่อแก้ปัญหาด้านบนเราจะลองมาเขียนแบบใหม่ดู

ผมใช้ call() แล้วโยน obj เข้าไปผลที่ได้มันก็จะไปเรียก obj.a ขึ้นมาให้เรา ซึ่งเราต้องการให้มันเป็นแบบนั่น และผมยังสามารถโยนตัวแปรหรืออ๊อฟเจ็คอื่นๆ เข้าไปได้อีกด้วยถ้าต้องการแบบนี้

ซึ่งประโยชน์ของมันทำให้เรา reuse ฟังก์ชันได้สบายๆ และเรายังใส่ค่าลงไปกี่ตัวก็ได้เท่าที่เราต้องการ แต่ถ้าเรามีข้อมูลสัก 10 ตัวละ หรือมากกว่านั่น งั่นเราลองมาเปลี่ยนเป็นแบบนี้แทนดีกว่า

ผมยกเอาส่วนของ print3 มาเขียนใหม่ โดยครั่งนี้เรียกผ่าน apply() แทนแล้วทำการโยนอาเรย์เข้าไปแทนการใส่ค่าทีละตัว ซึ่งก็ให้ผลไม่ต่างจาก call() แต่ต่างกันตรงที่ call() รับค่าที่ละตัวแบบไม่จำกัดจำนวน ส่วน apply() จะรับค่าที่เป็นอาเรย์เข้าไป

ฟังก์ชันสุดท้ายคือ bind() มาดูกันว่าเขียนยังไง

ผลที่ได้ก็เหมือนกับ call() และ apply() แต่ต่างกันตรงที่ call() และ apply() นั่นจะเรียกให้ฟังก์ชันทำงานทันที่หลังจากเราเรียกใช้งาน แต่ bind() นั่นจะทำการโยนค่าที่ส่งเข้าไปออกมาเป็นฟังก์ชันเพื่อรอให้เราเรียกใช้งานอีกทีนึงครับ

New Binding

ตัวนี้จะเป็นการทำงานกับ keyoword “new” หรือก็คือการสร้างอ๊อปเจ๊คนั่นเอง ถ้าใครเคยเขียน Java มาต้องร้อง อ่อ แน่ๆ เรามาดูตัวอย่างกัน โดยผมจะเอาโค้ด Java ข้างบนมาเขียนใหม่

จะเห็นว่าผมสร้างอ๊อฟเจ๊คจาก “new” ขึ้นมาจากนั่นก็เรียกใช้งานเมธธอด print_me() ให้ทำงาน ซึ่งใน JavaScript หลักการทำงานก็คล้ายๆ กัน แต่ JavaScript มันไม่มี Class ครับ ผมจะลองเอาโค้ด Java ข้างบนมาแปลงใหม่แบบนี้ ให้เป็น JavaScript

จะเห็นว่าโค้ด JavaScript ผมได้แปลงมาจาก Java ข้างบน ตรงส่วนของ print_me ผมได้ใช้ prototype เพื่อทำการ inheritance ตัว Rectangle อีกทีนึงครับ เราจะลองมาดูตัวอย่างสุดท้ายการโดยนำเอา Explicit Binding มารวมด้วยแบบนี้

ผมได้เพิ่ม calcu() เข้าไปอีก โดยผมยกโค้ดจากตัวอย่างแรกมาให้ เห็นไหมครับ เราสามารถเอามันมาประยุกต์ใช่ได้หลายแบบเลยทีเดียว **ข้อควรจำ การจะใช้ “new” ได้ต้องไม่มีการ return ค่าใดๆ ทั่งสิ้น หรือหมายความว่าต้องเขียนด้วย “this” ทั่งหมดครับ

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

Facebook Comments