วันพฤหัสบดีที่ 25 ธันวาคม พ.ศ. 2557

ภาษา JavaScript ฉบับผู้เริ่มต้น part 16-1

: รู้จักกับ DOM (Document Object Model)

>> แท้จริงว่าจะไม่กล่าวถึงเรื่องนี้แล้ว แต่ในเมื่อมันเป็นเรื่องสำคัญจึงเว้นไปไม่ได้ครับ อะไรคือ DOM แล้วมันเกี่ยวข้องกับ JavaScript อย่างไร?
ตอบ DOM คือวิธีการครับ เป็นวิธีการที่คิดขึ้นมาเพื่อเข้าถึงและควบคุมเอกสาร HTML แบ่งออกเป็นระดับ (level) เท่าที่ทราบขณะนี้คือ
- level 1 ว่าด้วยเรื่อง Core และ HTML
- level 2 ว่าด้วยเรื่องของ level 1, Events, Style, Views, Traversal และ Range
- level 3 ว่าด้วยเรื่องของ level 2, Load กับ Save และ Validation

>> เว็บแต่ละหน้าหรือเอกสาร HTML ของเรานั้นประกอบด้วยแท็กใช่ไหมล่ะครับ พื้นฐานเลยก็คือแท็ก html ภายในแท็กนี้ก็จะมีแท็ก head และ body หรืออยากเพิ่มขนาดตัวอักษรในลักษณะหัวข้อก็ใช้แท็ก h1, h2 ยัน h6 หรืออยากเน้นตัวหนาก็ใช้แท็ก b หรือ strong ใช่ไหมล่ะ ว่ากันว่าหากนำเอาแต่ละแท็กมาโยงกันเป็นโครงสร้างก็จะได้รูปต้นไม้กลับหัวครับ

>> ต้นไม้กลับหัวหรือว่า tree นี้ประกอบไปด้วยแท็ก เราจะเรียกแต่ละแท็กที่ทำหน้าที่ของมันว่าออบเจ็กต์ (object) หรือจะเรียกแต่ละแท็กที่ซ้อนกันเป็นลำดับชั้นนี้ว่า node นะครับ

>> เช่นนี้กล่าวได้ว่า node เริ่มต้นก็คือ html หรือออบเจ็กต์ html นั่นเอง แต่มี node ที่อยู่ก่อน node นี้ครับ เขาเรียกกันว่า root node และมันมีชื่ออย่างเป็นทางการว่า Document ครับ

>> เจ้า Document node นี้จะเป็นตัวแทนของทุก node ภายในเว็บหรือเอกสาร HTML หนึ่งหน้า (ตัวพ่อ) เพื่อใช้เข้าถึงแต่ละ node ในเอกสารได้ (ตัวลูก) ด้วยคำสั่ง document

>> สมมติเรามีเอกสารที่ประกอบด้วยแท็กดังต่อไปนี้นะครับ เริ่มจาก
html
head
body
h1
p
p

แล้วเขียนคำสั่ง
var e = document.getElementsByTagName("html");
ผลลัพธ์ของ e คือ
html
head
body
h1
p
p

เอาล่ะ ลองเขียนแบบนี้บ้าง
ver e = document.getElementsByTagName("head");
ผลลัพธ์ของ e คือ
head
body
h1
p
p

แล้วแบบนี้ล่ะ
var e = document.getElementsByTagName("p");
ผลลัพธ์ของ e คือ
p
p

นี่แสดงว่าอะไร? แสดงว่าเจ้า Document นี้สามารถเข้าถึงแต่ละสมาชิกแท็กที่อยู่ในเอกสารหนึ่งหน้าได้อย่างไรล่ะครับ

>> งงนะบางทีเรียก แท็ก บางทีก็เรียก node บางทีก็ว่า object ตกลงมันอันเดียวกันไหมหือ?
ตอบ แท้จริงเราก็พูดถึงสิ่งเดียวกันทั้งหมดนั่นแหละครับ เพียงแต่แยกบริบทของมันว่ากำลังทำอะไร หรือมีสถานะเป็นอะไรในเรื่องนั้นๆครับ ประมาณนี้
- แท็ก (tag) พูดถึงตอนจะเขียนมันเป็นเอกสารหนึ่งหน้า จะต้องประกอบด้วยแท็กอะไรบ้าง แบบนี้จะไม่พูดว่า node หรือ object เพราะฟังแล้วไม่เข้าใจ
- node พูดถึงตอนที่คิดถึงเอกสารในแบบโครงสร้างต้นไม้กลับหัวครับ ว่าประกอบด้วย node เรียกซ้อนกันไปอย่างไร
- ออบเจ็กต์ (object) พูดถึงตอนเขียนภาษาจาวาสคริปต์ ภาษานี้สร้างออบเจ็กต์ได้ แต่ละออบเจ็กต์จะมีคุณสมบัติ (properties) และพฤติกรรม (methods) รวมถึงเหตุการณ์ (evnets) เป็นของตัวเองครับ

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

วันอาทิตย์ที่ 19 ตุลาคม พ.ศ. 2557

MiniCompiler v1.0

       จากไวยากรณ์ข้างต้นของการประกาศตัวแปร (T) และการเรียกฟังก์ชัน (F) ต่างก็ใช้ ID เป็นตัวเริ่มต้นการผลิต ทำให้ไม่สามารถแยกแยะในทางโปรแกรมได้ว่า หลังจากกระทำกับ ID แล้วควรพบกับเครื่องหมาย '(' หรือ ',' ดังกรอบสีแดงของรูปด้านล่างนี้
       เป็นเหตุให้ต้องเขียนไวยากรณ์นี้ใหม่ (rewrite) โดยจะต้องคงความสามารถเดิมไว้ ด้วยการแยก ID ออกมา จากนั้นสร้างไวยากรณ์ย่อยในชื่อ S20 ทำหน้าที่เป็นตัวเลือกว่าควรจะกระทำกับเครื่องหมาย '(' หรือ ',' ดังนี้
       สังเกตต่อไปว่าที่ S20 เรียก T จึงต้องเขียน T ให้ใหม่ด้วย
       เรายังพบอีกว่า S20 ในช่วงการผลิต statement ของ T และ S1 มีลักษณะไม่ต่างจาก T และ F ดังที่กล่าวมา กล่าวคือเรียก ID ด้วยกันทั้งคู่ แต่ไม่รู้ว่าควรพิจารณา ',' หรือ '(' ดังนี้
       เช่นนั้นจึงต้องปรับเปลี่ยนไวยากรณ์การผลิตนี้ใหม่อีกครั้งเป็น
       สำหรับไวยากรณ์นิพจน์การคำนวณ ขออนุญาตเปลี่ยนกลับเป็นอย่างเดิม เพื่อให้ความหมายยังคงเดิม ดังนี้ครับ
       ท้ายที่สุดจึงได้ว่า
       โปรแกรมภาษา C# ต่อไปนี้เขียนด้วยไวยากรณ์ดังข้างต้น สามารถผลิต Target code ของนิพจน์การบวก ลบ คูณและหารครับ

Download MiniCompiler v1.0

หมายเหตุ*** ผมใช้ MS Visual Studio Express 2013 for Windows Desktop เขียนนะครับ

วันเสาร์ที่ 23 สิงหาคม พ.ศ. 2557

Interface, Abstract และ Concrete class

วันนี้เราพูดกันถึงเรื่อง Design Pattern ที่เกี่ยวข้องกับ
: หมู หมา แมว งู และนก

>> การเขียนโปรแกรมด้วยหลักการ OOP มักมาคู่กับการออกแบบคลาสเสมอ ซึ่งถือเป็นปัญหาสำคัญของผู้เขียนโปรแกรมที่อิงตามหลักการนี้แทบทุกคน ไม่เราก็เขาต้องมีคำถามหรือคำตอบทำนองว่า เอาล่ะวะ ได้ล่ะ หรือ เอาประมาณนี้ หรือ หื้อ~โอเคแบบนี้ ไม่กับตัวเองก็กับเพื่อนร่วมทีม

>> การเขียนโปรแกรมจับหลักการดีอย่างไร สำหรับผม ดีที่มั่นใจ ดีที่อุ่นใจได้ว่ากลวิธีที่เราหรือเขาได้ออกแบบมานี้สามารถนำมาประยุกต์แก้ปัญหาและจัดระบบงานได้ในเวลาขณะนั้น ทำให้โค้ดที่เขียนหรือคลาสที่สร้างขึ้นมีคุณภาพ อย่างน้อยก็ในระดับที่ตัวเราเองพอใจ

>> ปัญหาที่อยากแชร์ในโพสต์นี้ก็คือ สมมติเกมของเรามีสัตว์อยู่สามตัว ได้แก่ หมู หมา แมว เราต้องเขียนโปรแกรมเข้าไปควบคุมลักษณะการเดินของมัน คือให้มันส่ายขาดุ๊กดิ๊ก เดินดิ้นยุ๊กยิ๊กๆไปมา จะออกแบบคลาสของเจ้าสัตว์สามตัวนี้อย่างไร


>> งานนี้สมชายยกมือตอบทันที ให้มีคลาส (Concrete Class) ชื่อ หมู หมา แมว (สีเขียว) แต่ละคลาสมีเมธอดหรือพฤติกรรมการเดินสี่ขาของใครของมันไง ตามรูปที่ 1)

>> ปรากฏว่าเมื่อสมชายสร้างคลาส หมู หมา แมว ตามที่เขาคิด เขาก็ได้รู้ว่า โอ๊ะโอ๋! โค้ดที่เขียนลักษณะการเดินสี่ขามันซ้ำกันทั้งสามคลาสเลยนี่นะ ประเด็นคือเขียนโค้ดซ้ำ

>> ดังนั้นสมชายคิดใหม่ สร้าง Abstract Class ขึ้นมาแล้วกัน (สีส้ม) จับเอาสิ่งที่ซ้ำกันไปไว้ที่คลาสนามธรรมนั้น (Abstract Class คือคลาสที่เตรียมขึ้นเพื่อใช้ในการสืบทอดเท่านั้น) แล้วให้คลาส หมู หมา แมว เดิมทั้งสามไปสืบทอดมาอีกต่อหนึ่ง โดยตั้งชื่อคลาสนามธรรมว่า สัตว์ ดังรูปที่ 2) ทีนี้โค้ดของเขาก็ไม่ซ้ำอีกแล้ว

>> และโดยหลักการทั่วไป กลุ่มคลาสใดๆที่มีเมธอดหรือพฤติกรรมซ้ำกัน เมธอดหรือพฤติกรรมเหล่านั้นมักถูกบัญญัติให้เป็นข้อตกลงหรือกติกาที่ใช้ Interface (สีฟ้า) เข้ามากำหนดก่อน หลังจากนั้นจึงให้คลาสใดๆที่ใช้ข้อตกลงหรือกติกานี้มา implement อีกทีหนึ่ง ในที่นี้สมชายให้คลาสนามธรรมที่ชื่อ สัตว์ ไป implement เจ้า Interface ที่เขาได้สร้างและตั้งชื่อว่า สัตว์ เช่นกัน ตามรูปที่ 3) เรียกได้ว่าจัดมาเต็มองค์ประกอบ

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

>> ครั้นอีตาสมชายจะให้งูกับนกเดินสี่ขาเหมือน หมู หมา แมว มันก็ได้นะ แต่ว่า... งูที่ไหนมีขา? แล้วนกก็ไม่เคยมีสี่ขา? สมชายงานงอก เพราะจะยกเซตเดิมมาหากินไม่ได้แล้ว ดังรูปที่ 4)

>> สมชายจึงสร้างคลาสนามธรรม (Abstract Class) ขึ้นมาใหม่ ให้เป็นของงูและนกตามที่เขาต้องการ ตามรูปที่ 5) แน่นอนว่าเขาไม่ลืมที่จะบัญญัติข้อตกลงที่ว่า งูกับนกเป็นสัตว์ชนิดหนึ่ง ดังนั้นจึงมี Interface เปล่าๆเพิ่มเข้ามาด้วย

>> และเพื่อให้งานใหม่นี้เข้ากับงานเก่าได้ เขาจึงตัดสินใจเปลี่ยนชื่อคลาสนามธรรมที่เป็นของ หมู หมา แมว ให้สอดคล้องกับคลาสนามธรรมใหม่ที่เป็นของงูและนก ได้ตามรูปที่ 6) สมชายส่งงานแบบจัดเต็มเหมือนเคย งูกับนกที่เพิ่มเข้ามาภายหลังจึงสามารถทำงานกับ หมู หมา แมว กลายเป็นเกมที่สนุก + มีเพื่อนใหม่เพิ่มเข้ามาได้เรื่อยๆ เรียกได้ว่าเป็นภาคเสริมที่สร้างความฮือฮาเป็นอย่างยิ่ง

>> งานนี้สมชายรับทรัพย์กลับบ้านพาสาวเที่ยวสบายใจแฮ สวัสดีครับ

*** ประโยชน์ทั้งหมดที่ได้รับ ยกให้กับพี่ชายที่ทำงานหนักคนหนึ่ง นับถือๆ

วันเสาร์ที่ 2 สิงหาคม พ.ศ. 2557

Android create and destroy process


: ทำไมเครื่องที่มีหน่วยความจำเยอะ จึงทำงานได้เร็วกว่า?

อย่างที่เราทราบกันไปแล้วว่า หนึ่งหน้าที่เราเห็นของ app บนโทรศัพท์ android นั้นคือหนึ่ง activity ที่มี activity life-cycle เป็นของตัวเอง

- รูปที่ ๑ ได้แสดงให้เห็นว่า เมื่อเริ่มต้น app ใดๆจะเกิดการสร้าง process ขึ้นมาก่อน จากนั้นเริ่ม thread ของมัน เพื่อทำงานประมวลผลใดๆตามวัตถุประสงค์ของ app (สมมติชื่อว่า process A)

- รุปที่ ๒ ได้แสดงให้เห็นว่า android มีกระบวนการจัดการลำดับเหตุการณ์หรือประวัติ ในที่นี้ขอเรียกว่าปม history

- รูปที่ ๓ เกิดต่อเนื่องจากรูปที่ ๑ และ ๒ เริ่มจากสร้างหน้า activity1 ขึ้นมา เก็บประวัติการใช้ข้อมูลลง history1 หน้าดังกล่าวนี้ก็จะแสดงเป็นหน้าแรกของ app ตัวที่เรากำลังสนใจอยู่

เมื่อใดก็ตามที่เกิดการเปลี่ยนหน้า ย่อมเกิดการสร้างหน้าใหม่ขึ้นในครั้งแรก (first time) และเกิด activity ใหม่เช่นกัน

- รูปที่ ๓ นอกจากหน้าที่หนึ่งแล้ว สมมติเป็นเมนูเล่นเกม พอเราเลือกเมนูใดๆ เจ้า app ก็จะแสดงหน้าถัดไป ซึ่งก็จะสร้างปม history2 และ activity2 ตอนนี้เราจะมีทั้งหน้าแรก (activity1) และหน้าที่สอง (activity2) เก็บไว้ในหน่วยความจำ โดยหากว่าหน่วยความจำของเครื่องเราเพียงพอ ทั้งสอง activity ก็จะคงอยู่ต่อไป

- รูปที่ ๔ ในกรณีที่มีหน่วยความจำไม่มาก ก็จะเป็นโชคร้ายของ activity1 หรือหน้าแรกที่จะต้องถูกทำลายไปก่อน การทำลายในที่นี้ก็คือการคืนหน่วยความจำให้ระบบหรือก็คือตัวเครื่อง เพื่อที่ระบบจะนำไปใช้สอยอย่างอื่น (โดยปกติระบบของ android ทำงานส่วนนี้ให้อัตโนมัติ แต่อาจไม่สะใจผู้สร้าง app ที่อยากควบคุมหน่วยความจำเอง)

- รูปที่ ๕ เป็นเหตุการณ์ที่ app ปัจจุบันไปเรียก app อื่นให้ทำงานต่อจากมัน ซึ่งหากว่าหน่วยความจำของเครื่องไม่พอแล้วล่ะก็ เจ้า activity1 และ activity2 ก็จะถูกจัดการ เหลือไว้เพียงปม history เท่านั้น

ภายหลังหากมีการกดปุ่มย้อนกลับ ระบบ android ก็จะเข้าไปอ่านข้อมูลใน history นั้นๆเพื่อนำมันมาใช้กับ activity ของ history ปมดังกล่าว (ในที่นี้คือ history2 จะถูกอ่านและสร้าง activity2 อีกครั้ง หากกดปุ่มย้อนกลับอีก จึงเป็นคราวของ history1 และ activity1)

- รูปสุดท้าย รูปที่ ๖ หน่วยความจำเหลือน้อยมากจริงๆ ก็เป็นได้ว่าทั้ง app อาจถูกทำลายลงไป เพื่อที่ app ใหม่ซึ่งถูกเรียกในปัจจุบันนี้จะได้ใช้หน่วยความจำที่ว่านี้แทนครับ

ทราบอย่างนี้แล้ว เครื่องที่มีหน่วยความจำมากจึงราคาสูง เพราะประสิทธิภาพทั้งหมดก็เพื่อความราบรื่นและรวดเร็วนั่นเอง

คืนนี้สวัสดีครับ

เริ่มต้นเขียน Android


: Android activity life-cycle

รูปนี้นำมาจาก www.edureka.in แล้วเพิ่มเติมส่วนที่กำลังมุ่งเน้นลงไป ใครที่หัดเขียน Android ใหม่ๆควรจะทำความรู้จักกับ Android activity life-cycle ให้ดีนะครับ เพราะมันคือกิจกรรมพื้นฐานที่เกิดขึ้นตลอดเวลาตั้งแต่เปิดแอพ (open application) ไปจวบกระทั่งปิดแอพ (destroy application) เลยทีเดียว

เราเรียกแต่ละหน้าของแอพว่า activity หรือกิจกรรม และกำหนดให้ว่าหนึ่งหน้านั้นคือหนึ่งกิจกรรม (1:1)

แต่ละกิจกรรม (activity) จะมีสถานะ (state) ที่อยู่ในสภาวะสมมติ หลักๆดังนี้ครับ
- starting
- running
- paused
- stopped
- destroyed

สภาวะสถานะสมมติดังกล่าวเกิดขึ้นอันเนื่องมาจากพฤติกรรมของคลาส (ที่เป็นลูกของคลาส Activity) เกิดการกระทำต่างๆนานา โดยทั่วไปแล้วดังนี้

- เมื่อเปิดเกมคุกกี้รัน (สมมติๆ) จะเกิด onCreate() >> onStart() >> onResume() จากนั้นจะเข้าสู่สถานะ running เมนูต่างๆจะปรากฏให้เห็น

- ขณะที่เล่นเกมอยู่ในสถานะ running จู่ๆแบตเตอรี่จะหมด เกิดกล่องแจ้งเตือนพลังงานเหลือน้อยเต็มที เจ้ากล่องที่ว่าจะบังคับให้ onPause() เข้าสู่สถานะ paused เกมจะถูกกล่องบังไว้ชั่วคราว (บังแค่กลางจอ) พอจอที่ว่าถูกปิดลง (เราปิดเองหรือเสียบไฟเลี้ยงมัน) จะเกิด onResume() เพื่อกลับไปยังสถานะ running ใหม่ เล่นเกมต่อได้เลย

- เล่นไปสักพักชักเบื่อ จึงกดปุ่มตรงกลางของโทรศัพท์ จะเกิด onPause() ทำให้อยู่ในสถานะ paused ตามด้วย onSaveInstaceState() เพื่อบันทึกการเล่นล่าสุด ก่อนจะ onStop() เพื่อยุติการเล่น (แต่หน่วยความจำของเกมในเครื่องยังคงอยู่) และเข้าสู่สถานะ stopped ในที่สุด

- ทีนี้ไม่มีอะไรทำ พลันเกิดอาการกระสันอยากเล่นเกมต่อจากที่ค้างไว้ ก็กดไอคอนมัน ทำให้เกิด onRestart() >> onStart() >> onResume() เข้าสู่สถานะ running เล่นเพลินไปสามวัน (เวอร์)

- กระทั่งกดปุ่มที่สาม (ปุ้มย้อนกลับ) จะทำให้เกิด onPause() อยู่ในสถานะ paused หยุดชั่วคราว onSaveInstanceSate() บันทึกค่า และ onStop() ยุติ จากนั้นเข้าสู่สถานะ stopped

- หรือแบตเตอรี่หมด (อุต๊ะ!) จะทำให้เกิด onPause() อยู่ในสถานะ paused และเข้าสู่สถานะ destroyed ทันที
(อ่าว!ไม่ save ที่เล่นมาสามวันหายหมด เพราะหน่วยความจำจะคืนให้ระบบหมดสิ้น เสียใจด้วยนะ อิอิ)

สรุป หัวใจของเรื่องนี้ก็คือวงจรชีวิตของเหล่าสถานะ (state) ที่ดำเนินอยู่ตลอดเวลาตั้งแต่เกิดจนตาย แต่ละกิจกรรม (activity) มีเหล่าสถานะเป็นของตัวเอง และแต่ละแอพประกอบไปด้วยหนึ่งหรือหลายกิจกรรม (ประกอบไปด้วยหนึ่งหน้าหรือหลายหน้า) ทั้งนี้ยังคงมีพฤติกรรม (onCreate(), onStart() ฯลฯ) อีกมากมายซึ่งคงจะได้ศึกษาต่อไป

โพสต์นี้ลาแล้วครับ สวัสดี

ภาษา JavaScript ฉบับผู้เริ่มต้น part 15-3

: Prototype กับการสืบทอด

>> part สุดท้ายของเรื่อง ออบเจ็กต์ & คลาส ว่ากันด้วยพร็อพเพอร์ตี้ที่ชื่อ prototype (เขียนอย่างนี้เลย) ซึ่งมีชนิดเป็น Prototype (โปรดอย่าได้สับสนนะครับ ชนิดมันคือ Prototype และมันชื่อ prototype) เจ้าพร็อพเพอร์ตี้นี้มีสมบัติในการแชร์พื้นที่ใช้ร่วมกันในทุกๆออบเจ็กต์ที่สร้างมาจากคลาสเดียวกัน ยกตัวอย่างจากคลาส MyMath ของ part ก่อน

function MyMath(x, y) {
this.x = x;
this.y = y;
}

ทีนี้พอเราต้องการสร้างเมธอดไว้ใน prototype ก็ให้เรียกชื่อคลาสนั้นมาเขียนต่ออย่างนี้ (เขียนไว้นอกคลาสเลยนะ)

MyMath.prototype.getSummation = function() {
return this.x + this.y;
}

จะสังเกตได้ว่า เราไม่ได้สร้างเมธอดไว้ในคลาสอีกแล้ว เมธอด getSummation นี้จึงไม่ได้เป็นของออบเจ็กต์ตัวใดตัวหนึ่งภายหลังจากถูก new แต่จะเป็นของทุกๆออบเจ็กต์ที่ถูก new จากคลาส MyMath หรือก็คือจากคลาสเดียวกันครับ กล่าวได้ว่ามันถูกแชร์ใช้ร่วมกันนั่นเอง ทดสอบโดยเพิ่มโค้ดต่อไปนี้เข้าไป

MyMath.prototype.getSummation = function() {
document.write( "getSummation is a Prototype<br/>" );
return this.x + this.y;
}

จากนั้นสร้างออบเจ็กต์มาสองตัว

var point1 = new MyMath(10, 20);
var point2 = new MyMath(100, 20);
point1.getSummation();
point2.getSummation();

ผลลัพธ์ที่ได้คือ

getSummation is a Prototype
getSummation is a Prototype

>> หลักการนี้คล้ายคลึงกับเรื่อง static ของจาวาแต่ไม่ใช่หรอกนะ มันเป็นเรื่องของการสืบทอดล้วนๆ (Inheritance) เพราะทุกคลาสที่ถูกสร้างขึ้นในภาษาจาวาสคริปต์ จะมีพร็อพเพอร์ตี้ชื่อ prototype มาให้เสมอ ดังนั้นทุกคลาสที่ถูกสร้างขึ้นจึงเป็นลูก (is a sub-class) ของคลาสชื่อ Object ครับ

>> ข้อดีของการสืบทอดคือการนำทรัพยากรใดๆที่มีอยู่แล้วมาใช้ใหม่ คลาสลูกที่สืบทอดสมบัติจากพ่อแม่จะมีทุกอย่างที่พ่อแม่มี ทำให้เราสามารถเขียนพฤติกรรมหรือการกระทำของเมธอดในคลาสลูกเพิ่มเติมหรือทดแทนของเดิม (override) ซึ่งเป็นของพ่อแม่ได้อีกด้วย

>> ตัวอย่างต่อไปนี้แสดงการ override เมธอดที่ชื่อ greet ของคลาส Person โดยคลาส Employee ขั้นตอนแรกให้สร้างคลาส Person ขึ้นมาก่อน

var Person = function() {
     this.
canTalk = true;
     this.greet = function() {
          if (this.canTalk) {
               console.log("Hi, I'm " + this.name);
          }
     };
};

จากนั้นสร้างคลาส Employee

var Employee = function(name, title) {
     this.name = name;
     this.title = title;
     this.greet = function() {
          if (this.
canTalk) {
               console.log("Hi, I'm " + this.name + ", the " + this.title);
          }
     };
};

จากนั้น override เมธอด greet ของคลาส Person ด้วยการใช้พร็อพเพอร์ตี้ prototype

Employee.prototype = new Person();

ทดสอบ

var bob = new Employee('Bob', 'Builder');
bob.greet();

ผลลัพธ์คือ

Hi, I'm Bob, the Builder

>> หวังว่าจะไม่ยากจนเกินไป ใครเข้าใจได้แสดงว่ามีพื้นฐานและรู้หลักการ Object-oriented พอสมควร ใครที่ไม่เข้าใจก็ไม่ต้องกังวลไปนะครับ เรื่องนี้เป็นเรื่องเฉพาะที่เน้นหนักในการ design ค่อยๆเรียนรู้กันไป สวัสดีครับ

>> อ่านเพิ่มเติมได้ที่
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype

*** หมายเหตุ
คำสั่ง console.log แสดงผลลัพธ์ทาง console ของบราวเซอร์นะครับ กด F12 จึงจะเห็น แต่ถ้าไม่เข้าใจมันจะเปลี่ยนเป็น document.write แทนก็ได้

ภาษา JavaScript ฉบับผู้เริ่มต้น part 15-2

: คลาส

>> จาก part ที่แล้ว เราสร้างออบเจ็กต์ได้แล้ว คราวนี้เราจะสร้างสิ่งที่เรียกว่า 'คลาส' ครับ คลาสคืออะไร?
ตอบ จาวาสคริปต์เป็นภาษาเชิงวัตถุก็จริง (Object-oriented) แต่เป็นแบบ Prototype-based ครับไม่ใช่ Class-based กล่าวคือ เธอไม่ได้มีคลาสเป็นจริงเป็นจังและชัดเจนเหมือนภาษาจาวาหรือภาษาซีชาร์ป เธอมีฟังก์ชันรูปแบบหนึ่งที่เธอเรียกว่า Constructor Function เป็นตัวกำหนดโครงสร้างของออบเจ็กต์ มันเสมือนเป็นคลาสหรือเรียกว่าเทมเพลต (Template) ของเธอ

>> อะไรคือ Constructor Function?
ตอบ ก็ฟังก์ชันของภาษาจาวาสคริปต์ที่เราได้เรียนรู้ผ่านมานั่นแหละจ๊ะ สมมติเรามีข้อมูลตามนี้ (ตัวอย่างจาก part ก่อน)
- www.hotmail.com
username: pros
password: admin

เราสามารถนำมาสร้างเป็นคลาสได้ดังนี้
function Account( addressName, username, password ) {
this.addressName = addressName;
this.username = username;
this.password = password;
}

เมื่อมีคลาสหรือเทมเพลตที่เป็นโครงสร้างของออบเจ็กต์แล้ว ต่อไปก็เอามาใช้ เริ่มจากการประกาศตัวแปรออบเจ็กต์
var myAccount = new Account( "www.hotmail.com", "pros", "admin" );

ตอนเรียกใช้งานก็ว่า
document.write( myAccount.addressName ); ผลลัพธ์คือ www.hotmail.com
document.write( myAccount.username ); ผลลัพธ์คือ pros
document.write( myAccount.password ); ผลลัพธ์คือ admin

เมื่อมีหลายบัญชีก็สามารถ new เพิ่มได้ตามใจอยาก
var myAccount2 = new Account("www.gmail.com", "panda", "unlockme");
var myAccount3 = new Account("www.facebook.com", "Natcha", "lovely");

>> เราสามารถเพิ่มฟังก์ชันเข้าไปในคลาสได้ ตามทฤษฎีของหลักการเชิงวัตถุ เราจะเรียกฟังก์ชันที่มีความสัมพันธ์กับคลาสซึ่งเป็นส่วนหนึ่งที่ใช้อธิบายการกระทำของคลาสนั้นๆว่า เมธอด

>> สมมติว่าเราต้องการสร้างคลาสเกี่ยวกับการคำนวณไว้ใช้เอง และอยากตั้งชื่อว่า my math ให้สามารถคำนวนการบวก-ลบตัวเลขสองจำนวนได้ เราก็จะเอาชื่อนี้มาเขียนเป็น constructor function ได้ดังนี้
function MyMath(x, y) {
this.x = x;
this.y = y;
}

***หมายเหตุ คีย์คำว่า this ใช้กับเรื่องนี้โดยเฉพาะ มันหมายความว่า this.x เป็นชื่อตัวแปรของคลาส MyMath ส่วน x เฉยๆเป็นพารามิเตอร์คอยรับค่าที่ส่งเข้ามา สรุปได้ว่า this.x กับ x เฉยๆคนละหน้าที่กัน คนละความหมายกัน จึงไม่ใช่ตัวแปรตัวเดียวกัน

มันสามารถบวกได้ใช้ไหม ตั้งชื่อเมธอดว่า getSummation แล้วเขียนเพิ่มเข้าไปสิ
function MyMath(x, y) {
this.x = x;
this.y = y;
this.getSummation = function() {
return this.x + this.y;
}
}

มันสามารถลบได้ด้วยใช่ไหม ตั้งชื่อเมธอดว่า getSubtraction แล้วเขียนเพิ่มเข้าไป
function MyMath(x, y) {
this.x = x;
this.y = y;
this.getSummation = function() {
return this.x + this.y;
}
this.getSubtraction = function() {
return this.x - this.y;
}
}

ทีนี้ก็เอาไปใช้งาน
var point = new MyMath( 10, 20 );
document.write( point.getSummation() ); ผลลัพธ์คือ 30
document.write( point.getSubtraction() ); ผลลัพธ์คือ -10

>> อา...พอแล้วสำหรับ part ย่อยนี้ ต่อไปจะนำเสนอเรื่องสุดท้ายของคลาส ที่เกี่ยวกับการใช้พื้นที่หรือหน่วยความจำร่วมกันผ่านการสร้างเมธอดที่เรียกว่า prototype method หรือก็คือการแชร์เมธอดร่วมกันนั่นเองครับ

ภาษา JavaScript ฉบับผู้เริ่มต้น part 15-1

: ออบเจ็กต์

>> ในที่สุดก็มาถึงเรื่องท้ายๆของภาษาจาวาสคริปต์แล้ว (แม้ว่าจะข้ามไปบางเรื่อง เช่น Regular Expression และ DOM) ใครที่ศึกษาแบบผู้เริ่มต้นอย่างผมแล้วมาถึงนี่ได้ เราก็ควรให้กำลังใจซึ่งกันและกันนะครับ เยี่ยมมาก หากเราสามารถผ่านเรื่องนี้ไปได้ เรื่องที่ว่าเข้าใจยากกว่านี้ก็จะไม่ยากอีกต่อไป

>> ในภาษาอื่นเช่น จาวา แนวคิดของออบเจ็กต์ (object) และคลาส (class) จะแข็งแรงกว่านี้มาก มีความเป็น OOP มากกว่า จาวานิยามคำว่าออบเจ็กต์คือกลุ่มของแอตทริบิวต์ (attributes) กับเมธอด (methods) ที่มีความสัมพันธ์ต่อกันในเชิงของความหมาย ยกตัวอย่างเช่น ออบเจ็กต์ปากกา ก็คือปากกา จะต้องประกอบไปด้วยอะไรบ้างที่จำเป็นในขณะนั้น อาจได้แก่ หมึกปากกา ไส้ปากกา ปลอกปากกา จะต้องนำมาเขียนได้ มีโอกาสที่หมึกจะหมดหรืออื่นๆตามความเหมาะสม แล้วจาวาสคริปต์ล่ะ นิยามคำว่าออบเจ็กต์อย่างไร?

>> จาวาสคริปต์นิยามคำว่าออบเจ็กต์คือกลุ่มของพร็อพเพอร์ตี้ (properties) หรือก็คือคุณสมบัติที่เกี่ยวข้องกัน เพื่อให้มันง่ายต่อการเรียกใช้ มาถึงตรงนี้อาจสับสนว่าแล้วแอตทริบิวต์กับพร็อพเพอร์ตี้นี้มันเหมือนหรือต่างกันอย่างไร แท้จริงแล้วมันแทบไม่ต่างกันเลย ในเมื่อจาวาสคริปต์ของเราทำงานกับ DOM (ประดาแท็ก HTML ทั้งหลาย) จึงเรียกรายละเอียดของแท็กใดๆว่า แอตทริบิวต์ เช่น แท็กลิงค์

<a href="www.google.co.th">go to google</a>

มีรายละเอียดหรือแอตทริบิวต์ชื่อ href เป็นต้น แต่พอเราเข้าถึงแท็กดังกล่าวนี้ด้วยจาวาสคริปต์ (อาจโดย getElementByID) และต้องการกำหนดค่า URL ใหม่ เจ้า href นี้จะถูกเรียกในสภาพแวดล้อมของจาวาสคริปต์ว่า พร็อพเพอร์ตี้

>> สมมติว่าผมมี username กับ password ของสองเว็บไซต์เป็นอย่างนี้
- www.hotmail.com
username: pros
password: admin

- www.gmail.com
username: panda
password: unlockme

>> ผมสามารถนำมันทั้งสองมาสร้างเป็นอาร์เรย์ได้
var account1 = [ "www.hotmail.com", "pros", "admin" ];
var account2 = [ "www.gmail.com", "panda", "unlockme" ];

>> เวลาที่ผมต้องการเรียกใช้ก็ได้ว่า
document.write( account1[0] ); //ผลลัพธ์คือ www.hotmail.com
document.write( account2[2] ); //ผลลัพธ์คือ unlockme

>> ตัวอย่างข้างต้นคือออบเจ็กต์ของอาร์เรย์ แต่เรากำลังพูดถึงออบเจ็กต์ที่เราสามารถสร้างได้ด้วยตัวเอง เป็นออบเจ็กต์ที่สื่อความหมายถึงสิ่งนั้นเท่านั้นจริงๆ จึงได้ว่า
var account1 = {
addressName: "www.hotmail.com",
username: "pros",
password: "admin"
};

var account2 = {
addressName: "www.gmail.com",
username: "panda",
password: "unlockme"
};

>> เวลาจะเรียกใช้งานก็ว่า
document.write( account1.addressName ); //ผลลัพธ์คือ www.hotmail.com
document.write( account2.password ); //ผลลัพธ์คือ unlockme

>> หรือจะเรียกใช้แบบนี้ก็ได้ เราเรียกวิธีนี้ว่า Associative Array
document.write( account1[ "addressName"] );
document.write( account2[ "password" ] );

>> ตบท้ายด้วยการวนลูปแบบ for-in เพื่อดึงพร็อพเพอร์ตี้ออกมาดูหรือกำหนดค่าใหม่ครับ
for( var pName in account1 ) {
document.write( pName + " : " + account1[ pName ] + "<br/>" );
}

ผลลัพธ์คือ
addressName : www.hotmail.com
username : pros
password : admin

>> เมื่อรู้จักกับออบเจ็กต์ของภาษาจาวาสคริปต์กันแล้ว โอกาสหน้าเรามารู้จักกับคลาสบ้าง บอกให้เลยว่าจาวาสคริปต์ใช้ฟังก์ชันในการนิยามคลาสครับ

>> อ่านเพิ่มเติมเกี่ยวกับออบเจ็กต์ของภาษาจาวาสคริปต์
http://www.w3schools.com/js/js_objects.asp

วันพุธที่ 30 กรกฎาคม พ.ศ. 2557

Factory Pattern


>> นี่เป็น design pattern ที่ต้องการจะสื่อว่า ออบเจ็กต์ที่เราต้องการนั้น เราไม่ต้องสนใจว่ามันสร้างมาอย่างไร เพียงบอกชนิด (หรือชื่อ) ของออบเจ็กต์ เดี๋ยว design pattern นี้จะสร้างออบเจ็กต์ตามต้องการนั้นมาให้ครับ

>> factory pattern จะมีเมธอดสำหรับสร้างออบเจ็กต์ให้เอง โดยทั่วไปจะตั้งชื่อเมธอดนี้อย่างไรก็ได้ สมมติเป็นเรื่องการสร้างรูปทรงเรขาคณิต อาจตั้งชื่อว่า getShape, ถ้าเป็นเรื่องการสร้างไฟล์ logger อาจตั้งชื่อว่า createLogger หรือเป็นเรื่องการสร้างผลไม้กระป๋อง อาจตั้งชื่อว่า buildFruitCan ก็ตามสะดวก

>> factory pattern เริ่มต้นด้วย interface ที่กำหนดกติกาใดๆให้กับคลาสที่ต้องการ implement หรือนำไปใช้ครับ จากตัวอย่างนี้เป็นการสร้างรูปทรงเรขาคณิตสามแบบ คือ Rectangle, Square และ Circle ทั้งสามคลาสล้วน implement เจ้า interface ที่ชื่อ Shape เพื่อให้ตัวเองสามารถเรียกเมธอด draw ได้

>> หัวใจสำคัญของ factory pattern นั้น จะต้องมีคลาสที่ทำหน้าที่เป็นโรงงานครับ คลาสดังกล่าวนี้จะมีเมธอดในการสร้างออบเจ็กต์ Rectangle, Square และ Circle ตามตัวอย่างคือเมธอด getShape โดยกำหนดให้มันรับ input เป็นชนิดหรือชื่อของรูปทรงเรขาคณิตเข้ามา แล้วเอาไปเทียบว่าเป็นชนิดหรือชื่อของออบเจ็กต์รูปทรงเรขาคณิตชิ้นไหน ก็คืนออบเจ็กต์ชิ้นนั้นออกไป

>> ประยุกต์อย่างไร? ในงานที่ผมทำอยู่นี้ ผมต้องวาดกราฟจาก google chart tools (https://developers.google.com/chart/?hl=th) แต่ละกราฟใช้ข้อมูลเดียวกัน ต่างเพียงชนิดของกราฟเท่านั้น ดังนั้นผมจะสร้างคลาส GoogleChartFactory ขึ้นมา เพื่อให้สามารถ createChartByType โดยระบุชนิดของกราฟว่าต้องการแบบไหน ในขณะนี้มีสี่แบบได้แก่ column chart, line chart, bar chart และ table chart แต่ละแบบก็จะมีคลาสเป็นของตัวเอง ได้แก่ ColumnChart, LineChart, BarChart และ TableChart ซึ่งจะต้องมีเมธอด draw ไว้สำหรับวาดกราฟเหมือนกันหมด ผมจึงให้พวกมัน implement เจ้า interface ชื่อ GoogleChart เพราะถูกกำหนดให้มีกติกา draw ไว้ภายในครับ

>> สรุป factory pattern เหมาะสำหรับงานที่ต้องการออบเจ็กต์อารมณ์โรงงานที่มีเครื่องจักรสามารถสร้างออบเจ็กต์ให้ได้ทำนองว่าเป็นกลุ่มก้อนเดียวกัน โดยเราสนใจเพียงสิ่งที่ป้อนให้กับมัน (เช่นชื่อกราฟ) มากกว่าที่จะสนใจว่ามันสร้างออบเจ็กต์ (วาดกราฟ) ให้เราได้อย่างไร

>> ผมขอยกมาเพียง chart diagram นะครับ ส่วนโค้ดภาษาจาวาประยุกต์เขียน pattern นี้อย่างไร โปรดเยี่ยมชมลิงค์ต้นฉบับด้านล่างนี้ได้เลยครับ
http://www.tutorialspoint.com/design_pattern/factory_pattern.htm

Proxy Pattern


>> นี่เป็น design pattern ที่ต้องการจะสื่อว่า แหล่งทรัพยากรหรือข้อมูลใดๆที่เราต้องการนั้นอยู่ไกลและราคาแพงครับ เพราะถ้าอยู่ใกล้มากๆและราคาถูกขนาดว่าเรียกปุ๊บได้ใช้ปั๊บ design นี้ก็คงเกิดยากจริงไหม หรือจะกล่าวว่าช่องทางการเข้าถึงทรัพยากรหรือข้อมูลใดๆนั้นมีน้อยก็ย่อมได้ จึงต้องเกิดการกระจายไงล่ะ แต่เหตุผลนี้ก็มีคะแนนน้อยมากอยู่ดี

>> รูปแบบ (pattern) แบบ proxy ก็คือเรามีแหล่งทรัพยากร ในที่นี้ก็คือ server เอาง่ายๆว่าเป็นเครื่อง server แล้วกัน (ใกล้ตัวดี) เก็บสิ่งที่เราต้องการเอาไว้ พอเราอยากได้ก็จะติดต่อไปยัง server แล้วโหลดสิ่งนั้นมา ติดต่อครั้งหนึ่งก็โหลดเอาจาก server ครั้งหนึ่ง เป็นเช่นนี้เรื่อยไปครับ

>> ทีนี้ถ้าพวกเรามีกันสิบคนติดต่อไปยัง server ก็จะได้การติดต่อสิบครั้งจริงไหม ต่างคนก็ต่างโหลดสิ่งที่ตัวเองต้องการ ก็ว่ากันไป แล้วถ้าพวกเรามีกันเป็นพันเป็นหมื่นหรือแสนหรือล้านคนล่ะ? เจ้า server ก็ต้องเหนื่อยลิ้นห้อยหรือไม่ก็หัวใจวายแน่ๆ

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

>> จึงมีการคิดค้น proxy หรือเครื่อง proxy ซึ่งเป็นตัวแทนของ server ขึ้นมา ยามใดที่เราหรือใครๆต้องการทรัพยากรก็แค่ร้องขอไปที่ proxy ก่อน จากนั้น proxy จะตรวจสอบว่าทรัพยากรนี้มีเก็บอยู่ที่มันหรือไม่ ถ้าไม่มีมันก็จะไปโหลดเอาจาก server หนึ่งครั้ง แต่ถ้ามีแล้วมันก็จะไม่ไปโหลดที่ server อีก (โหลดครั้งเดียว) ดังนั้นทรัพยากรอะไรก็ตามที่ซ้ำๆกัน คนแรกที่ร้องขอผ่าน proxy เท่านั้นที่ต้องคอยนานหน่อย เพราะ proxy ต้องติดต่อไปโหลดจาก server ส่วนคนต่อๆไปไม่ต้องคอยนาน เพราะทรัพยากรนั้นมีเก็บไว้ที่ proxy แล้วนั่นเอง

>> ผมขอยกมาเพียง chart diagram นะครับ ส่วนโค้ดภาษาจาวาประยุกต์เขียน pattern นี้อย่างไร โปรดเยี่ยมชมลิงค์ต้นฉบับด้านล่างนี้ได้เลยครับ
http://www.tutorialspoint.com/design_pattern/proxy_pattern.htm

วันเสาร์ที่ 26 กรกฎาคม พ.ศ. 2557

ประโยชน์ของ Design Patterns

>> Design patterns ช่วยให้การจัดโครงสร้างความสัมพันธ์ของแต่ละคลาสภายในโปรแกรมหรืองานใดๆเป็นไปอย่างง่ายดายได้อย่างไร?

ความเห็นที่ 1) ก่อนจะตอบคำถามนี้ แรกเลยต้องทำความเข้าใจก่อนว่าปัญหาที่มักพบเจอในการเขียนโปรแกรมคือ เมื่อโปรแกรมมีความซับซ้อนและจำนวนโค้ดมากขึ้น คนในทีมก็ยากจะทำงานร่วมกันได้เพราะแต่ละคนมีรูปแบบการเขียนโค้ดที่ไม่เหมือนกัน ในกรณีที่โปรแกรมต้องการพัฒนาให้มีฟังก์ชันในการทำงานที่มากกว่าเดิมก็ทำได้ยาก เพราะตัวโค้ดเองถูกพัฒนาโดยไม่มีรูปแบบ

>> ดังนั้น design patterns จึงถูกพัฒนาขึ้นเพื่อใช้เป็นรูปแบบการเขียนโปรแกรมเพื่อแก้ปัญหาโค้ดที่ดูซับซ้อนให้ดูได้ง่ายขึ้น ทำให้ผู้พัฒนาและทีมสามารถเข้าใจสิ่งที่โปรแกรมต้องทำได้ง่ายขึ้น และสามารถเพิ่มฟังก์ชันใหม่ๆเข้าไปในระบบได้ง่ายขึ้น โดยรูปแบบต่างๆถูกคิดค้นมาเพื่อใช้ในงานที่ต่างกัน ได้แก่
- Creational
- Structural
- Behavioral
ที่มา : https://samyarn.com/2014/basic-design-pattern/

ความเห็นที่ 2) โดย (ขอเรียกว่าอาจารย์นะครับ) อาจารย์ pigproxtube

ภาษา JavaScript ฉบับผู้เริ่มต้น part 14-2

: ฟังก์ชันก็คือค่าของตัวแปร (จบเรื่องฟังก์ชัน)

>> ฟังก์ชันของภาษาจาวาสคริปต์เป็นเหมือนกับค่าที่เรากำหนดให้กับตัวแปรครับ ตัวอย่างเช่น

var x = 10;

เราบอกได้ว่า ค่าคงที่ (literal) สิบถูกกำหนดให้กับตัวแปร x หรือก็คือตัวแปร x มีค่าเท่ากับสิบ ดังนั้นจากคำกล่าวที่ว่า 'ฟังก์ชันก็คือค่าของตัวแปร' จึงสามารถเขียนได้ในรูปแบบต่อไปนี้ด้วยครับ

var x = function( ) { return 10; };

document.write( x() ); ผลลัพธ์เท่ากับ 10

>> ซึ่งจากตัวอย่างข้างต้น หากเราเขียนว่า document.write( x ); เฉยๆแบบนี้ก็จะได้ค่าเป็นฟังก์ชันที่ถูกกำหนดให้ x หรือก็คือค่า "function ( ) { return 10; }" นั่นเอง

>> และเรียกค่าของตัวแปรที่ถูกกำหนดให้เป็นฟังก์ชันว่า Function Literal โดยพิสูจน์ได้จากตัวอย่างต่อไปนี้

var x = 10;
document.write( typeof(x) ); ผลลัพธ์เท่ากับ number
var y = function() { };
document.write( typeof(y) ); ผลลัพธ์เท่ากับ function

>> เราสามารถส่งค่าที่เป็น function เหมือนกับการส่งค่าประเภทอื่นๆ ตัวอย่างเช่น
var x = 10;
var y = x;
document.write( y ); ผลลัพธ์เท่ากับ 10

ในทำนองเดียวกัน

var x = function() { return 99; };
var y = x;
document.write( y() ); ผลลัพธ์เท่ากับ 99

>> ย้อนกลับไปเรื่องของ array กับฟังก์ชันที่ชื่อว่า sort โดยปกติจะแปลงค่าในอาร์เรย์ทั้งหมดเป็นสตริงแล้วนำมาเปรียบเทียบกันใช่ไหมครับ ถ้าค่าทั้งหมดนั้นเป็นตัวเลข ก็จะได้ชุดตัวเลขที่เรียงลำดับจากน้อยไปหามาก ดังนี้
var x = [30, 20, 40, 50, 10];
x.sort();
document.write( x.join() ); ผลลัพธ์เท่ากับ 10,20,30,40,50

>> ทว่าเราสามารถกำหนดค่าการ sort ให้เป็นแบบอื่นได้ (เช่น เรียงลำดับจากมากไปหาน้อย) โดยส่งค่าฟังก์ชันต่อไปนี้เข้าไป
var maxToMin = function( first, second ) { return second - first; };
x.sort( maxToMin );
document.write( x.join() ); ผลลัพธ์เท่ากับ 50,40,30,20,10

>> อ่านเพิ่มเติมเกี่ยวกับอัลกอริทึมการ sort พร้อมเหตุผล
http://www.w3schools.com/jsref/jsref_sort.asp

>> โอกาสหน้าพบกับ Object และ Class หัวใจของการ design pattern ที่น่าหลงไหล เรื่องสุดท้ายก่อนที่เราจะไปมันส์กันต่อกับการสร้างเกมด้วยภาษาจาวาสคริปต์ครับผม

วันศุกร์ที่ 25 กรกฎาคม พ.ศ. 2557

ภาษา JavaScript ฉบับผู้เริ่มต้น part 14-1

: ฟังก์ชันหรือก็คือค่าของตัวแปรในรูปแบบฟังก์ชัน

>> ฟังก์ชัน (function) คืออะไรคะ?
ตอบ โดยทั่วไปคือกลุ่มโค้ดที่เขียนซ้ำๆในโปรแกรม ใช้อัลกอริทึมเดียวกันทั้งหมด เราจะแยกกลุ่มโค้ดเหล่านั้นออกมา ตั้งชื่อให้กับมัน และเรียกพวกมันโดยรวมว่าฟังก์ชันครับ

>> ประโยชน์ของฟังก์ชันคืออะไรครับ
ตอบ เพราะฟังก์ชันคือโค้ดที่เขียนด้วยอัลกอริทึมเดียวกัน (เขียนโค้ดเหมือนกัน) เมื่อเราแยกโค้ดเป็นฟังก์ชันต่างๆ ก็จะทำให้แก้ไขโปรแกรมได้ง่ายขึ้น เมื่อแก้ไขเพียงจุดเดียวก็จะทำให้จุดอื่นๆที่เรียกใช้ฟังก์ชันเดียวกันนี้ได้รับผลไปด้วย ทั้งยังอำนวยความสะดวกปกปิดโค้ดที่ซับซ้อนซึ่งเราไม่ได้มุ่งเน้นในลอจิกของเรา ตัวอย่างเช่น
document.write( ) สามารถแสดงข้อความออกไปที่หน้าเว็บบราเซอร์ได้
array.join( ) สามารถคืนค่าเป็นสตริงของสมาชิกทั้งหมดออกมาได้

>> จะสร้างฟังก์ชันได้อย่างไรล่ะ?
ตอบ เราควรทราบก่อนว่าฟังก์ชันของภาษาจาวาสคริปต์นั้น นอกจากจะใช้แบ่งโปรแกรมออกเป็นการทำงานย่อยๆแล้ว มันยังสามารถเป็นค่าของตัวแปรได้อีกด้วย แต่ก่อนจะกล่าวถึงประเด็นหลัง มาเรียนรู้วิธีการสร้างฟังก์ชันขึ้นมาก่อน

function functionName( parameters ) { ... }

แจกแจงดังนี้
- อันดับแรกคือคีย์ function ต้องเขียนแบบนี้เลยนะ
- ต่อไปก็ functionName ซึ่งจะตั้งชื่ออะไรก็ได้ เหมือนกับการตั้งชื่อตัวแปร ทว่าขอให้สื่อความหมายต่อกระบวนการที่ทำเป็นใช้ได้
- วงเล็บ ( และ ) จำเป็นต้องมีเสมอ
- parameters มีหรือไม่มีก็ได้ มีกี่ตัวก็ได้ มันก็คือชื่อตัวแปรใดๆก็ได้ที่เป็นทางผ่านของ input ที่ต้องการส่งให้กับฟังก์ชัน
- วงเล็บ { และ } จำเป็นต้องมีเสมอ
- สุดท้ายคือโค้ดที่เป็นอัลกอริทึมของฟังก์ชัน และหากฟังก์ชันนี้ส่งค่าผลลัพธ์กลับออกไปได้ ก็ควรระบุคีย์ return ด้วยนะ

>> สำคัญมาก เหล่า parameters ต่างๆที่ถูกกำหนดขึ้น รวมถึงทุกตัวแปรที่ประกาศในฟังก์ชันเป็นตัวแปร local ทั้งหมด

>> ตัวอย่างการสร้างฟังก์ชันบวกเลขสองจำนวน

function summation(x, y) {
return x + y;
}

document.write( summation(10, 20) ); ผลลัพธ์คือ 30
document.write( summation(-10, 10) ); ผลลัพธ์คือ 0

>> รู้จักกับตัวแปร arguments
ตัวแปร arguments เป็น implicit หรือก็คือตัวแปรที่จาวาสคริปต์เตรียมไว้ให้ใช้ สามารถอ้างอิงเพื่อใช้งานได้เลย มันมีชนิดเป็น array และเราสามารถนำมันมาประยุกต์ใช้ได้ดังตัวอย่างต่อไปนี้ สมมติเขียนฟังก์ชัน summation ขึ้นใหม่ ให้รับค่ามาบวกกันเท่าไรก็ได้

function summation() {
var sum = 0;
for(var i = 0; i < arguments.length; i++) { sum = sum + arguments[i]; }
return sum;
}

document.write( summation(10, 20) ); ผลลัพธ์คือ 30
document.write( summation(10, 20, 30, 40) ); ผลลัพธ์คือ 100
document.write( summation() ); ผลลัพธ์คือ 0

>> part นี้ยาวเกินไปแล้ว ไว้ part หน้าเราจะมาคุยกันว่าฟังก์ชันที่เป็นค่าของตัวแปรได้อีกด้วยนั้นเป็นเช่นไร

>> อ้อ ขอแนะนำ blog ของ Level Up Studio ไว้ด้วยนะครับ เห็นว่าทำ blog ได้สวยถูกใจดี พร้อมเนื้อหาการใช้ foreach กับ array ครับ
http://blog.levelup.in.th/2010/06/30/javascripts-foreach-foreach-%E0%B9%83%E0%B8%99-javascript/

วันอังคารที่ 22 กรกฎาคม พ.ศ. 2557

ภาษา JavaScript ฉบับผู้เริ่มต้น part 13

: ทบทวนเรื่องการประกาศและขอบเขตการใช้งานตัวแปร

>> ตัวแปรในภาษาจาวาสคริปต์ใดๆสามารถเก็บข้อมูลชนิดใดก็ได้ (untyped)

>> การประกาศตัวแปรด้วยคีย์ var ซ้ำกันสามารถทำได้ ให้ผลเป็นตัวแปรเดียวกัน เช่น
var x = 10;
var x = 20;
document.write( x ); ได้ผลลัพธ์เท่ากับ 20

>> การเรียกใช้ตัวแปรที่ไม่ได้กำหนดค่าให้ จะให้ผลเป็น undefined เสมอ

>> การเรียกใช้ตัวแปรที่ไม่ได้ประกาศไว้ จะให้ผลเป็น undeclared error

>> ตัวแปรในภาษาจาวาสคริปต์แยกได้ สอง ขอบเขต คือ global กับ local

>> ขอบเขต global คือการประกาศตัวแปรนอกฟังก์ชัน ส่วนขอบเขต local คือการประกาศตัวแปรในฟังก์ชัน

>> ตัวแปรที่อยู่ในขอบเขต global สามารถเรียก ณ ที่ใดในสคริปต์ก็ได้ (ในหน้า html นั้น) ต่างจากตัวแปรที่อยู่ในขอบเขต local สามารถเรียกได้ภายในฟังก์ชันเท่านั้น

>> สามารถประกาศตัวแปร global ชื่อเดียวกับ local ได้ และหากเรียกใช้ตัวแปรดังกล่าวภายในฟังก์ชัน จะถือว่าเรียกใช้ตัวแปร local นะจ๊ะ ตัวอย่างเช่น
var x = 10;
function area() {
var x = 20;
document.write( x );
}

area(); ผลลัพธ์คือ 20
document.write( x ); ผลลัพธ์คือ 10

>> หากละคีย์ var สำหรับการประกาศตัวแปร local ด้วยตัวอย่างข้างต้น จะถือเป็นการกำหนดค่าให้ตัวแปร global หรือก็คือการกำหนดค่าใหม่ให้กับตัวแปรที่ถูกประกาศแล้วผ่านฟังก์ชันเท่านั้นเอง
var x = 10;
function area() {
x = 20;
document.write( x );
}

area(); ผลลัพธ์คือ 20
document.write( x ); ผลลัพธ์คือ 20

>> ตัวแปรในภาษาจาวาสคริปต์ไม่มีระบบ block-level ตัวอย่างต่อไปนี้สามารถแสดงค่าของ y ได้แม้ว่าจะประกาศมันภายใน scope ของ if-else
function typeOfNumber( x ) {
if ( x >= 0 ) { var y = "positive integer"; }
else { var y = "negative integer"; }
document.write( y );
}

typeOfNumber( 10 ); ผลลัพธ์คือ "positive integer"

>> ในฟังก์ชันใดๆของจาวาสคริปต์ ตัวแปร local ที่ถูกประกาศจะเก็บไว้ในหน่วยความจำชั่วคราว เมื่อลำดับการประกาศตัวแปรนั้นไม่ถูกต้อง ค่าที่ได้จึงเป็น undefined ไม่ใช่ undeclared error แม้กระทั่งมีตัวแปร global ถูกประกาศไว้ก่อน แล้วเรียกชื่อของตัวแปร global นั้นภายในฟังก์ชัน ค่าที่ได้ก็ยังคงเป็น undefined ด้วยเหตุผลเดียวกัน ตัวอย่างเช่น
var x = 10;
function test() {
document.write( x );
var x = 30;
}

test(); ผลลัพธ์คือ undefined

>> เราสามารถแก้ไขผลลัพธ์ของตัวอย่างข้างต้นให้ถูกต้องด้วยการลบบรรทัด
var x = 30; ทิ้งไป เท่านี้มันก็จะไปใช้ค่าของตัวแปร global แทน

>> โอกาสหน้าพบกับเรื่อง Functions ก่อนจะโถมเข้าเรื่องคลาสกับออบเจ็กต์แบบจัดหนักเต็มลูกสูบฉบับผู้เริ่มต้นเช่นเคยครับ

วันจันทร์ที่ 21 กรกฎาคม พ.ศ. 2557

ภาษา JavaScript ฉบับผู้เริ่มต้น part 12-3

: Arrays กับฟังก์ชันของมัน (จบตอนอาร์เรย์)

>> ฟังก์ชัน join(separator:string) : string
คืนสตริงใหม่ที่เกิดจากคั้นด้วย separator ตัวอย่างเช่น
var weights = [10, 20, 30];
document.write( weights.join() ); ผลคือ "10,20,30"
document.write( weights.join("/") ); ผลคือ "10/20/30"

>> ฟังก์ชัน reverse() : void
เปลี่ยนลำดับสมาชิกภายในอาร์เรย์จากหน้าไปหลัง จากหลังมาหน้า
weights.reverse();
document.write( weights.join() ); ผลคือ "30,20,10"

>> ฟังก์ชัน sort(function:Function) : Array
เรียงลำดับค่าในอาร์เรย์ตามเงื่อนไขของ function ที่มีชนิดเป็นฟังก์ชัน (Function) (รายละเอียดละไว้ก่อน ไว้ค่อยคุยกันทีหลังนะจ๊ะ) หากไม่กำหนด คือเขียนแค่ sort() เฉยๆ จะเปลี่ยนค่าในอาร์เรย์ทั้งหมดเป็นสตริง แล้วนำมาเปรียบเทียบกันเจ้าค่ะ โดยการเปลี่ยนแปลงนี้เกิดขึ้นในตัวอาร์เรย์เองเลยด้วย
var myGirlfriends = [ "Pro", "Phai", 2 ];
myGirlfriends.sort();
document.write( myGirlfriends.join() ); ผลคือ "2,Phai,Pro"

>> ฟังก์ชัน concat(value...) : Array
เพิ่มสมาชิกให้อาร์เรย์แบบต่อเนื่องไปเรื่อยๆ (ได้อาร์เรย์ใหม่) โดยที่ตัวอาร์เรย์เดิมยังมีสมาชิกคงเดิม
var agents = [ "A", "B", "C" ];
var agentList = agents.concat( "D", "E" );
document.write( agentList.join() ); ผลคือ "A,B,C,D,E"
document.write( "<br/>" );
document.write( agents.join() ); ผลคือ "A,B,C"

>> ขอบคุณ JavaScript Programming Guide ที่นำความรู้มาให้ และนี่คือฟังก์ชันอื่นๆเพิ่มเติมจากที่ได้ยกตัวอย่างครับ
http://www.w3schools.com/jsref/jsref_obj_array.asp

>> หัดเขียนหัดใช้นะครับ ใจผมก็ไม่คิดชอบ แต่คิดว่าไม่เกินความพยายาม ทุกวันนี้เหงาก็เขียนโปรแกรม เกรียนก็อ่านหนังสือ อ่านได้น้อยไม่เข้าใจก็มักน้อยใจตัวเอง แต่ผมก็ทำอยู่เนื่องๆ ฟังเพลงทำนองเอามันส์ไว้ก่อน หัวเราะหรือร้องไห้คนเดียวประจำ ชีวิตก็โอเคนะ 555

วันเสาร์ที่ 19 กรกฎาคม พ.ศ. 2557

ภาษา JavaScript ฉบับผู้เริ่มต้น part 12-2

: Arrays กับความสามารถของมัน

>> เมื่อเพื่อนๆได้รู้จักอาร์เรย์ไปบ้างแล้ว เพื่อนๆควรทราบว่าเราสามารถสร้างอาร์เรย์ว่างได้ หรือก็คืออาร์เรย์ที่มีขนาดเป็นศูนย์ หรือกล่าวว่ายังไม่มีสมาชิกนั่นเอง เราเรียกอาร์เรย์ลักษณะนี้ว่า Empty Array ครับ

- สร้าง array ด้วย array literal ตัวอย่างเช่น
var sims = [ ];
- สร้าง array ด้วย array constructor ตัวอย่างเช่น
var weights = new Array();

>> เรายังสามารถจองพื้นที่หรือจองขนาดของอาร์เรย์ได้ด้วย เช่น จองอาร์เรย์สำหรับเก็บหมายเลขโทรศัพท์ของซิมจำนวนสิบหมายเลข จะเขียนได้ว่า
var sims = new Array(10);

>> เราสามารถสอบถามขนาดของอาร์เรย์ได้ โดยถามจากพร็อพเพอร์ตี้ชื่อ length ดังนี้
sims.length จะได้ค่าเท่ากับ 10
weights.length จะได้ค่าเท่ากับ 5

>> และยังปรับลดขนาดของอาร์เรย์ได้ดั่งใจ ตัวอย่างเช่น

sims.length = 3; หมายความว่าขณะนี้เหลือซิมเพียงสามหมายเลขเท่านั้น คือหมายเลข ณ sims[0], sims[1] และ sims[2] ที่เหลือหายไปสิ้นแล้ว โปรดระวังการลดขนาดอาร์เรย์ เพราะจะทำให้สูญเสียข้อมูล

weights.length = 20; หมายความว่าขณะนี้มีผู้ต้องการเข้าร่วมโครงการลดน้ำหนักเพิ่มเป็น 20 คน (จากเดิม 5 คน) ซึ่งการเพิ่มขนาดของอาร์เรย์ไม่ส่งผลกระทบใดๆต่อข้อมูลเดิมที่มีอยู่

>> ตัวอย่างต่อไปนี้คือโปรแกรมสอบถามความต้องการของผู้ที่ต้องการซื้อบ้านในโครงการที่มีชื่อว่า 'ปันบ้านสร้างมิตร คืนชีวิตที่เป็นสุขให้กับคุณและครอบครัว'


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

- elements.length ขอขนาดของอาร์เรย์ตามจำนวนสมาชิกที่บรรจุอยู่ภายในฟอร์ม ซึ่งได้ค่าเท่ากับ 4

- elements[optionSize - 1] อ้างถึงสมาชิกลำดับที่ 4 (มีค่า index เท่ากับ 3) หรือก็คือตัวเลือกที่มีชื่อว่า 'เลือกทั้งหมด' นั่นแหละครับ

- elements[index] หมายถึงตัวเลือกใดๆที่บรรจุอยู่ภายในฟอร์ม จากโค้ดเป็นไปได้สามค่า ได้แก่ elements[0], elements[1] และ elements[2] หรือก็คือตัวเลือกลำดับที่ 1, 2 และ 3

>> ตัวอย่างนี้แถมเรื่องฟังก์ชัน (Function) มาด้วย แน่นอนว่าจะต้องกล่าวถึงใน part ต่อๆไป จบเรื่องฟังก์ชันคงได้มันส์กันมากกว่านี้ หุหุ สวัสดีครับ

ภาษา JavaScript ฉบับผู้เริ่มต้น part 12-1

: Arrays ที่น่าพิสมัย

>> ในที่สุดก็มาถึงโครงสร้างข้อมูลที่ซับซ้อนขึ้นอีกนิด แต่ไม่ได้ยากเกินจะเข้าใจ หลายคนรู้จักแล้ว หลายคนลืม หลายคนต้องเปิดตำราหรือเว็บเพื่อกระตุ้นหน่วยความจำ และหลายคนเพิ่งได้รู้รวมถึงผมด้วย ดังนั้นโอกาสนี้เราจะมาตอบสามคำถามที่ควรรู้เกี่ยวกับอาร์เรย์ (array) ครับ

1) อาร์เรย์คืออะไร?
2) อาร์เรย์สร้างอย่างไร?
3) อาร์เรย์ใช้อย่างไร?

>> อาร์เรย์คืออะไร?
ตอบ ของ่ายๆเลยนะครับ คือตัวแปรชุด มีเป็นชุด มีเป็นเซต เหมามาแบบยกชุด ตัวอย่างเช่น
- น้องซื้อซิมป๊ะ เนี่ยเบอร์ละยี่สิบบาท เหลือสิบเบอร์แล้วสวยๆทั้งนั้น จะเห็นว่าซิมโทรศัพท์ยกมาเป็นชุด อาจตั้งชื่อตัวแปรนี้ว่า sim มีจำนวนทั้งสิ้นสิบตัวแปร จึงเขียนเป็น sim1, sim2, sim3, ...sim10 เป็นต้น
- นี่พวกเรา! เพราะวันนี้เราจะมาลดความอ้วนกัน เรามีกันห้าคน ไหนบอกซิว่าก่อนลดใครมีน้ำหนักเท่าไรบ้าง จะเห็นว่าน้ำหนักยกมาเป็นชุด อาจตั้งชื่อตัวแปรนี้ว่า weight มีจำนวนทั้งสิ้นห้าตัวแปร จึงเขียนเป็น weight1, weight2, ...weight5

ดังนั้นอาร์เรย์ก็คือคอลเลคชันของ elements ที่แต่ละ element เอาไว้เก็บข้อมูลที่มีความสัมพันธ์ในทิศทางเดียวกัน เช่น เก็บเบอร์โทรศัพท์ทั้งหมดหรือเก็บค่าน้ำหนักทั้งหมด เป็นต้น

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

>> อาร์เรย์สร้างอย่างไร?
ตอบ จากตัวอย่างที่ยกมาข้างต้น ตัวแปร sim มีสิบตัว ตัวแปร weight อีกห้าตัว แต่ที่น่ากลัวคือในทางปฏิบัติจริงๆแล้วจำนวนอาจมากกว่านี้หลายเท่า กรี๊ด! (ใครจะมานั่งประกาศตัวแปรเป็นร้อยๆเป็นพันๆชื่อจริงไหม หรืออาจมี!?) ซึ่งเหล่านี้ควรถูกจัดการด้วยอาร์เรย์ด้วยวิธีการสร้างอาร์เรย์ดังนี้ครับ
- สร้างด้วย Array Literal
- สร้างด้วย Array Constructor

>> สร้างด้วย Array Literal
literal ก็คือค่าที่ใช้กำหนดให้กับตัวแปร เป็นตัวอักษร ตัวเลข เป็นสตริงหรืออื่นๆ โดยมีรูปแบบคือ
var arrayName = [ value1, value2, ..., valueN ];
ตัวอย่างเช่น
var sims = ["0843677455", "0893666451", "0815501956", "0893991999", "0873677454", "0819606857", "0890900090", "0831545678", "0821221222", "0800000000"];

>> สร้างด้วย Array Constructor
ก็เหมือนกับตอนประกาศตัวแปรชนิดออบเจ็กต์ครับ คือต้องมีคำสั่ง new มาร่วม โดยมีรูปแบบคือ
var arrayName = new Array( value1, value2, ..., valueN );
ตัวอย่างเช่น
var weights = new Array(60, 63, 75, 120, 40);

>> อาร์เรย์ใช้อย่างไร?
ตอบ ใช้ง่ายมากครับ เพียงใส่ตัวเลขที่เรียกว่า index ลงไประหว่างเครื่องหมาย [ และ ] ก็จะสามารถเข้าถึงค่าที่เก็บไว้ภายในตัวแปรอาร์เรย์นั้นๆได้เลย โดยมีกฎกติกาเพิ่มเติมมาเพียงเล็กน้อยเท่านั้น กล่าวคือค่าของ index ถูกกำหนดให้เริ่มต้นที่เลขศูนย์ ดังนั้น index ใดๆที่เราต้องการเข้าถึงจึงต้องลบด้วยหนึ่งเสมอ
ตัวอย่างเช่น
- พี่ค่ะ หนูอยากได้ซิมหมายเลข "0843677455" นั่นคือ sims[0]
- พี่ขา หนูขอดูเบอร์ "0893666451" หน่อยสิคะ นั่นคือ sims[1]
- พี่ๆ หยิบเบอร์ "0815501956" ให้ผมที นั่นคือ sims[2]
- น้องๆพี่เอาเบอร์ "0800000000" นั่นคือ sims[9]
- และถ้ามีกวนทีนขอซิมที่ไม่มีอยู่ในรายการ เช่นขอเบอร์ "0888888888" นั่นคืออ้างมั่ว ค่าที่ได้แทนที่จะเป็นหมายเลขโทรศัพท์ก็จะได้ undefined หรือกำปั้นนั่นเอง

>> หมายเหตุ อาร์เรย์นั้นไม่ว่าจะสร้างด้วยวิธี literal หรือ constructor ไม่มีความแตกต่างกัน ได้เป็นชนิดออบเจ็กต์ทั้งคู่ สามารถหดยืดขนาดได้อัตโนมัติซึ่งจะขอยกไปเล่ายัง part ต่อไป สวัสดีครับ

วันพฤหัสบดีที่ 17 กรกฎาคม พ.ศ. 2557

ภาษา JavaScript ฉบับผู้เริ่มต้น part 11

: การจัดการ errors ด้วย try/catch

>> อะไรคือ error เหรอจ๊ะ?
ตอบ คือความผิดพลาดต่างๆที่เกิดขึ้นกับโปรแกรม ไม่ว่าจะเกิดขึ้นจากสภาพแวดล้อมที่โปรแกรมนั้นทำงานอยู่ หรือเกิดจากอัลกอริทึมของเราเอง หรือกระทั่งเกิดจากการเขียนโปรแกรมผิดไวยากรณ์ ขอยกตัวอย่างง่ายๆดังนี้นะครับ แม่จะทำกับข้าว แต่ว่ารสดีหมด จึงใช้ลูกชายจอมซนไปซื้อมาให้หน่อย ถ้าเกิดว่าลูกชายสามารถซื้อรสดีกลับมาให้แม่ได้แสดงว่าโปรแกรมนี้ทำงานปกติ เอาล่ะครับ เหตุการณ์ต่อไปนี้อาจเกิดขึ้น ซึ่งถือเป็นข้อผิดพลาดในลักษณะที่แตกต่างกัน

- กรณีที่ 1 ถ้าเกิดแม่บอกว่าเอามอไซค์ไปนะลูก แต่ลูกกลับดื้อเดินไปเฉยเลย กว่าแม่จะได้รสดีเธอก็หมดอารมณ์ทำกับข้าวไปเสียแล้ว... ความผิดพลาดนี้คือสภาพแวดล้อมขณะที่โปรแกรมทำงานครับ ในกรณีนี้คือทำงานได้ แต่ใช้เวลานานเกินไป

- กรณีที่ 2 ลูกเอามอไซค์ไปอย่างที่แม่บอก ทว่ากลับมาพร้อมผงชูรสตราชฎา? ความผิดพลาดนี้คืออัลกอริทึมผิดพลาด หรือที่เรียกว่า logic error กล่าวคือโปรแกรมไม่พัง แต่ผลลัพธ์ไปดาวอังคาร คือไม่ถูกต้องตามที่ต้องการนั่นเอง

- กรณีที่ 3 ขณะที่ลูกขับมอไซค์อยู่นั้น ปรากฏว่าขับไปชนหมา เอ๋ง!!! รถล้มได้รับบาดเจ็บถึงขั้นต้องหามส่งอนามัยหมู่บ้าน (อุ้มหมาไปรักษา เฮ้ยไม่ใช่) ลูกชายไม่สามารถซื้อรสดีกลับมาให้แม่ได้ มิหนำซ้ำกับข้าวแม่ก็ไม่ได้ทำเพราะเป็นห่วงลูก ความผิดพลาดลักษณะนี้คือ runtime error เกิดขึ้นขณะที่โปรแกรมกำลังทำงานอยู่ อาจเป็นที่หน่วยความจำ ระบบเน็ตเวิร์คหรืออะไรก็แล้วแต่ ที่มีผลทำให้สภาพแวดล้อมของโปรแกรมเปลี่ยนไป เป็นไปได้ทั้งหมดครับ ขอยกตัวอย่างง่ายๆ เช่น ตั้งตัวแปร x เก็บค่า 10 ไว้ แล้วหารมันด้วย 10 ด้วย 8 ด้วย 6 (สมมติ) ลดลงทีละสองในแต่ละรอบ สุดท้ายหาร x ด้วย 0 ก็เกิด runtime error ขึ้นจนได้ กรณีอย่างนี้จะต้องคิดให้ดี คิดอย่างหวาดระแวงเข้าไว้

- กรณีที่ 4 แม่บอกลูกว่าซื้อรสดีให้หน่อยสิจ๊ะลูกจ๋า ลูกบอกไม่! แล้วก็นั่งเล่นเกมคอมพิวเตอร์ต่อไป หรือทำอะไรก็แล้วแต่ที่เป็นการขัดขวางความตั้งใจของแม่ที่ต้องการให้ลูกไปซื้อรสดีให้ในเชิงของโครงสร้าง ความผิดพลาดลักษณะนี้มักตรวจเจอตั้งแต่สั่ง compile หรือรันโปรแกรม เขาเรียกกันว่าไวยากรณ์ผิดพลาดหรือก็คือ syntax error นั่นแหละจ้า

>> ภาษาจาวาสคริปต์มี error อยู่สามประเภทหลักๆคือ
1) Syntax Error
2) Runtime Error
3) Logic Error
และต้องเข้าใจร่วมกันว่า จาวาสคริปต์นี้ไม่ครอบคลุมความผิดพลาดที่เกิดจากการเขียน syntax ผิดนะครับ (ไวยากรณ์เล็กๆน้อยๆ ถึงผิดมันก็ยอมให้ผ่านและทำงานได้) ควรระมัดระวังนิดนึง~

>> เราจะใช้คำสั่ง try/catch ห่อและรายงานความผิดพลาดที่เกิดขึ้น โดยเขียนโค้ดตามปกติในบล็อกของ try เมื่อเกิด error ขึ้น บล็อกของ catch จะถูกรันโดยอัตโนมัติ เรียกลักษณะเช่นนี้ว่าการจัดการความผิดพลาดด้วย try/catch

โครงสร้างของ try/catch คือ

try {
...
} catch ( ex ) {
...
}

ตัวอย่างเช่น

var x = 10, y = 20;
try {
var sum = x + y + z;
} catch ( ex ) {
alert ( ex.name );
alert ( ex.message );
}

คำตอบของ ex.name คือ ReferenceError คำตอบของ ex.message คือ z is not defined หรือจะเขียนการรายงานความผิดพลาดสั้นๆเพียง

alert ( ex );

ก็จะได้ผลลัพธ์เป็น ReferenceError: z is not defined หมายความว่าตัวแปร z ไม่ถูกประกาศแล้วจะอ้างอิงได้อย่างไร ประมาณนี้ครับ

>> ใน part ต่อไปเราจะคุยกันเรื่องของ Arrays มันคืออะไร ประกาศอย่างไร ใช้อย่างไร เราจะแหกแหวกมันออกมาชม ให้ขมขื่นน้ำตาไหลรินกันเลยทีเดียวเทียว อิอิอิ

ภาษา JavaScript ฉบับผู้เริ่มต้น part 10

: Iteration Statements เหล่าคำสั่งทำซ้ำ

>> คำสั่งทำซ้ำคืออะไรเหรอ?
ตอบ เพื่อนๆเคยใช้ if เคยใช้ switch มาแล้ว ตอนนี้รู้แล้วว่าพวกมันคือทางเลือกเพื่อกระทำอย่างหนึ่งอย่างใดใช่ไหม จะทำจริงหรือทำเท็จควบคุมสมใจอยาก บัดนี้ทางเลือกเหล่านั้นอาจไม่เพียงพอครับ ไม่พอในที่นี้คือ อาจต้องเขียนโค้ดเยอะ เขียนโค้ดยาวตามปริมาณข้อมูลที่มีอยู่เป็นร้อย เป็นพัน หรือเป็นหมื่นๆ หรือไม่รู้ด้วยซ้ำว่าปริมาณข้อมูลมีอยู่มากน้อย หรือต้องเขียนจาวาสคริปต์ให้หยุดรอคำสั่งยกเลิกจากผู้ใช้งาน โปรแกรมเมนูอาหารจึงจะปิดตัวลงไป อีกหลายหลากเหตุผลที่จำเป็นต้องมีกลุ่มคำสั่งจำพวกทำซ้ำ ซึ่งได้แก่
- for statement
- while statement
- do-while statement

>> ปริมาณข้อมูลเป็นที่ทราบแน่ชัด จำนวนรอบรู้แจ้งเห็นจริง ควรเลือกใช้ for statement เหตุผลคือ?
ตอบ for ถูกคิดขึ้นเพื่องานที่รู้จำนวนอย่างแน่นอน มีตัวแปร index คอยเพิ่มหรือลดค่าใดๆเพื่อบังคับให้เกิดรอบการทำงานทำซ้ำจนกว่าค่าของ index นั้นจะขัดกับเงื่อนไข ตัวอย่างเช่น

for ( var i = 0; i < 10; i++ ) {
document.write( i );
}

ผลลัพธ์จะได้ 0123456789 แสดงออก ณ บราเซอร์ เพราะค่าของ i ต้องน้อยกว่า 10 ดังนั้นค่าสูงสุดที่ได้จึงเท่ากับ 9 นั่นเอง และในที่นี้ตัวแปร i ก็คือ index ที่บังคับการเกิดรอบดังกล่าว

>> ทำทุกอย่างได้เหมือน for แต่ถูกออกแบบให้รับกับเงื่อนไขที่เป็นจริงอยู่เสมอจึงจะทำงาน ไม่คํานึงถึงจำนวนรอบหรือการทำซ้ำที่จะเกิด เอาเป็นว่าเงื่อนไขเป็นเท็จเมื่อไรค่อยออกจากวงวน ลักษระงานแบบนี้ให้เลือกใช้ while statement ครับ เหตุผลคือ?
ตอบ จริงอยู่ที่ทั้ง while และ for สามารถกำหนดเงื่อนไขและตัวแปร index ให้ทำงานอย่างเดียวกันเป๊ะๆ ทว่าตำราหลายเล่มได้กล่าวเอาไว้ว่า หากต้องนับจำนวนหรือค่าใดๆโดยขึ้นกับรอบและตัวแปร index ให้ใช้ for, แต่หากเป็นเงื่อนไขที่ไม่เกี่ยวข้องกับที่ยกมานี้ให้ใช้ while เพราะจะสื่อความหมายได้ดีกว่า อย่างน้อยก็ทำให้รู้ว่าสนใจรอบหรือไม่ ตัวอย่างการเขียน while ให้ทำงานดุจเดียวกับ for ข้างต้น

var i = 0;
while( i < 10 ) {
document.write( i );
i++;
}

ตัวอย่างการใช้ while ที่ไม่เกี่ยวกับจำนวนรอบ : โปรแกรมป้อนเลขท้ายสองตัว

var userInput = prompt("Please, Input your last two digits in a lottery ticket in this box.");
userInput = parseInt(userInput);

while ( userInput != 88 ) {
userInput = prompt("Please, Input your last two digits in a lottery ticket in this box.");
userInput = parseInt(userInput);
}

alert("You won the prize!!!");

โปรแกรมป้อนเลขท้ายสองตัวนี้ ป้อนผิดมันจะถามอยู่เรื่อยๆ แต่ถ้าป้อนถูก (ตัวเลขที่ถูกรางวัลคือ 88) ก็จะแสดงข้อความว่าคุณถูกรางวัลนะ แล้วจบโปรแกรมไป

>> ทำทุกอย่างได้เหมือนกับ while ต่างเพียงสิ่งที่ทำนั้นทำก่อนการตรวจสอบเงื่อนไข กล่าวคือ กระทำคำสั่งที่ต้องการไปก่อนครั้งหนึ่ง แล้วค่อยถามว่าจะทำซ้ำอีกหรือไม่ ลักษณะงานแบบนี้สมควรให้ do-while statement

ตัวอย่างการเขียน do-while ที่ให้ผลลัพธ์เช่นเดียวกับ while และ for ข้างต้น

var i = 0;
do {
document.write( i );
i++;
} while( i < 10 );

มันจะทำคำสั่ง document.write ก่อนครึ้งหนึ่งแล้วค่อยไปถามว่า i ยังคงน้อยกว่า 10 หรือไม่ ซึ่งต่างจาก while ที่ต้องถามคำถามนี้ก่อน

>> เนื้องจากว่าหน้ากระดาษ (อิเล็กทรอนิกส์) นี้ยาวเกินไปแล้ว part ต่อไปจะแนะนำการจัดการ errors ด้วย try/catch ครับ สวัสดีครับ

ภาษา JavaScript ฉบับผู้เริ่มต้น part 9

: ควบคุม Keyboard ด้วย JavaScript

>> ตอนนี้ฉันรู้แล้วว่าเธอทั้งหลายรู้จักภาษาจาวาสคริปต์กันพอสมควรแล้ว ถึงแม้จะไม่ถึงครึ่งของครึ่งของครึ่ง (แอบเศร้า) แต่ก็พอนำมันมาสร้างเป็นงานชิ้นเล็กๆได้แล้วนะเออ โอกาสนี้ฉันก็เลยจะชวนเธอมาดักจับเหตุการณ์การกดปุ่มใดๆบนคีย์บอร์ดกัน เอาละสิ แล้วต้องรู้เรื่องไหนบ้าง มาๆฉันจะเล่าสิ่งที่ฉันพอจะรู้ให้ฟัง

>> เธอที่น่ารักต้องรู้จักเจ้า Event Listener ก่อนนะ (ฉันอยากให้เธอใช้ตัวนี้) แล้วมันคืออะไรเหรอจ๊ะ?
ตอบ มันก็คือนักฟัง ที่จะคอยฟังสิ่งต่างๆที่อาจเกิดขึ้นเมื่อไรก็ได้ ฟังเพื่อต้องการกระทำอย่างหนึ่งอย่างใดจากสิ่งที่ฟังนั่นเอง ยังไม่เข้าใจอะ? เอางี้ รู้จักพวกชอบแอบฟังแอบดูชาวบ้านไหม ใครกำลังดัง ใครภาพหลุด ใครตบกับใคร ใครแย่งแฟนใคร ต้าย! นั่นแหละพวกชอบนินทาชาวบ้านก็ด้วย คือฟังแล้วเอามาเล่าต่อ ขยายเรื่องจริงสร้างเรื่องเท็จสนุกสนานกันวุ่นวาย

อ่านเพิ่มเติมเกี่ยวกับ JavaScript Event Listener
- จากเว็บมาตราฐาน http://www.w3schools.com/jsref/dom_obj_event.asp
- เข้าใจมันมากขึ้นพร้อมกับตัวอย่างที่ดี https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener

>> เธอที่น่ารักต้องเข้าใจว่าทุกปุ่มที่เธอกดลงไปนั้นจะให้ค่าตัวเลขออกมาเสมอ และเขา (ใครก็ไม่รู้) ได้กำหนดความหมายของแต่ละตัวเลขเอาไว้หมดแล้ว เธอกับฉันมีหน้าที่ที่จะต้องรู้ว่าตัวเลขไหนให้ความหมายว่าอย่างไรพอ คือพอเท่าที่ต้องการใช้น่ะจ๊ะคนดี

อ่านเพิ่มเติมเกี่ยวกับ JavaScript Key Code
- พร้อมช่องสำหรับกดปุ่มใดๆ แล้วมันจะคืนค่าตัวเลข code ออกมา http://www.scripttheweb.com/js/ref/javascript-key-codes/
- document การใช้งานออบเจ็กต์ event เช่นเดียวกับการเรียกใช้ event listener อ่านตรงนี้แล้วรับรองว่าเข้าใจง่ายขึ้น https://developer.mozilla.org/en-US/docs/Web/API/event.keyCode


>> ตัวอย่างต่อไปนี้จะแสดงให้เธอเห็นว่า เราสามารถขอค่าออบเจ็กต์ Element จากแท็กที่ชื่อ img เพื่อเปลี่ยนเส้นทางของภาพผ่านแอตทริบิวต์ src ของมันได้ ซึ่งภาษา HTML เวลาที่เธอต้องการแสดงรูปภาพจะเขียนได้อย่างง่ายๆดังนี้

<img src="x" />

เมื่อ x หมายถึง URL ใดๆที่อ้างอิงไปยังรูปภาพที่ต้องการนั้น จากโค้ดเราขอออบเจ็กต์ Element ของแท็ก img เก็บไว้ในตัวแปรชื่อ myImage จากนั้นตรวจจับค่าคีย์ที่จะเกิดขึ้น หากกดปุ่ม A (คีย์โค้ดคือ 65) จะเปลี่ยนค่าของ src ไปยัง URL ใหม่ แต่หากกลับไปกดปุ่ม D (คีย์โค้ดคือ 68) จะเปลี่ยนค่าของ src ไปยัง URL เดิม ลองกดปุ่มทั้งสองนี้เล่นสลับไปมาสิ

>> part หน้ามาลุยต่อกันเรื่องของลูป (Loop) เขียนภาษาจาวาสคริปต์อย่างไรให้เกิดการกระทำโค้ดซ้ำๆหลายๆรอบได้กับหัวข้อ Iteration Statements ครับ

ภาษา JavaScript ฉบับผู้เริ่มต้น part 8-2

: Condition Statement กับคำสั่ง switch statement

>> จาก part ที่ 8-1 เรื่องของ if-else-if statement คราวนี้เพื่อนๆจะได้รู้จักกับ switch statement ซึ่งมีลักษณะการทำงานแทบไม่ต่างจาก if-else-if statement เลย โดยมีโครงสร้างดังนี้

switch ( expression ) {
case value1 : break;
case value2 : break;
default :
}

เงื่อนไขหรือ expression ของ switch จะเทียบค่าว่าตรงกับค่า value ใดในแต่ละ case (จะเขียนกี่ case ก็ได้นะ) เปรียบดั่งเขียน else if ( expression ) นั่นแหละจ๊ะ เมื่อค่าของ expression ตรงกับค่าของ value ใดๆในแต่ละ case แล้วไซร้ การกระทำคำสั่งก็จะเริ่ม ณ จุดนั้น (หลังเครื่องหมาย : ) เป็นต้นไปจวบกระทั่งพบคีย์เวิร์ด break ก็จะหลุดออกจาก switch แต่หากไม่เข้า case ใดเลยก็จะไปกระทำคำสั่งใน default แทน ซึ่งเปรียบดั่งเขียน else นั่นเอง

>> ฟังแล้วงงเพราะยังไม่ค่อยชิน พาทำตัวอย่างหน่อยสิ
ตอบ จัดไป

var today = new Date();
var day = today.getDay();
switch(day) {
case 0 : day = "Sunday"; break;
case 1 : day = "Monday"; break;
case 2 : day = "Tuesday"; break;
case 3 : day = "Wednesday"; break;
case 4 : day = "Thursday"; break;
case 5 : day = "Friday"; break;
case 6 : day = "Saturday"; break;
}
alert("This day is " + day);

จากตัวอย่างข้างต้น เราสร้างออบเจ็กต์ Date ขึ้นมาโดยคำสั่ง new Date (งงหรือสงสัยข้ามไปก่อน เอาเป็นว่าให้ใช้แบบนี้เวลาสร้าง Date) ค่าของมันเก็บไว้ในตัวแปรชื่อ today ซึ่งอ้างอิงตามวันและเวลาของเครื่องคอมฯของเพื่อนๆ และเมื่อเราเอา today มาดอท (.) กับ getDay ก็จะได้ตัวเลขออกมา ซึ่งมีค่าอยู่ระหว่าง 0 ถึง 6 เราก็เลยไปตั้ง case ค่าของตัวเลข 0 ถึง 6 เพื่อเปลี่ยนค่าของตัวแปร day เป็นสตริงใดๆที่มีความหมายกับตัวเลขนั้นๆ ตัวอย่างเช่น วันนี้เป็นวันจันทร์ (ณ ขณะนี้) ค่าของ day ก็จะได้เท่ากับ 1 เมื่อนำเลขนี้ไป switch กับ case ใดๆก็เท่ากับ case 1 : ซึ่งทำคำสั่ง day = "Monday" (ตอนนี้เลข 1 ที่เคยเก็บไว้ในตัวแปร day หายไปแล้ว โดยมี "Monday" เก็บเอาไว้แทน) จากนั้นเจอคำสั่ง break โปรแกรมก็จะหลุดออกจาก switch ไปทำคำสั่ง alert ต่อไป

สามารถอ่านเกี่ยวกับ Date เพิ่มเติมได้จาก
http://www.tizag.com/javascriptT/javascriptdate.php

>> ฉันไม่เห็นการใช้ default เลย สรุปว่าใส่หรือไม่ใส่?
ตอบ ตาแหลมมากครับ คำสั่ง default จะใส่หรือไม่ใส่ก็ได้ ขึ้นอยู่กับว่าเราทราบค่าที่แน่นอนของ switch หรือเปล่า ถ้าทราบไม่ต้องใส่ครับ (ไวยากรณ์ไม่บังคับ) แต่ถ้าไม่ทราบสมควรใส่ไว้ จะได้รู้ไงว่าไม่มี case ใดๆสามารถทำตาม switch ได้เลย ดังตัวอย่างผมทราบว่าค่าของ getDay คือ 0 ถึง 6 ไม่มีค่าอื่นนอกจากนี้อีกแล้ว ดังนั้นละ default ได้อย่างสบายใจ แถมให้นิด~ คำสั่ง default ไม่จำเป็นต้องใส่ break ต่อท้ายนะครับ (ไวยากรณ์ไม่บังคับ)

>> ขอตัวอย่างที่ต้องใช้ default หน่อยสิจ๊ะ?
ตอบ จัดไปครับตามรูปภาพเลย โดยคำสั่ง prompt คือการรับข้อมูลผ่านกล่องลอย (ผมเรียกมันอย่างนี้นะ) แล้วเก็บค่าที่รับมาไว้กับตัวแปรชื่อ userInput ซึ่งจะมีไทป์เป็นสตริง เปลี่ยนค่าสตริงเป็นตัวเลขก่อนด้วย parseInt (เปลี่ยนค่าใดๆเป็น Number) จากนั้นนำค่าที่ได้ไปใช้กับ switch เหมือนตัวอย่างก่อนหน้านี้


>> ใน part 9 ต่อจากนี้ ขอนำเพื่อนๆเขียนภาษาจาวาสคริปต์ควบคุมการกดปุ่มที่แป้นพิมพ์ครับ เพื่อที่จะสลับรูปภาพจากรูปหนึ่งสู่อีกรูปหนึ่ง ไว้เจอกันนะค๊าบบบ

อ่านเกี่ยวกับคำสั่ง parseInt เพิ่มเติม
http://www.w3schools.com/jsref/jsref_parseint.asp

ภาษา JavaScript ฉบับผู้เริ่มต้น part 8-1

: Condition Statement กับคำสั่ง if-else-if statement

>> อะไรคือ condition statement เหรอ?
ตอบ ให้คิดง่ายๆอย่างนี้ครับ ทุกวันนี้เรามีถนนสำหรับให้รถวิ่ง ย่อมมีทั้งทางตรง ทางโค้งและทางแยก condition statement ก็คือทางแยกของถนนที่ว่าจะเลี้ยวซ้ายหรือขวาหรือตรงไปในทางโปรแกรมมิ่งนั่นเอง เพื่อนๆหลายคนฟังแล้วอ๋อทันที ใช่ครับ ก็คือเหล่าคำสั่งต่อไปนี้
- if-else-if statement
- switch statement

>> if-else-if statement คืออะไรเหรอ?
ตอบ มันคือเงื่อนไขให้เลือกทางหนึ่งทางใด ซึ่งมีโครงสร้างดังนี้

if ( boolean_expression ) { ... }

เมื่อ boolean_expression คือค่าที่มีผลเป็น จริง (true) หรือ เท็จ (false) เท่านั้น ตัวอย่างเช่น

var x = 10;
if(x == 10) {
alert("Yes, x equals ten");
}

คำตอบที่ได้คือข้อความ Yes, x equals ten ปรากฏขึ้นมาครับ เพราะเรากำหนดค่าของตัวแปร x เท่ากับ 10 แล้วถามการเท่ากันนี้ในเงื่อนไขของคำสั่ง if ว่าตัวแปร x เท่ากับ 10 ใช่ไหม (ด้วยเครื่องหมาย == นะจ๊ะ) คำตอบคือ true แน่นอน

var x = 0;
if(x = 10) {
alert("Yes, set x by ten");
}

คำตอบของกรณีข้างต้นนี้อันตรายมาก (ด้วยเครื่องหมาย = เพียงอันเดียว) เพราะภาษาจาวาสคริปต์ไม่ถือเป็นข้อผิดพลาดในนิพจน์ boolean_expression และถือว่าเป็น true กล่าวคือจะได้คำตอบเป็น Yes, set x by ten ออกมาอย่างแน่แท้ โดยมีกติกาดังนี้จ๊ะ
- กำหนดให้ x มีค่าเท่ากับ 0 จะตีความเป็น เท็จ
- ค่าอื่นใดที่ไม่ใช่ 0 (กระทั่งค่าลบ) จะตีความเป็น จริง
- กำหนดให้ x มีค่าเท่ากับ null จะตีความเป็น เท็จ
- กำหนดให้ x มีค่าเป็นออบเจ็กต์ (new ให้ไง) จะตีความเป็น จริง

บางคนว่าจำยากจัง จำได้บ้างไม่ได้บ้างก็ไม่ต้องกังวลไปนะ ขอให้ฝึกเขียนบ่อยๆใช้บ่อยๆเดี๋ยวก็ได้เอง สรุปว่าควรใช้เครื่องหมาย == (เท่ากับสองอัน) เสมอในเงื่อนไขหรือนิพจน์ที่เป็น boolean_expression

>> จากโค้ดตัวอย่างทั้งสองข้างต้น ขอถามว่าถ้าเกิดผมกำหนดค่าของ x เป็น -1 (ลบหนึ่ง) จะเกิดอะไรขึ้น?
ตอบ กล่องข้อความจากคำสั่ง alert ก็จะไม่ทำงานน่ะสิ ใช่ครับ!เก่งมาก หรือก็คือมันข้ามทุกคำสั่งที่อยู่ระหว่างเครื่องหมาย { และ } ของ if ไปเลยไงล่ะ ทว่าในกรณีที่เราต้องการดักจับหรือกำหนดให้ทางแยกซ้ายและขวาเกิดการกระทำอย่างหนึ่งอย่างใด (จริงก็ทำ เท็จก็ทำ) เราก็จะเขียนคำสั่ง else เพิ่มเข้าไปครับ ดังตัวอย่างนี้

var x = 5;
if(x == 10) {
alert("x equals ten");
} else {
alert("x not equals ten");
}

กำหนดให้ x มีค่าเท่ากับ 5 ดังนั้นคำตอบคือ x not equals ten ครับผม ทีนี้เอาใหม่ สร้างทางเลือกให้มากกว่าสองทางด้วยคำสั่ง else if เพิ่มเข้าไปอีก (เอาสี่ทางเลือกเลย) ดังตัวอย่างต่อไปนี้จ้า

var x = 5;
if(x >= 100) {
alert("x more than or equals one hundred");
} else if(x > 10) {
alert("x more than ten");
} else if(x < 5) {
alert("x less than five");
} else {
alert("x more than or equals five");
}

ลองทายกันสิครับว่า ข้อความใดจะปรากฏออกมา? อิอิ

>> เนื่องจากเนื้อหาเยอะเกินไป ผมขอตัด part นี้เป็น 8-1 และ 8-2 นะครับ ก่อนจะนำมันมาสร้างเป็นตัวอย่างสนุกๆให้ศึกษากันใน part 9 (ปูรากฐานสู่เกมเล็กๆขำๆ) ครั้งนี้ลาแล้ว สวัสดีครับ

ภาษา JavaScript ฉบับผู้เริ่มต้น part 7

: Expressions กับการสร้างโปรแกรมเครื่องคิดเลขง่ายๆ

>> expression คืออะไรเหรอ?
ตอบ ถ้าจะให้เข้าใจคำนี้เพื่อนๆจะต้องรู้จักคำว่า statement เสียก่อน เจ้า statement ก็คือโค้ดต่างๆที่เพื่อนๆเขียนขึ้น โดยมากมักจะจบในหนึ่งบรรทัดหรือจวบกระทั่งปิดด้วยเครื่องหมาย ; (semicolon) ตัวอย่างเช่นการประกาศตัวแปร

var x = 10;

เราเรียกบรรทัดคำสั่งลักษณะนี้ว่า statement โดยเมื่อ statement ใดๆก็ตามเกิดการทำงานแล้วได้มาซึ่งผลลัพธ์หรือค่า เราก็จะเรียกมันว่า expression ตัวอย่างเช่น

var y = x + 20;

ทั้งหมดนี้ก็คือหนึ่ง statement โดยมี x + 20 เป็น expression นั่นเองครับ

>> แสดงว่า expression ก็คือการคำนวณ เช่นการบวกอย่างนั้นหรือ?
ตอบ นั่นเป็นความเข้าใจที่ถูกต้องครับ แต่ถ้าจะให้ดีกว่านี้ เราต้องทราบว่า expression ใดๆจะเกิดขึ้นได้ต้องผ่านการกระทำจากเหล่า Operator

>> แล้วเหล่า operator คืออะไร?
ตอบ ก็คือสัญลักษณ์ที่ใช้ในการคำนวณค่า ไม่ว่าจะเป็นทางคณิตศาสตร์หรือตรรกศาสตร์ โดยพื้นฐานประกอบด้วย
- Arithmetic Operators ได้แก่ +, -, *, / , %, ++, --
- Relational Operators ได้แก่ <, >, <=, >=, ==, !=
- Logical Operators ได้แก่ &&, ||

สัญลักษณ์ตัวไหนที่ไม่รู้จักในขณะนี้ก็ไม่ต้องไปสนใจครับ เลือกใช้และศึกษาเฉพาะตัวที่ใช่ไปก่อนได้ ในที่นี้ผมเลือกบวกกับลบ (+, -)

>> มาสร้างโปรแกรมเครื่องคิดเลขง่ายๆกันเถอะ!
: หัวใจสำคัญคือ วาดกล่องสามใบ กล่องใบแรกกับใบที่สองสามารถดึงค่าออกมาเพื่อนำไปกระทำการบวกหรือลบ โดยผลลัพธ์ที่ได้ให้แสดงยังกล่องใบที่สาม


1) ใช้แท็กของภาษา html สร้างเป็นกล่องรับค่าดังรูปครับ โดยแท็กชื่อ input กำหนดไทป์ของมันเป็น text แล้วตั้งชื่อ (id) ว่า x, y และ z ตามลำดับ
2) ใช้แท็ก button สร้างเป็นปุ่มสำหรับการบวกและลบ เพิ่มเหตุการณ์คลิกให้กับปุ่ม เพื่อให้ปุ่มสามารถไปเรียกฟังก์ชันในแท็ก script
3) ในแท็ก script คำสั่งของภาษาจาวาสคริปต์ที่ว่า document.getElementById จะให้ผลลัพธ์เป็นออบเจ็กต์ Element ของชื่อนั้นๆ (หรือก็คือของ id นั้นๆ) ออกมา ในที่นี้ผมตั้งชื่อว่า elementX, elementY และ elementZ ตามลำดับ
4) เปลี่ยนค่าไทป์สตริง (String type) เป็น float (คำนวณทศนิยมได้จ้า) ด้วยฟังก์ชันชื่อ parseFloat ทีนี้ก็จะได้ค่าของ x และ y ที่มีไทป์เป็น Number แล้ว
5) ให้ x และ y บวกกันถ้ากดปุ่มบวก หรือให้ x และ y ลบกันถ้ากดปุ่มลบ
6) นำผลลัพธ์ที่ได้ไปใส่ในกล่อง z เป็นอันเรียบร้อย

>> ใน part ต่อไปเราจะคุยกันเรื่อง Condition Statement มันจะทำให้โปรแกรมของเรามีทางเลือกเพิ่มมากขึ้น ถ้าเปรียบเทียบเป็นการขับมอไซด์ ที่ผ่านมาเราเริ่มประกอบมอไซด์แล้วซิ่งตรงอย่างเดียว คราวนี้แหละ! เราจะสามารถควบคุมมันได้ จะให้มันเลี้ยวซ้ายตกคลองหรือขวาติดไฟแดงอย่างไรก็ได้ หึหึหึ น้องสก๊อยจับแน่นๆนะ

>> อ่านเพิ่มเติมเกี่ยวกับคำสั่ง document.getElementById และฟังก์ชัน parseFloat
- http://www.javascript-coder.com/javascript-form/getelementbyid-form.phtml
- http://www.w3schools.com/jsref/jsref_parsefloat.asp

ภาษา JavaScript ฉบับผู้เริ่มต้น part 6-2


: ภาพอันเปลือยเปล่าของน้อง Primitive Type และ Reference Type

>> ภาพดังที่เห็นนี้อาจไม่ถูกต้องตามโครงสร้างของหน่วยความจำไปเสียทุกอย่าง แต่เพื่อให้เพื่อนๆได้เห็นว่าหน่วยความจำที่บราวเซอร์ใช้นั้น ใช้จัดเก็บตัวแปรที่มีไทป์ประเภท primitive type ต่างจากประเภท reference type อย่างไร

>> ด้านซ้ายคือพื้นที่ที่เกิดการจองหน่วยความจำของตัวแปรที่มีไทป์ประเภท primitive type เมื่อเราประกาศตัวแปร bookPrice กับ bookName จากภาพเราสามารถอ้างอิงทั้งสองชื่อนี้เพื่อเข้าถึงค่า 25 และ "JS" ตามลำดับ

>> ด้านขวาคือพื้นที่ที่เกิดการจองหน่วยความจำของตัวแปรที่มีไทป์ประเภท reference type เมื่อเราสร้างออบเจ็กต์ (คำสั่ง new ใช้สร้างออบเจ็กต์ ออบเจ็กต์เป็นอย่างไรนั้น ไว้ค่อยคุยกันใน part ต่อๆไปเน๊อะ) จะเกิดค่าค่าหนึ่งขึ้นมา (ระบบจะจัดสรรให้เองโดยอัตโนมัติ) สมมติว่าเป็นค่า @ab1764ac ค่าดังกล่าวนี้จะอ้างอิงถึงหน่วยความจำอีกแห่งหนึ่ง เสมือนว่าเราได้หนังสือมาหนึ่งเล่มจริงๆ หนังสือที่ว่านี้อาจมีความสัมพันธ์กับตัวแปร bookPrice และ bookName ซึ่งเป็นราคาและชื่อหนังสือของมันเองเลย (คนละตัวแปรกับฝั่ง primitive type นะจ๊ะ) ครั้นเราสร้างออบเจ็กต์โดยการ new อีก ก็จะได้หนังสือเล่มใหม่ออกมาอีก (งง ก็ไม่ต้องสนใจ เดี๋ยว part ต่อๆไปจะพาทำเองครับ) โดยแต่ละเล่มที่ได้ใหม่นั้นก็จะมีราคาและชื่อหนังสือเป็นของมันเอง ของใครของมัน

>> เพื่อนๆคงทราบว่าเราเขียนโปรแกรมล้อเลียนความจริง ดังนั้นจะพบเจอโค้ดโปรแกรมลักษณะไทป์ประเภท reference type อยู่บ่อยๆ ซึ่งพื้นฐานของมัน (ที่สุดของที่สุด) ก็คือการห่อหุ้มไทป์ประเภท primitive type นี่แหละครับ

>> หากต้องการเข้าใจให้ละเอียดกว่านี้ อยากรู้ๆ ผมแนะนำลิงค์นี้
http://www.youtube.com/watch?v=mh-hPzDfb_Q

>> สำหรับ part หน้า เราจะคุยกันเรื่อง Expressions จับตัวแปรและค่ามาบวกลบคูณหารกัน ทำโปรแกรมคำนวณค่าเล็กๆสนุกๆกัน ไว้เจอกันนะ

ภาษา JavaScript ฉบับผู้เริ่มต้น part 6-1

: ชนิดของไทป์ (type)

>> ชนิดของตัวแปร หรือ ชนิดของไทป์ หรือไทป์ หรือ type ได้ยินคำไหนใน part นี้ก็ความหมายเดียวกันหมดนะ เอาล่ะ จาวาสคริปต์แบ่งชนิดของไทป์ออกเป็นสองกลุ่ม ได้แก่
- Primitive Type
- Reference Type

>> Primitive Type คืออะไร?
ตอบ กลุ่มไทป์ที่เก็บค่าไว้ในพื้นที่ที่จองไว้ในหน่วยความจำโดยตรง (ในรูปของเลขฐานสอง) ประกอบด้วย Number, String และ Boolean

>> Reference Type คืออะไร?
ตอบ กลุ่มไทป์ที่เก็บค่าอ้างอิงไปยังพื้นที่อื่นซึ่งจะเรียกว่ากลุ่มของออบเจ็กต์ก็ได้ ประกอบด้วย Object, Array และ Function ครับ

>> เราทราบว่าจาวาสคริปต์เป็นภาษาประเภท Dynamic Typing กล่าวคือตัวแปรสามารถเปลี่ยนไทป์ไปมาได้ตามค่าที่ถูกกำหนดให้ใหม่ เราสามารถตรวจสอบว่าตัวแปรที่ประกาศขึ้นมานั้นมีไทป์เป็นชนิดอะไรด้วยคำสั่ง typeof ซึ่งดูได้จากตัวอย่างต่อไปนี้
1) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
2) http://www.w3resource.com/javascript/operators/typeof.php

เมื่อศึกษาแล้วจึงพบว่า
- ตัวแปรที่กำหนดค่าให้เป็นดังเช่น 37 หรือ 3.14 มีไทป์เป็น number
- หากกำหนดเป็น "" หรือ "love you" จะมีไทป์เป็น string
- หากกำหนดเป็น true หรือ false จะมีไทป์เป็น boolean
- หากกำหนดเป็น new Date() หรือ JSON จะมีไทป์เป็น object
- หากกำหนดเป็น function(){} หรือ Math.sin จะมีไทป์เป็น function
- ส่วนไทป์ที่เป็น Array ขออธิบายอย่างละเอียดในโอกาสต่อๆไป

>> รู้จักชนิดของไทป์แล้วมีประโยชน์อย่างไร?
ตอบ การที่เราทราบชนิดของไทป์ เราย่อมทราบพฤติกรรมของมัน พฤติกรรมที่ว่านี้ก็คือการเข้าถึงค่า (ที่ถูกกำหนดให้) ของตัวแปร อีกทั้งยังเป็นการบริหารหน่วยความจำของบราวเซอร์ให้มีประสิทธิภาพอีกด้วย (พวกนี้เทพเกินไป) ตัวอย่างเช่น เขียนเกมหมากฮอส ถ้าหมากของเราสามารถเดินไปจนถึงตารางแถวสุดท้ายของอีกฝ่ายได้ หมากตัวนั้นจะเลเวลอัพเพิ่มความสามารถในการเดิน (แนวทแยงมุม) ได้สุดกู่ ลักษณะอย่างนี้เมื่อเรากำหนดชนิดของตัวแปรด้วยไทป์ที่เป็น Number ก็จะสิ้นเปลืองหน่วยความจำอย่างมากหากนำมาเทียบกับไทป์ที่มีชนิดเป็น Boolean ทว่าในขั้นเริ่มต้นเรียนรู้ร่วมกันนี้ก็ไม่จำเป็นต้องทราบละเอียดขนาดนั้น ปล่อยวางไปบ้างก็หาเป็นไรไม่

>> ขอให้ติดตามต่อใน part 6-2 ผมจะแสดงให้เห็นถึงความแตกต่างของ Primitive Type กับ Reference Type สำหรับ part นี้ไว้เท่านี้ก่อน ยาวไปเดี๋ยวหลับ สวัสดีจ้า

ภาษา JavaScript ฉบับผู้เริ่มต้น part 5

: variable declaration and type

>> ถามว่าอะไรคือตัวแปรเหรอจ๊ะ?
ตอบ ง่ายๆเลยที่ที่สำหรับเก็บของ เช่น กล่องใส่ดินสอ กล่องก็เป็นตัวแปร ส่วนดินสอก็เป็นของ หรือกระเป๋าใส่เงิน กระเป๋าก็เป็นตัวแปร ส่วนเงินก็เป็นสิ่งที่ถูกเก็บไว้ภายใน อาจฟังดูบ้าไปนิด อันที่จริงในทางคอมพิวเตอร์ ตัวแปรก็คือสิ่งที่ใช้อ้างอิงค่าหรือพื้นที่ที่ถูกกำหนดขึ้นในหน่วยความจำ และค่านั้นเรียกว่า value

>> เหมือนตัวแปร x = 10 ที่เคยเห็นใช่ไหม?
ตอบ ใช่เลยครับ เราเรียก x ว่าตัวแปรชื่อเอ็กซ์ แล้วระบุค่าสิบให้กับมัน ต่อไปนี้หากว่าเจอเอ็กซ์ก็เข้าใจว่าเจอค่าสิบนั่นเอง

>> ประกาศตัวแปรเพื่อใช้ทำอะไร?
ตอบ variable declaration หรือการประกาศตัวแปรนั้นมีไว้เพื่อระบุชื่อใดๆที่จะใช้แทนค่าใดๆที่ต้องการ เพื่อสำหรับอ้างอิงในการคำนวณก็ได้ ทั้งที่เป็นค่าคงที่หรือไม่คงที่ก็ได้ (เปลี่ยนแปลงตามอัลกอริทึม) ไม่เข้าใจก็ไม่ต้องคิดมาก เอาเป็นว่าถ้าเราจะหาพื้นที่ของรูปสี่เหลี่ยม เราจะใช้สมการที่ว่า กว้าง x ยาว ใช่ไหม ในภาษาจาวาสคริปต์ก็แค่เขียนๆไปว่า

var rectangleArea = width * height ;

โดยที่ width แทนค่าความกว้าง ส่วน height แทนค่าความยาว เมื่อคูณกันแล้ว (คอมพิวเตอร์ใช้เครื่องหมาย * แทน x) ก็จะได้พื้นที่ของรูปสี่เหลี่ยม (ผืนผ้า) ออกมา โดยค่าที่ได้ก็เก็บไว้อีกตัวแปรหนึ่งที่ให้ชื่อว่า rectangleArea

>> จากตัวอย่างข้างต้น width กับ height ก็คือตัวแปรใช่ไหม?
ตอบ เก่งมาก ใช่แล้วล่ะครับ โดยเราต้องระบุค่าให้ width กับ height ด้วยนะ เขียนประมาณนี้

var width = 10 ;
var height = 20 ;
var rectangleArea = width * height ;

ผลลัพธ์ที่ได้ก็คือ 200 นั่นเอง ซึ่งเวลาเอาไปแสดงผลก็เอาไปใส่ไว้ในฟังก์ชัน alert โค้ดทั้งหมดนั้นแสดงดังด้านล่าง

<html>
<head>
</head>
<body>
<script>
var width = 10 ;
var height = 20 ;
var rectangleArea = width * height ;
alert(rectangleArea) ;
</script>
</body>
</html>

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

>> แล้วอะไรคือไทป์?
ตอบ ไทป์ (type) ก็คือชนิดของตัวแปร เช่น กล่องใส่ดินสอ ก็มีชนิดเป็นกระดาษ เป็นพลาสติกหรือไม้ เป็นต้น ตัวแปรเองก็ต้องมีชนิดเหมือนกัน และเป็นที่โชคดีที่ตัวแปรใดๆในภาษาจาวาสคริปต์ ชนิดของตัวแปรนั้นสามารถเปลี่ยนแปลงไปตามค่าที่ถูกกำหนดให้กับตัวแปรนั้นๆครับ ในขั้นต้นนี้ขอให้รู้จักเพียงเท่านี้ก่อน มากไปเดี๋ยวจะไม่สนุก อิอิ

>> เจอกัน part หน้าจะนำเสนอชนิดของตัวแปร (type) อย่างละเอียด เสมือนแก้ผ้ามันออกให้หมด โจ๊ะๆกันเลย หึหึหึ

ภาษา JavaScript ฉบับผู้เริ่มต้น part 4

: รูปแบบของแท็ก script

>> มันเป็นเรื่องวิวัฒนาการของรูปแบบครับ ปัจจุบันโปรแกรมเล่นเว็บ (ต่อไปจะเรียกว่า บราวเซอร์) นั้นเก่งมากๆ สามารถรองรับรูปแบบของแท็ก script ได้ทั้งสามรูปแบบดังต่อไปนี้

แบบแรก
<script language="javascript"></script>

แบบที่สอง
<script type='text/javascript'></script>

และแบบที่สาม
<script></script>

โดยมีเหตุผลสั้นๆคือ
- แบบแรก นั้นโบราณมาก ประมาณภาษา HTML เวอร์ชัน 3.2 ขึ้นไป
- แบบที่สองมีอยู่ให้เห็นอย่างหลากหลาย ประมาณภาษา HTML เวอร์ชัน 4.X ขึ้นไป (ตัว X นี้แทนหมายเลขเวอร์ชันย่อยๆ เช่น 4.01) หรือภาษา XHTML เวอร์ชัน 1.X ขึ้นไป
- แบบสุดท้ายคือล่าสุดตอนนี้ ประมาณภาษา HTML เวอร์ชัน 5 โดยหากกำหนดตามนี้จะมีค่าเหมือนกับแบบที่สองครับ (เราเรียกว่าค่าโดย default)

>> สรุปฉันควรเลือกเขียนแบบไหน?
ขอตอบแบบกวนประสาทนิดๆก่อนนะครับ ทุกวันนี้เราตามโลกหรือโลกตามเรา? แน่นอนเราต้องตามสิ่งที่ใหญ่กว่า คือเราตามโลก ดังนั้นหากโลกมีเทคโนโลยีใหม่ๆมาให้ใช้ เราก็ควรใช้ครับ กล่าวคือใช้แบบที่สามไปเลย

ถามใหม่ ทุกวันนี้เราตามเงินหรือเงินตามเรา? แน่นอนเราต้องตามหาเงินครับ ศึกษามันก็เพื่องาน งานทำให้เกิดเงิน ดังนั้นหากกลุ่มลูกค้าที่จะใช้เว็บของเรามีบราวเซอร์ที่เก่าและแก่มากๆ (ไม่ยอม update เสียที) เราก็คงเลือกแบบที่สองให้อุ่นใจไว้ก่อน ส่วนแบบที่หนึ่งมันไม่เป็นมาตราฐาน ดังนั้นไม่เลือก

สรุป เป็นผม ผมเลือกแบบที่สาม

>> part หน้าจะเสนออะไร?
ตอบ เราจะลงลึกซุกดิ๊กไปในเรื่องการประกาศตัวแปรและไทป์ของมัน คอยติดตามนะฮาบ

หมายเหตุ นี่คือเว็บจาวาสคริปต์ที่ผมอยากลองให้เข้าไปเล่น อิอิ
http://www.codetukyang.com/java/

ภาษา JavaScript ฉบับผู้เริ่มต้น part 3

: จะวางโค้ด JavaScript ที่ไหนดี?

>> มาถึง part นี้เพื่อนๆหลายคนคงได้เริ่มต้นศึกษา HTML กันบ้างแล้ว และทราบว่าภาษา HTML ที่ใช้สร้างเอกสารหรือหน้าเว็บนั้น ประกอบไปด้วยแท็กสำคัญ 3 แท็ก ได้แก่
1) <html>
2) <head>
3) <body>

โดยแท็กทั้งสามจะประกอบกันเป็นโครงสร้างพื้นฐานดังนี้
<html>
<head></head>
<body></body>
</html>

กล่าวคือมีแท็ก html ไว้ครอบแท็ก head และ body ซึ่งหน้าที่ของแท็ก head คือการระบุทรัพยากรที่มองไม่เห็น ต่างจากแท็ก body ที่ใช้สื่อถึงสิ่งที่มองเห็นเป็นสำคัญ

>> จาก part ที่ผ่านมา เพื่อนๆทราบว่าภาษา JavaScript จะเขียนไว้ภายในแท็ก <script> และ </script> ตัวอย่างเช่นคำสั่ง alert คำถามมีอยู่ว่า เราจะเขียนเจ้าแท็ก script นี้ไว้ได้ที่ไหนบ้างที่เหมาะสมที่สุดภายในโครงสร้างของเอกสาร HTML?

>> ผมมีให้เลือกอยู่สองตำแหน่งสำคัญ ได้แก่ (1) ไว้ระหว่างแท็ก head หรือ (2) ไว้ก่อนปิดแท็ก body ดังด้านล่าง
<html>
<head>(1)</head>
<body>(2)</body>
</html>

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

>> ขอฟังเหตุผลโบราณที่กล่าวมาหน่อยสิ?
ได้เลยครับ พูดกันถึงข้อเสียแล้วกัน เริ่มจากข้อเสียหากวางไว้ ณ ตำแหน่งที่ (1) ก่อน

- หากใส่ JavaScript ไว้ที่แท็ก head จะต้องรอให้ JavaScript ตัวก่อนหน้าโหลดเสร็จก่อน จึงจะโหลด JavaScript ตัวต่อไปได้ ทำให้เกิดความล่าช้า
- Web Crawler บางตัว (ตอนนี้ไม่ต้องสนใจนะ) อาจไม่อ่านหน้าเว็บทุกตัวอักษร แต่จะกำหนดจำนวนตัวอักษรที่ต้องการอ่านเอาไว้ ดังนั้น การใส่ JavaScript ไว้ที่ head มากๆ อาจทำให้ Web Crawler นั้นๆไม่ให้ความสำคัญกับเนื้อหาอื่นๆ

ทีนี้มาฟังข้อเสียหากวางไว้ ณ ตำแหน่งที่ (2) บ้าง
- สิ่งที่ไม่แสดงผลออกมา ไม่ควรอยู่ในแท็ก body ดังนั้น JavaScript ควรอยู่ในแท็ก head
- หากใส่ JavaScript ไว้ก่อนปิดแท็ก body จะทำให้การพัฒนามีความยากลำบากในบางกรณี เช่น คำสั่ง document.ready ของ jQuery (ตอนนี้ไม่ต้องสนใจกรณีนี้)
- หาก JavaScript โหลดทีหลังสิ่งอื่นๆในหน้าเว็บ อาจทำให้พฤติกรรมของผู้ใช้เว็บเปลี่ยนไป

>> สรุปจะวางโค้ด JavaScript ไว้ ณ ตำแหน่งไหน ขออีกที?
ตอบ หากเพื่อนๆไม่มั่นใจว่าโปรแกรมเล่นเว็บที่ผู้ใช้ใช้อยู่นั้น เป็นเวอร์ชันใหม่หรือเก่า และคันใจเหลือเกินกับเหตุผลข้างต้น (หรือไม่รู้สึกอะไรเลย) ก็ให้คิดอย่างนี้ครับ ให้ส่วนที่เป็นการเรียกภาษา JavaScript จากที่อื่น (แหล่งอื่นๆที่ไม่ใช่เว็บของเรา) ไว้ ณ ส่วน head และให้ส่วนที่ไม่เกี่ยวข้องกับโครงสร้าง (layout) ของหน้าเว็บรวมถึงคำสั่งที่เกี่ยวกับการโหลดสิ่งต่างๆในแท็ก body ให้วางภาษา JavaScript ไว้ ณ ก่อนปิดแท็ก body ก็หมดเรื่องแล้ว ซึ่งจะขอกล่าวถึงรายละเอียดแบบตับตับในโอกาสต่อไป

ขอบคุณแหล่งข้อมูล
- http://www.w3schools.com/js/js_examples.asp สำหรับมาตราฐานที่ดี
- http://stackoverflow.com/questions/1213281/does-javascript-have-to-be-in-the-head-tags สำหรับการถกเถียงที่มีข้อสรุป
- http://www.siamhtml.com/ (javascript-head-body-ควรใส่ไว้ที่ไหน) สำหรับข้อมูลภาษาไทย

>> ใน part ต่อไปเราจะมาทำความเข้าใจกันว่า รูปแบบของแท็ก script มีกี่รูปแบบ ควรใช้แบบไหนอย่างไรครับ

เริ่มต้นเรียนรู้ Oracle Database part 4-2

: Oracle Listener (ตอนจบ)

>> ต่อจาก part 4-1 นะครับ ทิ้งท้ายไว้ที่ผมต้องการติดต่อฐานข้อมูล Oracle ด้วยโปรแกรม SQL Developer ผ่านช่องทาง TCP/IP

>> จากลิงค์นี้ http://www.toadworld.com/platforms/oracle/b/weblog/archive/2013/08/14/the-oracle-listener-process-how-does-it-work-connecting-to-oracle.aspx

>> คุณ Dan Hotka ได้กล่าวว่า (เท่าที่ผมเข้าใจนะครับ เพราะภาษาอังกฤษผมก็ไม่ค่อยดีนัก) Oracle ใช้วิธีการติดต่อฐานข้อมูลผ่านทาง port ประเภท TCP/IP ด้วยสิ่งที่เรียกว่า 'host string' หรือในทางเทคนิคเรียกว่า 'TNS Names Entry'

>> เขายังเล่าว่าโดยปกติแล้วฝั่ง server (หมายถึงเครื่องที่ติดตั้งฐานข้อมูลไว้) จะมี process ที่ชื่อ 'listener' ทำหน้าที่คอยฟังคอยรับรู้ความเคลื่อนไหวของฐานข้อมูล (ต้องเข้าใจว่าฐานข้อมูลของ Oracle นี้สำคัญมาก เราติดต่อโดยตรงไม่ได้ จะต้องผ่านผู้ช่วยหรือตัวแทนในลักษณะต่างๆตามที่ Oracle กำหนดหรือยอมรับเท่านั้นนะครับ) เพราะเจ้า listener นี้จะเริ่มต้นทำงานเมื่อฐานข้อมูลเริ่มต้นทำงาน ดังนั้นที่เครื่อง server เราสามารถควบคุมมันได้ จะสั่งให้มันเริ่มทำงาน หรือหยุดทำงาน หรือสอบถามสถานะการทำงานของมันอย่างไรก็ได้ ฆ่าได้ ทารุณกรรมมันได้ตามใจอยาก หึหึหึ

>> แน่นอนว่าผมลงฐานข้อมูลไว้ในเครื่องนี้ เครื่องของผมจึงกลายเป็น server โดยปริยาย คุณ Dan Hotka บอกว่ารายละเอียดของเจ้า listener ถูกเขียนเก็บไว้ในไฟล์ที่ชื่อ 'listener.ora' ด้วยเครื่องของผมเป็น server จึงสามารถตามไปดูได้ ณ
C:\app\ProS\product\11.2.0\dbhome_2\NETWORK\ADMIN
.
.
.
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = ORCL11G)
(ORACLE_HOME = C:\app\ProS\product\11.2.0\dbhome_2)
(PROGRAM = extproc)
(ENVS = "EXTPROC_DLLS=ONLY:C:\app\ProS\product\11.2.0\dbhome_2\bin\oraclr11.dll")
)
)
.
.
.
สองสิ่งสำคัญที่ต้องรู้จักคือ
- SID_NAME ในที่นี้ยังคงเป็น Global Database Name ง่ายๆว่าชื่อฐานข้อมูลซึ่งผมตั้งเป็น ORCL11G (ตอนที่ติดตั้งไง ที่เคยเล่าให้ฟังไง ถ้าไม่ตรงขออภัยด้วยนะครับ เพราะนี่ติดตั้งฐานข้อมูลลูกที่สองแล้ว) จำได้ว่าเขียนด้วยพิมพ์เล็กทั้งหมดนะ สงสัยมันไม่สนใจพิมพ์เล็กพิมพ์ใหญ่
- ORACLE_HOME ก็คือ path หรือเส้นทางที่วางเจ้าฐานข้อมูลไว้

>> รายละเอียดดังข้างต้นเป็นตัวบอกว่าฐานข้อมูลชื่ออะไรและอยู่ที่ไหนในเครื่อง server และส่วนต่อไปนี้คือรายละเอียดการติดต่อเข้ามายังฐานข้อมูลลูกนี้ครับ
.
.
.
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1522))
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1522))
)
)

ADR_BASE_LISTENER = C:\app\ProS
.
.
.
สองสิ่งสำคัญที่ต้องรู้จักคือ
- HOST หมายถึงชื่อโดเมน หรือไอพีแอดเดรสที่ทำงานผ่าน TCP/IP นั่นเอง ในที่นี้คือ localhost (หลายคนคงเข้าใจดี เพราะถ้าฐานข้อมูลเราไปอยู่ที่ Google ก็ต้องใส่ว่า google.com หรือ google.th หรือก็แล้วแต่ว่าติดตั้งฐานข้อมูลไว้ที่ชื่อโดเมนไหน)
- PORT หมายถึงช่องทางหรือหมายเลขช่องทางที่จะใช้ติดต่อมายังฐานข้อมูลข้างต้น ในที่นี้ค่าคือ 1522 (เพราะผมติดตั้งครั้งที่สอง Oracle จึงรันเลข port ให้อัติโนมัติ ลูกแรกคือ 1521 ดังนั้นลูกนี้จึงเป็น 1522 ครับ)

>> เอาละครับทั้งหมดข้างต้นคือรายละเอียดของเจ้า listener ที่มันจะต้องทราบขณะที่ฐานข้อมูลเริ่มต้นทำงาน ตัวมันเองทำงานอยู่ฝั่ง server ผู้ที่ทำหน้าที่ปรับเปลี่ยนรายละเอียดการใช้ port ตลอดจนชื่อโดเมน แหล่งที่วางฐานข้อมูลและชื่อฐานข้อมูลก็คงจะเป็น administrator ทางฝั่ง server แหละ (ดีที่เครื่องเรากลายเป็น server อิอิ)

>> แล้วเราในฐานะผู้ต้องการใช้งานฐานข้อมูลล่ะ จะคุยกับเจ้า listener เพื่อเชื่อมต่อไปยังฐานข้อมูลได้อย่างไร?
ตอบ ประเด็นนี้คุณ Dan Hotka มีคำตอบให้แต่แรกแล้วไงครับ เขากล่าวว่าที่ฝั่ง client หรือก็คือเราผู้ที่ต้องการคุยกับ listener จะมีไฟล์ที่ชื่อว่า 'TNSNAMES.ora' ซึ่ง Oracle จัดเตรียมไว้ให้ไว้สำหรับผู้ใช้หรือ client อย่างเราๆติดต่อกับฐานข้อมูลได้ง่ายขึ้น (ผ่าน listener นะอย่าลืม) ในไฟล์จะบรรจุสิ่งที่จำเป็นในการเชื่อมต่อเอาไว้ (This file gives a simple name to the information needed to connect to the database) ประมาณนี้ครับ (ตัดมาเพียงชื่อเดียว)
.
.
.
ORCL11G =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1522))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl11g)
)
)
.
.
.
ดูจากรายการแล้วเพื่อนๆคงเดาได้ไม่ยากเลย ทั้ง HOST ทั้ง PORT ทั้งชื่อ SERVICE_NAME (ที่จริงหนึ่งฐานข้อมูลตั้งแต่เวอร์ชัน 8i เขาเปลี่ยนจากการใช้ชื่อฐานข้อมูลตรงๆเป็น service name แทน เพื่อที่ฐานข้อมูลเดียวจะได้แบ่งการทำงานออกเป็นหลายๆ service เช่น ฐานข้อมูลชื่อ A มีสอง service ได้แก่ HR_SERVICE กับ ACCOUNT_SERVICE เป็นต้น) หากใส่ค่าให้ตรงกับที่เจ้า listener ฝั่ง server คอยฟังอยู่ล่ะก็ ก็ติดต่อไปยังฐานข้อมูลลูกนั้นๆได้เลย

>> สุดท้ายคุณ Dan Hotka เขาบอกว่าสำหรับ client ที่ต้องการคุยกับ listener ผ่านสิ่งที่เรียกว่า host string หรือ TNS Names Entry หรือก็คือใช้ไฟล์ TNSNAMES.ora จะต้องไปกำหนด variable specified ที่ windows environment variable ก่อนนะจึงจะเรียกใช้ไฟล์ดังกล่าวได้ ภาษาเราๆก็คือ set path น่ะ คงรู้ๆกันชิมิ โดยตั้งชื่อตัวแปรว่า TNS_ADMIN และให้ค่ามันไปตามเส้นทางที่เครื่องของเราได้เก็บไฟล์ TNSNAMES.ora ไว้ (Oracle จัดเตรียมไว้ให้อยู่ที่เดียวกับ listener.ora จ้า) ก็เป็นอันจบข่าว

>> แบ่งปันกันนะครับ ใครรู้อะไรก็แชร์ๆกัน ผมไม่ได้อวดรู้ แต่ผมคิดว่าการแชร์สิ่งที่รู้ซึ่งอาจจะผิดหรือถูกเป็นสิ่งที่ดี ผมแก้ปัญหาที่บริษัทได้หลายต่อหลายครั้งก็เพราะ Google ต้องขอบคุณเพื่อนๆใจกว้างในโลกออนไลน์ที่กล้าแชร์สิ่งที่คิดสิ่งที่น่าเป็นไปได้แก่ผมและคนอื่นๆ ถ้าไม่มีพวกเขาผมก็คงไม่มีทางได้รู้ ถ้าไม่มีคุณ Dan Hotka โพสต์นี้ก็ยังไม่เกิดขึ้น เสียสละเวลาสักนิดทำสิ่งเหล่านี้เป็นความรู้สึกที่ผมไม่เคยเสียใจเลย คืนนี้ฝันดีครับผม zZ


JavaScript Picture

JavaScript Picture

เริ่มต้นเรียนรู้ Oracle Database part 4-1

: Oracle Listener

>> เว้นไปหนึ่งหรือสองสัปดาห์จำไม่ได้ จึงกลับมาเริ่มต้นเจ้า Oracle ใหม่ เวอร์ชันเดิมนี่แหละจ้า 11g ด้วยความไม่รู้จึงงมไปเยอะ เสียเวลาไปก็มาก อย่างวันนี้ก็ตั้งแต่สิบเอ็ดโมงเช้า (เช้าเพราะกำลังตื่น) เอาล่ะ ปัญหาเดิม

>> ติดตั้งฐานข้อมูลก้อนแรกไปแล้วประสบปัญหาไม่สามารถเริ่ม OracleDBConsole ได้ ซึ่งโดยปกติแล้วชื่อของเจ้าเนี่ยจะต่อท้ายด้วยชื่อของฐานข้อมูลที่เราตั้งชื่อไว้ชิมิ ตอนนั้นตั้งไว้ว่า orcl ดังนั้นมันจึงมีชื่อเต็มๆว่า OracleDBConsoleorcl

>> ไม่ว่าจะโหลดเกม Child of Light มาเล่นก็แล้ว หรือโหลด The Sims3 พ่วงอีกยี่สิบภาคเสริมเล่นยันเช้าของวันนี้ ก็ยังไม่สามารถจัดการเจ้า OracleDBConsoleorcl นี่ได้เสียที เซ็งมั๊กๆ (เกี่ยวกันยังไง?)

>> error มันฟ้องว่าไม่สามารถเริ่มการทำงานได้ เราก็เข้าใจผิดคิดว่ามันเกี่ยวข้องกับการ config เจ้า SQL Developer ให้ใช้ฐานข้อมูล อันที่จริงไม่ใช่เลยนะครับ

>> ร้อนต้องให้พี่ชายใหญ่ (พี่นรินทร) ช่วยเหลือ มานั่งชั่งเหตุชั่งผลกันว่ามันเป็นเพราะอะไรกันแน่ที่ไม่สามารถ config เจ้า SQL Developer หรือจะเป็นเพราะ OracleDBConsoleorcl มันมีปัญหาเข้ากันไม่ได้กับเครื่องของเราจริงๆ?

>> พี่ครับ ขั้นตอนการติดตั้งผ่านเกือบทั้งหมด พบแค่ปัญหาเดียวคือ service ที่ชื่อ OracleDBConsoleorcl มันไม่ยอมทำงาน เฆี่ยนมันก็แล้ว ปล้ำปลุกก็แล้ว มันทำให้ผมไม่สามารถเชื่อมต่อฐานข้อมูล 11g กับ SQL Developer ใช่ไหมก๊าบ?

>> พี่ชายที่รักตอบทันทีว่า มิได้! มันบ่อแม่นเด้อ เราต้องรู้จักโครงสร้าง (Architecture) ของเจ้า Oracle นี้ตอนติดตั้งเสียก่อน ว่าแล้วก็เปิด Youtube แกฟังเราฟัง ต่างคนต่างแปลแล้วคุยกัน ยิ่งคุยยิ่งมันส์ เกายังไม่ถูกที่คัน จวบจนกระทั่ง

>> แจ่มจันทร์! ผมคิดว่าใช่แน่ ต้องเป็นเพราะเจ้า Listener แน่แท้ ว่าแล้วก็เปิดไฟล์ที่ชื่อ listener.ora ซึ่งอยู่ ณ
C:\app\ProS\product\11.2.0\dbhome_2\NETWORK\ADMIN

>> อย่าได้ตกใจที่ oracle home ของผมมีชื่อ dbhome_2 แทนที่จะเป็น dbhome_1 นะครับ เพราะระหว่างนั้นผมลงฐานข้อมูลก้อนที่สองแล้ว เลขต่อท้ายมันเลยเพิ่ม พอเปิดไฟล์ดังกล่าวปุ๊บ พี่ชายผมก็ตาลุกเป็นประกายไฟ

>> โอ้เบบี๋ ชัดเลย! แล้วแกก็เปิดไปที่เว็บนี้ครับ ทดลองเปิดตามเลยนะจะได้รู้กันเสียที
http://www.toadworld.com/platforms/oracle/b/weblog/archive/2013/08/14/the-oracle-listener-process-how-does-it-work-connecting-to-oracle.aspx

>> เนื้อที่เยอะไปแล้ว ขอกล่าวสรุปให้เห็นภาพรวมดังนี้
- ปกติแล้ว Oracle จะวาง database ไว้ ณ oracle home ซึ่งเป็นไปตามความต้องการของเรา
- เมื่อมีฐานข้อมูลอยู่ในเครื่อง (ใน server หรืออื่นใด) ทางที่จะติดต่อฐานข้อมูลนี้ได้มีอยู่ สาม เส้นทาง (เท่าที่ทราบตอนนี้นะครับ)
1) ใช้ SQL Plus
2) ใช้ TCP/IP
3) และสามใช้ JDBC (Java Database Connectivity) หรืออื่นใดที่ไม่ใช่สองเส้นทางข้างต้น (กวนดี)
- SQL Plus สามารถอยู่แล้ว เพราะ Oracle จัดการมาให้พร้อมกับตัวฐานข้อมูล
- TCP/IP คือสิ่งที่ผมต้องการสำหรับติดต่อกับ SQL Developer
- JDBC หรืออื่นใด อันนี้ยังไม่ได้ศึกษา ไว้ก่อน

>> ยาวไป ขอต่อที่ part 4-2 แล้วกันครับ (ว่าแล้วระหว่างรอก็อ่านลิงค์ที่ให้ไปนะ คิดว่ากระจ่างกันทุกคน) ฝันดีจ้า

เริ่มต้นเรียนรู้ Oracle Database part 3

: ความคืบหน้าของเวอร์ชัน 11g

>> ดูเหมือนจะไปได้ดีกับ Oracle 11g ซึ่งผมทำตามวิธีการของคุณ Manish Sharma (พี่อินเดีย) จาก
http://www.youtube.com/watch?v=0NLsJQCvKXY&index=1&list=TL94bUdetKdfyrIoNpMzHF_xbxX4NCO_Cf

>> เกิดปัญหาในการเริ่มต้นฐานข้อมูลซึ่งเกี่ยวกับไฟล์ emctl.bat ซึ่งอยู่ ณ
C:\app\ProS\product\11.2.0\dbhome_1\BIN
รายงานแจ้งว่าให้ไปเปิดไฟล์นี้เองซึ่งก็ได้ทำไปแล้ว (-*-)

>> เนื่องจากเวอร์ชันนี้จะมีตัวอย่างที่เป็นที่สนใจ (หลายต่อหลายเว็บเอ่ยถึงมันเหลือเกินครับ) คือ schema (ตู้เก็บของ) ชื่อ HR กับ SCOTT และเมื่อขั้นตอนการติดตั้งล่วงไปถึงการจัดการ database configuration assistant ผมก็เลยขอรีรหัสผ่านพร้อมปลดล็อค HR กับ SCOTT ด้วยเลย ดังภาพประกอบ

>> จากนั้นเราสามารถเริ่ม user interface การจัดการฐานข้อมูล Oracle 11g นี้ผ่านหน้าเว็บ https://localhost:1158/em (เมื่อการติดตั้งเสร็จสมบูรณ์ รายงานนี้จะปรากฏออกมาครับ) แต่ผมในขณะนี้ยังไม่สามารถใช้ได้

>> เข้าไปเจอในเว็บ
https://community.oracle.com/thread/618267?start=0&tstart=0
เขาแนะนำว่าให้เซต oracle_sid ให้ยิงไปที่ Global database name ที่เราได้ตั้งชื่อไว้ ซึ่งของผมคือ orcl ผ่านทาง command line (cmd) โดยเรายังสามารถตรวจสอบได้ว่า Global database name ของเราชื่ออะไรผ่านคำสั่ง v$database โดยกระบวนการทั้งหมดดังกล่าวสามารถดูได้จากวีดีโอของคุณ Manish Sharma ครับ

>> ไว้จัดการ connect ฐานข้อมูลได้เมื่อไร ค่อยมาเล่าเรื่องสิทธิ์ให้ฟังทีหลังนะ (โทษจ้า) คืนนี้ฝันดีครับผม


JavaScript Picture

วันพุธที่ 16 กรกฎาคม พ.ศ. 2557

สร้าง Tool-tip ขึ้นมาใช้เอง


: แชร์ประสบการณ์การเขียนโปรแกรมฉบับผู้เริ่มต้น เมื่อจำเป็นต้องสร้าง Tool-tip ขึ้นมาใช้เอง

>> ปัญหา : เพราะ Google table chart ที่ใช้อยู่ไม่ได้เตรียม Tool-tip text เอาไว้ให้ จึงต้องหาทางแก้ไขด้วยวิธีการอื่น
คำตอบที่ได้ : เมื่อค้นจากเว็บจึงทราบว่าสามารถสร้าง Tool-tip text ขึ้นมาใช้งานเองได้ อาจใช้ไลบรารีใดๆที่ชอบหรือตามแต่วิธีการที่เหมาะสมเท่าที่ความรู้ในขณะนั้นจะสามารถ

>> ภาพต่อไปนี้แสดงให้เห็นตัวอย่างการสร้าง Tool-tip text อย่างง่ายที่สุดขึ้นมาด้วยแท็ก div จำนวนสองแท็ก (แท็กอื่นก็ได้นะครับ) แท็ก div แรกจะห่อหุ่มแท็ก div ที่สองเอาไว้ภายใน โดยมีรายละเอียดสำคัญดังนี้
- แท็ก div แรก (ด้านนอกสุด) จะบรรจุ text ที่แสดงตามปกติ
- แท็ก div ที่สอง (ด้านใน) จะบรรจุ text ที่ต้องการให้แสดงในลักษณะของ Tool-tip (กล่องข้อความที่กำหนดสีพื้นหลังเป็นสีชมพู) เมื่อเกิดเหตุการณ์เม้าส์ hover (เอาเม้าส์ไปวางไว้เหนือข้อความ Hover Event)
- หัวใจอยู่ที่แท็ก div ที่สองต้องกำหนดค่า opacity เป็น 0 เพื่อให้โปรงแสงจนมองไม่เห็น รอคอยจนกว่าจะเกิดเหตุการณ์เม้าส์ hover จึงกำหนดค่า opacity ใหม่เป็น 1 (ค่านี้อยู่ระห่าง 0 ถึง 1) ซึ่งจะกลายเป็นทึบแสง เราจึงมองเห็นได้ครับ

*** หมายเหตุ หากรูปเล็กไปมองไม่เห็นโค้ด ให้คลิกขวาที่รูปแล้วเลือก 'เปิดรูปภาพในแท็บใหม่' แล้วขยายภาพเอานะครับ