diff --git a/.idea/dictionaries/DELL.xml b/.idea/dictionaries/DELL.xml new file mode 100644 index 0000000..d88077d --- /dev/null +++ b/.idea/dictionaries/DELL.xml @@ -0,0 +1,7 @@ + + + + frist + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index eb12724..9199649 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,17 @@ -# นี้มันปี 2016 แล้ว มาเรียนรู้ JavaScript ยุคสมัยใหม่กันเถอะ! +# มาเรียนรู้ JavaScript ยุคสมัยใหม่กันเถอะ! ![cover](images/Introduction3.png) ## สารบัญ -* [บทที่ 1 แนะนำภาษาจาวาสคริปต์](#บทที่-1-แนะนำภาษาจาวาสคริปต์) -* [บทที่ 2 ทวน ES5 (มาตรฐานเก่า)](#บทที่-2-ทวน-es5-มาตรฐานเก่า) -* [บทที่ 3 แนะนำ ES6](#บทที่-3-แนะนำ-es6) -* [บทที่ 4 แนะนำ ES7](#บทที่-4-แนะนำ-es7) -* [บทที่ 5 แนะนำ ES8](#บทที่-5-แนะนำ-es8) +* [แนะนำภาษาจาวาสคริปต์](#แนะนำภาษาจาวาสคริปต์) +* [ทวน ES5 (มาตรฐานเก่า)](#ทวน-es5-มาตรฐานเก่า) +* [แนะนำ ES6](#แนะนำ-es6) +* [แนะนำ ES7](#แนะนำ-es7) +* [แนะนำ ES8](#แนะนำ-es8) +* [แนะนำ ES9 และ ES10](#แนะนำ-es9-และ-es10) -## บทที่ 1 แนะนำภาษาจาวาสคริปต์ +## แนะนำภาษาจาวาสคริปต์ ### เกริ่นนำ @@ -26,7 +27,7 @@ ![คำคมจาวา](images/chap01/quotes.png) -* คนส่วนใหญ่รู้แค่ว่าใช้จาวาสคริปต์ร่วมกับภาษา HTML (ปัจจุบันเวอร์ชั่น HTML5) กับ CSS (ปัจจุบันเวอร์ชั่น CSS3) เพื่อทำให้เว็บมันไดนามิก ฟุ้งฟิ้ง กรุ้งกิ๊ง (มันดังในฝั่ง Font-end มานาน) +* คนส่วนใหญ่รู้แค่ว่าใช้จาวาสคริปต์ร่วมกับภาษา HTML (ปัจจุบันเวอร์ชั่น HTML5.1) กับ CSS (ปัจจุบันเวอร์ชั่น CSS3) เพื่อทำให้เว็บมันไดนามิก ฟุ้งฟิ้ง กรุ้งกิ๊ง (มันดังในฝั่ง Font-end มานาน) * แต่ปัจจุบันนี้จาวาสคริปต์สมัยใหม่ มันก้าวหน้าไปไกลมาก ๆๆๆ เพราะสามารถทำงานอยู่ฝั่งเซิร์ฟเวอร์ได้ (Back-end) ด้วย Node.js แม้แต่เอาไปทำแอพบนโมบาย หรือแม้แต่โรบอท ก็ยังทำได้ด้วย ….อายย่ะ @@ -44,13 +45,13 @@ * ต้องเข้าใจอย่างนี้นะครัช เนื่อง ES6 มันใหญ่โตอลังการงานสร้างมาก คืนรอปล่อยออกมาหมดทีเดียว ก็คงรอหลายชาติภพ อาจทำให้มีเสียงบ่นตามมาได้ ด้วยเหตุนี้เข้าถึงเพิ่มฟีเจอร์เล็กยิบ ๆ ย่อย ๆ มาใส่ไว้ในเวอร์ชั่นหลัง ๆ แทน -* โดยคาดว่าจากนี้ไป จะมีการประกาศเวอร์ชั่นใหม่ทุก ๆ ปี โดยให้คิดเสียว่า ES6 เหมือนโปรแกรมหลัก ส่วนเวอร์ชั่นที่ออกตามทีหลัง ไม่ได้ว่าจะเป็น ES7, ES8 และ ESXXXXX มันก็คือการอัพเดตซอฟต์แวร์ อะไรประมาณนี้ +* โดยคาดว่าจากนี้ไป จะมีการประกาศเวอร์ชั่นใหม่ทุก ๆ ปี โดยให้คิดเสียว่า ES6 เหมือนโปรแกรมหลัก ส่วนเวอร์ชั่นที่ออกตามทีหลัง ไม่ได้ว่าจะเป็น ES7, ES8 และ ESXXXXX __(ถ้ามีต่อนะ)__ มันก็คือการอัพเดตซอฟต์แวร์ อะไรประมาณนี้ ![ES7_ES8](images/chap01/ES7_ES8.PNG) -* API ที่ใช้ติดต่อกับ DOM หรือใช้งานร่วมกับ HTML5, CSS3 ใน ES6 เขาไม่ได้เปลี่ยนแปลงอะไรเลย +* API ที่ใช้ติดต่อกับ DOM หรือใช้งานร่วมกับ HTML5.1, CSS3 ใน ES6 เขาไม่ได้เปลี่ยนแปลงอะไรเลย -* ES6, ES7, ES8 มันเป็นแค่มาตรฐานใหม่สด ๆ ซิง ๆ ดังนั้นการใช้งานโดยตรงบนเว็บบราวเซอร์ (ปัจจุบันที่ผมเขียนอยู่นี้) ก็ยังไม่ support ทุกฟีเจอร์ ต้องมีตัวคอมไพล์ช่วยก่อน (ยังมีข้อจำกัดบางประการ) …แต่ถ้าใครใช้ Node.js เวอร์ชั่น 7 ขึ้นไป ก็จะรองรับ ES6 ได้ 98% (ES7 รองรับได้บางส่วน) +* ES6, ES7, ES8 มันเป็นแค่มาตรฐานใหม่สด ๆ ซิง ๆ ดังนั้นการใช้งานโดยตรงบนเว็บบราวเซอร์ (ปัจจุบันที่ผมเขียนอยู่นี้) ก็ยังไม่ support ทุกฟีเจอร์ ต้องมีตัวคอมไพล์ช่วยก่อน (ยังมีข้อจำกัดบางประการ) …แต่ถ้าใครใช้ Node.js เวอร์ชั่น 7 ก็จะรองรับ ES6 ได้ 99% ![ES5_ES6_ES7_ES8](images/chap01/Table_ES_version.PNG) @@ -93,12 +94,6 @@ ![my ebook](images/chap01/my_book.PNG) -ถ้าใครขี้เกียจสมัครเป็นสมัครชิก ก็ให้ใช้ลิงค์ดังต่อไปนี้แทน - -* http://www.ebooks.in.th/ebook/37385/วิธีติดตั้ง_Node.js_และ_npm_เบื้องต้น/ -* http://www.ebooks.in.th/ebook/37714/เสียดายไม่ได้อ่าน_จาวาสคริปต์ฝั่งเซิร์ฟเวอร์_Node.js_(ฉบับย่อ)/ -* http://www.ebooks.in.th/ebook/37836/เสียดายไม่ได้อ่าน_จาวาสคริปต์ฝั่งเซิร์ฟเวอร์_Node.js_ฉบับย่อ_เล่ม2/ -* http://www.ebooks.in.th/ebook/37861/การใช้งาน_MongoDB_เบื้องต้น/ * เล่มอื่นเผื่อใครสนใจ http://www.ebooks.in.th/adminho/ ![read books](images/read_book.png) @@ -284,10 +279,9 @@ import "./mylib.js"; // อ้างไฟล์ .js **หมายเหต** วิธีอิมพอร์ตไฟล์ด้วยวิธีนี้ ถ้าไปเปิดดูบน Google Chrome อาจไม่ทำงาน แต่ไม่ต้องซีเรียส เรามีทางแก้ไข แนะนำให้ไปอ่านหัวข้อ [Cross-origin resource sharing (CORS)] (#cross-origin-resource-sharing-cors) - #### Babel -ต่อไปจะแสดงการเขียนจาวาสคริปต์บนเว็บเบราเซอร์ โดยใช้ Babel ทำตัวเป็น transpiler (ผลการทำงานจะเหมือนเวลาใช้ traceur ) +ต่อไปจะแสดงการเขียนจาวาสคริปต์บนเว็บเบราเซอร์ โดยใช้ Babel ทำตัวเป็น transpiler (ผลการทำงานจะเหมือนตัวอย่างตอนใช้ Traceur ) ```js @@ -333,7 +327,6 @@ C:\ES6> ![Hello world es6 es7](images/chap01/helloworld_es6_es7.png) - สังเกตในโค้ดจะต้องระบุ < script type="text/babel" > หรือเขียนเป็น < script type="text/jsx" > ก็ได้เหมือนกัน แต่ถ้าจะเขียนโค้ดจาวาสคริปต์ แยกออกมาเป็นไฟล์ .js เช่น mylib.js ก็สามารถทำได้ โดยจะมีโครงสร้างข้างล่าง (ไฟล์ .js หน้าตาเหมือนตอนใช้ Traceur) @@ -376,7 +369,7 @@ C:\ES6> C:\ES6>npm install -save traceur ``` -จะเห็นไฟล์ถูกโหลดเข้ามาได้แก่ traceur.js กับ BrowserSystem.js +จะเห็นไฟล์ถูกโหลดเข้ามาเก็บ ได้แก่ traceur.js กับ BrowserSystem.js ```js C:\ES6\node_modules\traceur\bin @@ -411,746 +404,286 @@ C:\ES6\node_modules\babel-standalone https://github.com/Daniel15/babel-standalone/releases +*** Traceur กับ Babelเท่าที่ผมลองใช้งานดู มันยังไม่นิ่งเท่าไร ถ้าจะนำมันไปใช้งานยังไง ก็ควรหมั่นอัพเดตจากทีมสร้างเขาอีกทีนะครับ ...ที่สำคัญวิธีใช้งานแต่ละเจ้า ก็ดันแตกต่างกันอีกแฮะ! จนหนังสือที่ผมเขียนไป ถ้าใครลองทำตาม แล้วใช้งาน ES6 ไม่ได้ เค้าขอโทษแล้วกันน๊า! ยังไงเดี่ยวขออัพเดตโค้ดล่าสุดที่เว็บนี้แล้วกันเนอะ -*** Traceur ที่เห็นเป็นของ Google กับ Babelแต่ทั้งนี้ปัจจุบันตัว transpiler ก็มีหลายเจ้าให้เลือก ซึ่งเท่าที่ผมลองใช้งานดู มันก็ยังไม่นิ่งเท่าไร ถ้าจะนำมันไปใช้งานยังไง ก็ควรหมั่นอัพเดตจากทีมสร้างเขาอีกทีนะครับ ...ที่สำคัญวิธีใช้งานแต่ละเจ้า ก็ดันแตกต่างกันอีกแฮะ! - -จนหนังสือที่ผมเขียนไป ถ้าใครลองทำตาม แล้วใช้งาน ES6 ไม่ได้ เค้าขอโทษแล้วกันน๊า! ยังไงเดี่ยวขออัพเดตโค้ดล่าสุดที่เว็บนี้แล้วกันเนอะ - -### Cross-origin resource sharing (CORS) - -โดยปกติแล้วเว็บเพจ จะไม่สามารถแชร์ resources ข้าม domain กันได้ (เช่น ฟอนต์, ไฟล์จาวาสคริปต์ และรูปภาพ เป็นต้น) เพราะมันเป็นเรื่องของความปลอภัย (same-origin policy) - -คราวนี้ถ้าเขียนจาวาสคริปต์แบบแยกไฟล์ .js แล้วอิมพอร์ตเข้ามา (จากตัวอย่างก่อนหน้านี้ ผมอิมพอร์ตไฟล์ mylib.js เข้ามา ด้วยวิธี Traceur หรือ Babel) เมื่อนำไปเปิดบน Google Chrome อาจทำงานไม่ได้ (ซวยแล้วไง!) เพราะเมื่อไปดูที่ console จะเห็นมันฟ้องเรื่อง Cross origin ดังรูป - -![Hello world es6 es7](images/chap01/errorOnChome.png) - -แต่เราสามารถหลีกเลี่ยงกฏข้อนี้ได้ โดยใช้ Cross-origin resource sharing (CORS) ซึ่งเป็นกลไกอนุญาตให้ resources บนเว็บเพจ ถูกเข้าถึงจาก Domain อื่นได้ - - -**วิธีการ** - -สามารถทำได้ง่ายๆ เพียงแค่บอกให้เว็บเซิร์ฟเวอร์ เพิ่มค่าต่อไปนี้ลงไปใน HTTP Header (วิธีกำหนดค่านี้ ต้องดูที่คู่มือของเซิร์ฟเวอร์แต่ละเจ้าเอาเอง) - -```js -Access-Control-Allow-Origin: * -``` - -จริงๆ ทำแบบนี้ก็ดูไม่ปลอดภัยเท่าไร ทางที่ดีควรให้สิทธิเฉพาะ url เท่าที่จำเป็น ตัวอย่างเช่น - -```js -Access-Control-Allow-Origin: http://www.example.com http://test.example.com -``` - -(ที่มา http://manit-tree.blogspot.com/2012/07/cross-origin-resource-sharing.html) - - -แต่ถ้าเราไม่ได้เขียนเว็บ แล้วเทสบนเว็บเซิร์ฟเวอร์ อารมณ์ทดสอบเว็บบนเครื่องตัวเองแบบ local ก็ต้องเปิด Google chrome ด้วยท่าพิศดาร โดยปลดความปลอดภัยเรื่องนี้ออก เพื่อให้มันทำ CORS ได้ - -บนวินโดวส์ก็ให้ไปที่คอมมานไลน์ แล้วพิมพ์คำสั่งตามนี้ เมื่อนั้น Google Chrome ก็จะเปิดขึ้นมา แล้วถึงเปิดไฟล์ HTML ตามทีหลัง - -```js -chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security -``` - -หรือจะระบุชื่อไฟล์ HTML ให้เปิดขึ้นมาพร้อมกับ Google Chrome ก็ได้ -```js -chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security "c:\ES6\index.html" - -``` - -อีกวิธีหนึ่งง่ายดี ให้ไปที่ Shortcut ของ Google Chrome แล้วคลิกขวาเปิดมันขึ้นมา จากนั้นจึงเพิ่มค่าต่อไปนี้ตรงช่อง "Target:" หลังข้อความเดิม - -```js ---user-data-dir="C:/Chrome dev session" --disable-web-security -``` - -![Hello world es6 es7](images/chap01/howto_open_chrome_edit.png) - -ต่อไปนี้ ก็ให้เปิดที่ Shortcut ของ Google Chrome ก่อนเสมอ แล้วหลังจากนั้น จึงเปิดไฟล์ HTML ตามทีหลัง - - -ส่วนบน OSX กับ Linux ผมไม่มีเครื่องลองครับ จึงไม่กล้าเขียน ลองดูเพิ่มเติมได้ที่ - -http://stackoverflow.com/questions/3102819/disable-same-origin-policy-in-chrome) - -### ตัวอย่างการเขียน ES6 กับ ES7 บน Node.js - -ต่อไปจะแสดงการเขียนจาวาสคริปต์ด้วย ES6 กับ ES7 แล้วสั่งรันผ่านทาง Node.js โดยตรง ไม่ต้องใช้ transpiler (หรือจะใช้ ก็แล้วแต่ครับ) +### วิธีคอมไพล์จาก ES6 ให้เป็น ES5 ด้วยมือตนเอง -*** ทั้งนี้ Node.js เวอร์ชั่น 7 ขึ้นไปก็จะรองรับ ES6 ได้ 98% +#### Traceur -*** ส่วน ES7 ผมยังไม่ค่อยแน่ใจสักเท่าไร +เราสามารถใช้กระบวนท่าแปลงซอร์สโค้ดจาก ES6 เป็น ES5 ด้วยมือตนเอง ด้วยการเปิดคอมมานไลน์ขึ้นมา (ตัวอย่างจะใช้วินโดวส์) แล้วเรียกสคริปต์ traceur ซึ่งถ้าคุณทำตามตัวอย่างก่อนหน้า ที่แนะวิธีโหลดไฟล์ Traceur มาเก็บแบบออฟไลน์ ด้วยคำสั่ง npm install -save traceur ก็ให้ไปที่โฟลเดอร์ ...\node_modules\ .bin จะเห็นไฟล์สคริปดังนี้ ```js -class Chat{ // class ไวยากรณ์ใหม่ของ ES6 - constructor(message) { // constructor ไวยากรณ์ใหม่ของ ES6 - this.message = message; - } - say(){ - console.log(this.message); - } -} - -let chat = new Chat("Hello, world!"); // let ไวยากรณ์ใหม่ของ ES6 -chat.say(); // "Hello, world!" - -let array = ["A", "B", "C"]; -console.log(array.includes("A")); // true -- เมธอดของอาร์เรย์ที่เพิ่มมาใน ES7 +C:\ES6\node_modules\.bin + |-- traceur + |-- traceur.cmd ``` -จะสมมติว่าบันทึกเป็นไฟล์ test.js โดยมีโครงสร้างโปรเจคดังนี้ +จากไฟล์ mylib.js ในตัวอย่างก่อนหน้านี้ (โค้ด ES6) ```js C:\ES6> - |-- test.js + |-- index.html + |-- mylib.js ``` -รันไฟล์ test.js ผ่านทาง Node.js ด้วยความสั่งต่อไปนี้ ตามรูป - -![node.js es6 es7](images/chap01/node.js_es6_es7.png) - -## บทที่ 2 ทวน ES5 (มาตรฐานเก่า) - -![cover](images/chap02/Introduction_edit1.png) - -จาวาสคริปต์ยังคงความอินดี้ของมาตรฐานตัวเดิมเอาไว้เช่นเดิม (ES5) โดยไม่ได้ลบเลือนจางหายไปไหนเลย ซึ่งบทนี้เราจะมาทบทวนคร่าวๆ กัน - -(บทนี้ ยังไม่เสร็จดีครับ) -### Comments - -คอมเมนต์ในจาวาสคริปต์ ก็จะเหมือนภาษาที่มีรากฐานมาจากภาษา C โดยจะใช้เครื่องหมาย // นำหน้าประโยคที่ต้องการคอมเมนต์ได้เพียงบรรทัดเดียวเท่านั้น +เราก็สามารถเรียกสคริปต์ traceur ให้มาทำการคอมไฟล์ mylib.js เพื่อแปลงเป็น ES5 ได้คำสั่งดังนี้ ```js -var x = 10; //This is an example. +C:\ES6\node_modules\.bin>traceur --out ../../out/mylib.js --script ../../mylib.js ``` -แต่ถ้าต้องการคอมเมนต์หลายๆ บรรทัด ก็ให้ใช้เครื่องหมาย /*… */ มาครอบเปิดและปิดท้าย กลุ่มประโยคที่ต้องการ +(ถ้าติดตั้ง Traceur ด้วยคำสั่ง npm install -g traceur ก็ไม่ต้อง cd มาที่ C:\ES6\node_modules\ .bin) + +สำหรับไฟล์ที่ถูกแปลงเป็น ES5 จะเก็บอยู่ที่โฟลเดอร์ out\mylib.js ```js -/* This is an example -ECMAScript 6 is very easy*/ +C:\ES6> + |-- index.html + |-- mylib.js + |-- out + |-- mylib.js +``` + +ถ้าแอบไปเปิดไฟล์ out\mylib.js ก็จะเห็นว่าโค้ดถูกแปลงเป็น ES5 หน้าตาเรียบร้อยดังนี้ + +```js +var Chat = function() { + "use strict"; + function Chat(message) { + this.message = message; + } + return ($traceurRuntime.createClass)(Chat, {say: function() { + var element = document.querySelector('#element1'); + element.innerHTML = this.message; + }}, {}); +}(); +var chat = new Chat("Hello, world!"); +chat.say(); +var array = ["A", "B", "C"]; +console.log(array.includes("A")); ``` -### console.log -ประโยคคำสั่ง console.log() จะเป็นฟังก์ชั่น (Function) ในจาวาสคริปต์ ที่ใช้ประโยชน์ในแง่ของการดีบั๊ก (Debug) เพื่อแสดงข้อความออกทางหน้าคอนโซล (Console) +จากตัวอย่างเดิม ก็สามารถเขียนใหม่ได้ดังนี้ ```js + - - - -

Hello, world!

- - - -``` - -จะปรากฏผลลัพธ์ดังนี้ - -![Hello world](images/chap02/hello_word_console.png) - -### Semicolon - -จาวาสคริปต์ถือว่าเป็นภาษาหนึ่ง ที่ไม่ต้องใช้เครื่องหมายเซมิโคลอน (;) ต่อท้ายแต่ละประโยคคำสั่งก็ได้ ดังตัวอย่าง - -```js -// ไม่ต้องมี ; ต่อท้ายประโยคก็ได้ -console.log("Hello world") - -// หรือมี ; ต่อท้ายประโยคก็ได้ -console.log("Hello world"); -``` - -แต่ถ้ามี 2 ประโยคคำสั่งขึ้นไป เขียนติดกันอยู่ภายในบรรทัดเดียวกัน จะต้องมี ; แบ่งคันเอาไว้เสมอ - -```js -// แบบนี้จะเกิด Syntax Error เพราะไม่มี ; แบ่งคั่นประโยค -// console.log("Hello, world!") console.log("Hello, world!"); - -console.log("Hello, world!") ; console.log("Hello, world!") -// Hello, world! -// Hello, world! -``` -แต่ทั้งนี้เขาจะนิยมใส่ ; ต่อท้ายประโยคเหมือนหลายๆ ภาษา - -![semicolon](images/chap02/semicolonForgot2.png) - -### การประกาศตัวแปร + -การประกาศตัวแปร จะใช้คีย์เวิร์ด var นำหน้าชื่อตัวแปร ดังตัวอย่าง + + -```js -var x = 100; -``` + -หรือจะประกาศตัวแปรให้อยู่ในบรรทัดเดียวกันก็ได้ ดังตัวอย่าง -```js -var x = 1, y = 2, z = 3; // ประกาศตัวแปร x, y และ z ให้อยู่ในบรรทัดเดียวกัน -``` + +

-แต่ถ้าเราไม่ได้กำหนดค่าเริ่มต้นให้กับตัวแปร ตอนประกาศตัวแปร ก็จะมีค่าเป็น undefined ดังตัวอย่าง + + -```js -var x; -console.log(x); // undefined + + ``` -### Literals -สำหรับข้อมูล (Literals) ที่สามารถกำหนดค่าให้กับตัวแปรได้นั้น ในจาวาสคริปต์ก็จะมีหลากหลายชนิดข้อมูล แต่โดยหลัก ๆ จะมีอยู่ 2 แบบได้แก่ - -* ข้อมูลพื้นฐาน (Primitives data) -* อ็อบเจ็กต์ (Object) - -สำหรับข้อมูลพื้นฐาน จะแยกย่อยได้นี้ -* null -* undefined -* ตัวเลข (Number) -* สตริง (String) รวมทั้งเทมเพลตสตริง (Template String) -* บูลีน (Boolean) -* ซิมโบล (Symbol) +ซึ่งผลการทำงานจะเหมือนกับตัวอย่างก่อนๆ ที่ยกมา -### Function - -ตัวอย่างต่อไปนี้จะเป็นการประกาศฟังก์ชั่น - -```js -function calculate(param1, param2){ - return param1 * param2; -} -``` +#### Babel -ส่วนวิธีเรียกใช้งานฟังก์ชั่น ก็จะเหมือนกับภาษาเขียนโปรแกรมทั่ว ๆ ไป ดังตัวอย่าง +สำหรับ Babel ก็เช่นกัน สามารถใช้กระบวนท่าแปลงซอร์สโค้ดจาก ES6 ให้เป็น ES5 ด้วยมือตนเอง โดยทำตามตัวอย่างจากเว็บต้นทางผู้สร้าง เขาจะแนะนำตามนี้ ```js -var result = calculate(10, 2); -console.log(result); // 20 +var input = 'const getMessage = () => "Hello World";'; +var output = Babel.transform(input, { presets: ['es2015'] }).code; ``` -### Hoist - -การประกาศฟังก์ชั่น รวมทั้งการประกาศตัวแปรแบบ var มันจะลอยขึ้นไปประกาศอยู่ข้างบนสุดของขอบเขตการมองเห็น ดังตัวอย่าง +จากตัวอย่างเดิม ก็สามารถเขียนใหม่ได้ดังนี้ ```js -function myFunction(num){ - // สามารถมองเห็นตัวแปร value - console.log(value); // undefined - - if(num > 10) { - var value = num*10; // ประกาศตัวแปร value ที่ตรงนี้ แต่มองเห็นได้ทั่วฟังก์ชั่น - - /* ซอร์สโค้ด */ - - } else { - - // ถ้าเงื่อนไขประโยค if เป็นเท็จ ก็จะเข้ามาทำงานที่ else - // ซึ่งจะเห็นตัวแปร value มีค่าเป็น undefined - - console.log(value); // undefined - } - - // สามารถมองเห็นตัวแปร value ได้ หลังจากประโยค if …else ทำงานเสร็จสิ้น - console.log(value); -} -``` + + + + -จากตัวอย่างซอร์โค้ดดังกล่าวที่ยกมาให้ดู จริง ๆ แล้ว จาวาสคริปต์จะทำการแปลงซอร์สโค้ดให้มีหน้าตาดังต่อไปนี้ + + -```js -function myFunction(num){ - var value; // ประกาศตัวแปร value โดยไม่มีค่าเริ่มต้น จึงทำให้มีค่าเป็น undefined - console.log(value); // undefined - - if(num > 10) { - value = num*10; // บรรทัดนี้เป็นเพียงการกำหนดค่าให้กับตัวแปร value - - /* ซอร์สโค้ด */ - - } else { - - console.log(value); // undefined - - } + + +

+ + + ``` -(เดี่ยวมาเขียนต่อให้เสร็จ) - -### 3.2 Functions - -#### Arrow Functions - -ในหลาย ๆ ภาษาจะมี "Lambda expressions" ซึ่งคนที่มาจากภาษาอื่นอาจรู้จักกันดีอยู่แล้ว เช่น +ซึ่งผลการทำงานจะเหมือนกับตัวอย่างก่อนๆ ที่ยกมา -* ใน C# จะใช้สัญลักษณ์ => -* หรือถ้าเป็นจาวา (ตั้งแต่ Java 8) จะใช้สัญลักษณ์ -> -* ใน Python ใช้คีย์เวิร์ด lambda - -แต่สำหรับจาวาสคริปต์จะเรียกว่า "Arrow Functions" แปลตรงตัวก็คือ "ฟังก์ชั่นลูกศร" โดยใช้เครื่องหมาย => (มันคือฟังก์ชั่นไร้ชื่อ ที่ไม่ได้ใช้คีย์เวิร์ด function) ซึ่งมันเขียนได้หลายวิธีมากๆ ดังตัวอย่างต่อไปนี้ +### Cross-origin resource sharing (CORS) -##### ตัวอย่างที่ 1 +โดยปกติแล้วเว็บเพจ จะไม่สามารถแชร์ resources ข้าม domain กันได้ (เช่น ฟอนต์, ไฟล์จาวาสคริปต์ และรูปภาพ เป็นต้น) เพราะมันเป็นเรื่องของความปลอภัย (same-origin policy) -```js -let arrowFunc = function(value){ - return value; -}; +คราวนี้ถ้าเขียนจาวาสคริปต์แบบแยกไฟล์ .js แล้วอิมพอร์ตเข้ามา (จากตัวอย่างก่อนหน้านี้ ผมอิมพอร์ตไฟล์ mylib.js เข้ามา ด้วยวิธี Traceur หรือ Babel) เมื่อนำไปเปิดบน Google Chrome อาจทำงานไม่ได้ (ซวยแล้วไง!) เพราะเมื่อไปดูที่ console จะเห็นมันฟ้องเรื่อง Cross origin ดังรูป -console.log(arrowFunc(122)); // 122 -``` +![Hello world es6 es7](images/chap01/errorOnChome.png) -จากตัวอย่างดังกล่าว สามารถเปลี่ยนมาเขียนแบบฟังก์ชั่นลูกศร ได้ดังนี้ +แต่เราสามารถหลีกเลี่ยงกฏข้อนี้ได้ โดยใช้ Cross-origin resource sharing (CORS) ซึ่งเป็นกลไกอนุญาตให้ resources บนเว็บเพจ ถูกเข้าถึงจาก Domain อื่นได้ -```js -let arrowFunc = value => { - return value; -}; -// เรียกใช้ฟังก์ชั่นได้เหมือนปกติธรรมดา -console.log(arrowFunc(122)); // 122 -``` -##### ตัวอย่างที่ 2 +**วิธีการแก้ปัญหา** -```js -// เหมือนในตัวอย่างที่ 1 แต่การเขียนจะสั้นและกระชับกว่า -// ไม่ต้องมีเครื่องหมายปีกกา {....} ครอบบอดี้ฟังก์ชั่น รวมทั้งไม่ต้องเขียนประโยคคำสั่ง return -let arrowFunc = value => value; -console.log(arrowFunc(122)); // 122 -``` +__วิธี1__ -จะเสมือนเขียนเป็น +สามารถทำได้ง่ายๆ เพียงแค่บอกให้เว็บเซิร์ฟเวอร์ เพิ่มค่าต่อไปนี้ลงไปใน HTTP Header (วิธีกำหนดค่านี้ ต้องดูที่คู่มือของเซิร์ฟเวอร์แต่ละเจ้าเอาเอง) ```js -let arrowFunc = function(value){ - return value; -}; -console.log(arrowFunc(122)); // 122 +Access-Control-Allow-Origin: * ``` -อีกตัวอย่างหนึ่ง +จริงๆ ทำแบบนี้ก็ดูไม่ปลอดภัยเท่าไร ทางที่ดีควรให้สิทธิเฉพาะ url เท่าที่จำเป็น ตัวอย่างเช่น ```js -let arrowFunc2 = value => console.log(value); -arrowFunc2(122); // 122 +Access-Control-Allow-Origin: http://www.example.com http://test.example.com ``` -จะเสมือนเขียนเป็น +(ที่มา http://manit-tree.blogspot.com/2012/07/cross-origin-resource-sharing.html) -```js -let arrowFunc2 = function(value){ - return console.log(value); -}; -arrowFunc2(122); // 122 -``` -##### ตัวอย่างที่ 3 +__วิธีที่ 2__ -```js -// ฟังก์ชั่นลูกศรที่ไม่มีการประกาศพารามิเตอร์อะไรเลย -let arrowFunc = () => 122; -console.log(arrowFunc()); // 122 -``` +ถ้าเราไม่ได้เขียนเว็บ แล้วเทสบนเว็บเซิร์ฟเวอร์ อารมณ์ทดสอบเว็บบนเครื่องตัวเองแบบ local ก็ต้องเปิด Google chrome ด้วยท่าพิศดาร โดยปลดความปลอดภัยเรื่องนี้ออก เพื่อให้มันทำ CORS ได้ -จะเสมือนเขียนเป็น +บนวินโดวส์ก็ให้ไปที่คอมมานไลน์ แล้วพิมพ์คำสั่งตามนี้ เมื่อนั้น Google Chrome ก็จะเปิดขึ้นมา แล้วถึงเปิดไฟล์ HTML ตามทีหลัง ```js -let arrowFunc = function(){ - return 122; -}; -console.log(arrowFunc()); // 122 -``` - -##### ตัวอย่างที่ 4 - -```js -// ฟังก์ชั่นลูกศรที่ไม่มีพารามิเตอร์ และตัวบอดี้ของฟังก์ชั่นก็ว่างเปล่า -let arrowFunc = () => {}; -arrowFunc(); -``` - -จะเสมือนเขียนเป็น - -```js -var arrowFunc = function(){}; -arrowFunc(); -``` - -##### ตัวอย่างที่ 5 - -```js -// ใส่เครื่องหมายวงเล็บ เพื่อครอบอ็อบเจ็กต์ที่ถูกรีเทิร์นออกมา -let getFont = () => ( { color: "red", size: 200 } ); -console.log(getFont()); // {color: "red", size: 200} -``` - -จะเสมือนเขียนเป็น - -```js -let getFont = function(){ - return {color: "red", size: 200}; -}; -console.log(getFont()); // {color: "red", size: 200} -``` - -##### ตัวอย่างที่ 6 - -```js -// มีวงเล็บครอบพารามิเตอร์เอาไว้ -let sum = (val1, val2, val3) => val1 + val2 + val3; -console.log(sum(1,2,3)); // 6 +chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security ``` -จะเสมือนเขียนเป็น - +หรือจะระบุชื่อไฟล์ HTML ให้เปิดขึ้นมาพร้อมกับ Google Chrome ก็ได้ ```js -let sum = function(val1, val2, val3){ - return val1 + val2 +val3; -}; -console.log(sum(1,2,3)); // 6 -``` - -##### ตัวอย่างที่ 7 - -```js -// ฟังก์ชั่นลูกศรที่ใช้พารามิเตอร์แบบดีฟอลต์ -let sum = (val1 = 1, val2 = 2, val3 = 3) => val1 + val2 + val3; -console.log(sum()); // 6 -``` - -จะเสมือนเขียนเป็น - -```js -let sum = function(val1 = 1, val2 = 2, val3 = 3){ - return val1 + val2 +val3; -}; -console.log(sum()); // 6 -``` - -##### ตัวอย่างที่ 8 - -```js -// ฟังก์ชั่นลูกศรที่ใช้พารามิเตอร์แบบเรสต์ -let max = (...value) => Math.max(...value); -console.log(max(1, 2, 3, 6)); // 6 -``` - -จะเสมือนเขียน +chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security "c:\ES6\index.html" -```js -let max = function(...value){ // พารามิเตอร์แบบเรสต์ - return Math.max(...value); // โอเปอเรเตอร์สเปรด -}; -console.log(max(1, 2, 3, 6)); // 6 ``` -(ยังเขียนไม่เสร็จดี) - -### 3.3 Template strings - -เทมเพลตสตริง (Template strings) จะใช้เครื่องหมาย back-tick (ตัวอักษร grave accent) มาครอบข้อความเอาไว้ (เครื่องหมายจะคล้ายๆ กับคำพูดเดี่ยว แต่มันจะเอนไปด้านหน้าเล็กน้อย) ดังตัวอย่าง - -```js -let msg = `JavaScript`; +อีกวิธีหนึ่งง่ายดี ให้ไปที่ Shortcut ของ Google Chrome แล้วคลิกขวาเปิดมันขึ้นมา จากนั้นจึงเพิ่มค่าต่อไปนี้ตรงช่อง "Target:" หลังข้อความเดิม -console.log(msg); // "JavaScript" -console.log(msg.length); // 10 -console.log(typeof msg); // "string" +```js +--user-data-dir="C:/Chrome dev session" --disable-web-security ``` -#### เขียนสตริงหลายบรรทัด - -เทมเพลตสตริงสามารถเขียนข้อความได้มากกว่า 1 บรรทัด (Multiline strings) ดังตัวอย่าง - -```js -let div = `
-

Hello world

-
`; +![Hello world es6 es7](images/chap01/howto_open_chrome_edit.png) -console.log(div); -``` +ต่อไปนี้ ก็ให้เปิดที่ Shortcut ของ Google Chrome ก่อนเสมอ แล้วหลังจากนั้น จึงเปิดไฟล์ HTML ตามทีหลัง -แสดงผลลัพธ์เป็น -```js -
-

Hello world

-
-``` -#### นิพจน์ในเทมเพลตสตริง +ส่วนบน OSX กับ Linux ผมไม่มีเครื่องลองครับ จึงไม่กล้าเขียน ลองดูเพิ่มเติมได้ที่ -ปกติแล้วการเขียนนิพจน์ร่วมกับสตริงแบบเดิมจะดูยุ่งยากมาก เพราะต้องใช้เครื่องหมายบวก (+) เชื่อมสตริงกับนิพจน์ต่าง ๆ เข้าด้วยกัน ดังตัวอย่าง +http://stackoverflow.com/questions/3102819/disable-same-origin-policy-in-chrome -```js -let a = 5, b = 10, c = 100; -console.log("Price $" + ((a*b).toFixed(2)) + ", not " + (c + a) ); // "Price $50.00, not 105" -``` +__วิธีที่ 3__ -แต่ถ้าลองเปลี่ยนมาใช้เทมเพลตสตริง ก็สามารถยัดนิพจน์เข้าไปอยู่ในสตริงได้เลย ดังตัวอย่าง +จากไฟล์ index.html ที่มีปัญหาเวลาเปิด Google Chrome แล้วไม่ทำงาน ```js -let a = 5, b = 10, c = 100; - -console.log(`Price $${(a*b).toFixed(2)}, not ${c + a}` ); // "Price $50.00, not 105" +C:\ES6> + |-- index.html + |-- mylib.js ``` -### 3.4 Symbols - -(เดี่ยวมาเขียน) - -### 3.5 Objects - -(เดี่ยวมาเขียน) - -### 3.6 คลาส - -คลาสใน ES6 จะเหมือนกับภาษาโปรแกรมเชิงวัตถุอื่น ๆ (OOP: Object Oriented Programming) ที่เปรียบได้เป็นพิมพ์เขียวเอาไว้สร้างอ็อบเจ็กต์ โดยตัวอย่างต่อไปนี้จะแสดงการประกาศคลาส Car ขึ้้นมา (ยังไม่มีสมาชิกอะไรอยู่ข้างใน) +ให้ลองใช้เซิร์ฟเวอร์จำลอง จาก Node.js แต่ก่อนอื่นจะให้ติดตั้งเซิร์ฟเวอร์ที่ว่า ก็คือ live-server ด้วยคำสั่ง npm ดังนี้ ```js -class Car { - // สมาชิกภายในคลาส ยังไม่ได้ประกาศ -} +npm install -g live-server ``` -มันก็เหมือนๆ ภาษาอื่น เราสามารถใช้โอเปอเรอตร์ new สร้างอ็อบเจ็กต์จากคลาส Car ข้างต้นขึ้นมาได้ +จากนั้นก็ cd ไปที่ C:\ES6\ ต่อด้วยสั่งให้ live-server ทำการรัน index.html ด้วยคำสั่งง่ายๆ ดังนี้ ```js -let car1 = new Car(); -let car2 = new Car(); -let car3 = new Car(); +C:\ES6>live-server ``` -#### สมาชิกคลาส - -ในคลาสสามารถมีสมาชิกดังต่อไปนี้ - -1) สมาชิกที่เป็นคอนสตรัคเตอร์ (constructor) โดยใช้เมธอดที่ชื่อ constructor ทำหน้าที่เป็นคอนสตรัคเตอร์เหมือนในภาษา OOP อื่นๆ - -2) สมาชิกที่เป็นเมธอด - -*** ทั้งนี้สมาชิกของคลาส ไม่ว่าจะเป็นคอนสตรัคเตอร์ และเมธอดต่างๆ ไม่ต้องใช้เครื่องหมายจุลภาค , แบ่งคั่นนะ - -```js -class Car { - constructor(param){ // ประกาศคอนสตรัคเตอร์ - console.log(param); - } - - drive(){ // ประกาศเมธอด - console.log("The car is running"); - } -} - -let carObj = new Car("red"); // "red" -carObj.drive(); // "The car is running" -``` +เมื่อนั้นเว็บบราวเซอร์ที่ถูกตั้งไว้เป็นดีฟอลต์ ก็จะเด้งขึ้นมา และเปิดไฟล์ index.html อย่างอัตโนมัติ หรือถ้าเครื่องเรา Google Chrome ไม่ได้ตั้งเป็นดีฟอลต์ ก็ให้กรอก url ตรงๆ เป็น http://127.0.0.1:8080/ ตามรูป -มีข้อสังเกต ในภาษา C++, Java, C# สามารถประกาศตัวแปรเป็นสมาชิกประเภทหนึ่งในคลาสได้ -แต่เสียใจด้วยใน ES6 ไม่สามารถประกาศตัวแปร เป็นสมาชิกในคลาสได้ ...เว้นแต่ใช้ภาษา TypeScript เราก็สามารถประกาศได้ +![Hello world es6 es7](images/chap01/run_with_live-server.png) -ถึงกระนั้นก็ดีสามารถประกาศพร็อพเพอร์ตี้ที่เป็นตัวแปรขึ้นมาได้ ด้วยการใช้ this.xxx ภายในคอนสตรัคเตอร์ ดังตัวอย่าง -(ในเมธอดก็ประกาศได้ แต่อาจผิดหลักการ OOP ซึ่งคอนสตรัคเตอร์ ควรทำหน้าที่กำหนดค่าต่างๆ ให้กับพร็อพเพอร์ตี้ของอ็อบเจ็กต์) +** เสริมนิดหนึ่ง ถ้าใครใช้ Python ก็อาจใช้เซิร์ฟเวอร์จำลองได้ด้วยเช่นกัน อย่างกรณีผมใช้ Python 3 ก็จะพิมพ์คำสั่งดังนี้ ```js -class Car { - constructor(param){ - this.param = param; // ประกาศพร็อพเพอร์ตี้ param ขึ้นมา (แต่เป็นของอ็อบเจ็กต์) แล้วกำหนดค่าให้มัน - } - - drive(){ - console.log(`The ${this.param} car is running`); - } -} - -let carObj = new Car("red"); // "red" -carObj.drive(); // "The red car is running" +C:\ES6>python -m http.server 8080 ``` -#### Property accessors - -เราสามารถมีพร็อพเพอร์ตี้แอคเซสเซอร์ (Property accessors) หรือเมธอด getter กับ setter ในคลาส ดังตัวอย่าง - -```js -class Car { - constructor (){ - this.speedValue = 100; - } - get speed(){ // เมธอด getter - return this.speedValue; - } - set speed(speedValue) { // เมธอด setter - this.speedValue = speedValue; - } -} - -let carObj = new Car(100); -console.log(carObj.speed); // 100 +จากนั้นก็เปิด Google Chrome ขึ้นมาโดยกรอก url เป็น http://127.0.0.1:8080/ -carObj.speed = 60; -console.log(carObj.speed); // 60 -console.log(carObj.speedValue); // 60 (่ไม่ควรเข้าถึงด้วยวิธีนี้โดยตรง ตามหลัก information hiding ของ OOP) -``` -#### Static methods +### ตัวอย่างการเขียน ES6 กับ ES7 บน Node.js -เมธอดสแตติก (Static methods) คือเมธอดของคลาส ที่เวลาเรียกใช้งานจะต้องผ่านชื่อคลาสโดยตรง (ไม่ต้องเรียกผ่านอ็อบเจ็กต์ เพราะมันไม่ใช่เมธอดของอ็อบเจ็กต์) +ต่อไปจะแสดงการเขียนจาวาสคริปต์ด้วย ES6 กับ ES7 แล้วสั่งรันผ่านทาง Node.js โดยตรง ไม่ต้องใช้ transpiler (หรือจะใช้ ก็แล้วแต่ครับ) -โดยสามารถใช้คีย์เวิร์ด static นำหน้าชื่อเมธอด หรือพร็อพเพอร์ตี้แอคเซสเซอร์ก็ได้ แต่มีข้อแม้ว่าห้ามใช้คำว่า static นำหน้าคอนสตรัคเตอร์ +*** ทั้งนี้ Node.js เวอร์ชั่น 7 ขึ้นไปก็จะรองรับ ES6 ได้ 99% ```js -class Car { - constructor (speed){ // ห้ามมีคำว่า static นำหน้าคอนสตัคเตอร์ - this.speed = speed; - } - drive(){ - console.log("Driving speed:", this.speed); - +class Chat{ // class ไวยากรณ์ใหม่ของ ES6 + constructor(message) { // constructor ไวยากรณ์ใหม่ของ ES6 + this.message = message; } - static stop() { // เมธอดสแตติก - console.log("Stop this car"); + say(){ + console.log(this.message); } -} +} -// เรียกใช้งานเมธอดสแตติกผ่านชื่อคลาส -Car.stop(); // "Stop this car" +let chat = new Chat("Hello, world!"); // let ไวยากรณ์ใหม่ของ ES6 +chat.say(); // "Hello, world!" -let carObj = new Car(100); -carObj.drive(); // "Driving speed: 100" -console.log(typeof carObj.drive); // "function" -console.log(typeof carObj.stop); // undefined +let array = ["A", "B", "C"]; +console.log(array.includes("A")); // true -- เมธอดของอาร์เรย์ที่เพิ่มมาใน ES7 ``` -#### Class Inheritance - -การสืบทอดคลาส (Class Inheritance) ในจาวาสคริปต์ สามารถทำได้โดยใช้คีย์เวิร์ด extends ดังตัวอย่าง +จะสมมติว่าบันทึกเป็นไฟล์ test.js โดยมีโครงสร้างโปรเจคดังนี้ ```js -class Calculation { - constructor (a, b){ - this.a = a; - this.b = b; - } - multiply(){ - return this.a * this.b; - } -} - -class Division extends Calculation { // Division สืบทอดมาจาก Calculation - constructor (a, b){ - super(a, b); // เรียกใช้คอนสตรัคเตอร์ของ Calculation - - // สามารถกำหนดค่าให้กับ this.a และ this.b ที่อยู่ในคลาสแม่ได้โดยตรง - // แต่การทำเช่นนี้จะไม่ปลอดภัย - // this.a = a; // ไม่ควรทำ - // this.b = b; // ไม่ควรทำ - } - - divide(){ - return this.a / this.b; - } -} +C:\ES6> + |-- test.js ``` -ในตัวอย่างดังกล่าว คลาส Division จะสืบทอดสมาชิก (พร็อพเพอร์ตี้) จากคลาส Calculation ได้แก่ a, b และ multiply โดยเราสามารถเข้าถึงพร็อพเพอร์ตี้เหล่านี้ได้ (ในตัวอย่างถัดไป) - -*** ทั้งนี้ในจาวาสคริปต์จะมีเงื่อนไขว่า คอนสตรัคเตอร์ของคลาสลูกต้องเรียก super() ด้วยเสมอ มิฉะนั้นจะเกิด error - -```js -let div = new Division(20,10); - -console.log(div.multiply()); // 200 -console.log(div.divide()); // 2 -console.log(div.a, div.b); // 20 10 (ไม่ควรเข้าถึงข้อมูลอ็อบเจ็กต์โดยตรง ด้วยวิธีนี้) +รันไฟล์ test.js ผ่านทาง Node.js ด้วยความสั่งต่อไปนี้ ตามรูป -console.log(div instanceof Division); // true -console.log(div instanceof Calculation); // true -console.log(div instanceof Object); // true -``` -ให้สังเกต ตอนสร้างอ็อบเจ็กต์ด้วยประโยค new Division(20,10); นอกจากเรียกคอนสตรัคเตอร์ของตัวเองแล้ว (Division) มันยังเรียกของคลาสแม่ด้วยประโยค super(a, b); ซึ่งจะหมายความว่าให้ส่ง 20 กับ 10 ไปให้คอนสตรัคเตอร์ของ Calculation เพื่อกำหนดค่าให้กับ this.a และ this.b ตามลำดับ +![node.js es6 es7](images/chap01/node.js_es6_es7.png) -#### Method overriding -คลาสลูกที่สืบทอดมาจากคลาสแม่ เมธอดของลูกสามารถโอเวอร์ไรด์ (Override) เมธอดของแม่ได้ด้วย และถ้าเมธอดของคลาสลูกจะเรียกเมธอดของคลาสแม่ (ที่ชื่อซ้ำกัน) ก็ให้เรียกผ่าน super แทน ตัวอย่าง +## ทวน ES5 (มาตรฐานเก่า) +## แนะนำ ES6 -```js -class Calculation { - constructor (a, b){ - this.a = a; - this.b = b; - } - multiply(){ - return this.a * this.b; - } -} - -class Multiplying extends Calculation { - constructor (a, b){ - super(a, b); - } - multiply(){ // โอเวอร์ไรด์เมธอด multiply() ของคลาสแม่ - return "The result is " + super.multiply(); - } -} - -let m = new Multiplying(20,10); -console.log(m.multiply()); // "The result is 200" -``` +เนื้อหาบทที่ 2 และ 3 ขอลบนะครับ ไม่สามารถนำเนื้อหาออกมาได้เพราะติดลิขสิทธิ์ แต่ตัวอย่างโค้ดสามารถแยกออกให้ดูได้ทีนี้ครับ -(บทนี้ ยังไม่เสร็จดีครับ) +[ตัวอย่างโค้ด](https://github.com/adminho/javascript/tree/master/examples_book) -### 3.7 Collection -### 3.8 Iterator กับ Generator -### 3.9 Meta Programming -### 3.10 Module -### 3.11 อื่นๆ +[อ่านเพิ่มได้ในหนังสือ]( https://www.se-ed.com/product/พัฒนาเว็บแอปพลิเคชั่นด้วย-JavaScript.aspx?no=9786160825394) -## บทที่ 4 แนะนำ ES7 +## แนะนำ ES7 หัวข้อต่อไปนี้จะแสดงฟีเจอร์ใหม่ที่เพิ่มเข้ามาใน ES7 (ECMAScript 2016) รวมทั้งที่เปลี่ยนแปลงไปจาก ES6 ซึ่งมันเปลี่ยนเล็กนิดเดียวเอง @@ -1295,13 +828,6 @@ console.log(uint8.includes(5)); // true console.log(uint8.includes(10)); // false ``` -```js -หมายเหตุ โอเปอเรเตอร์ ** ตามสเปค ES7 ผมยังหาจาวาสคริปต์เอ็นจิ้นรองรับการรันเทสไม่ได้เลย (เศร้าจัง) -สรุปซอร์สโค้ดที่เห็นในตัวอย่างที่ผ่านมา ขาดการทดสอบจริงจัง -ดังนั้นถ้าในอนาคตสามารถทดสอบได้ เดี่ยวมาปรับแก้เนื้อหาใหม่ -ตอนนี้เอาคอนเซปท์ให้เห็นไปก่อนแล้วกันเนอะ! -``` - ### สิ่งที่เปลี่ยนแปลงไปของ ES7 เมื่อเทียบกับ ES6 (นิดเดียวเอง) หัวข้อก่อนหน้านี้ได้กล่าวถึงฟีเจอร์ที่เพิ่มมาใหม่ใน ES7 แต่หัวข้อนี้จะกล่าวถึงฟีเจอร์ที่เปลี่ยนไปจาก ES6 ดังนี้ @@ -1314,19 +840,43 @@ function * generator() {} let iterator = new generator(); // throws "TypeError: f is not a constructor" ``` -## บทที่ 5 แนะนำ ES8 +## แนะนำ ES8 + +สิ่งที่คาดว่าจะเพิ่มเข้ามาใน ES8 (ECMAScript 2017) + +* Object.entries() กับ Object.values() +* padStart() กับ padEnd() +* Object.getOwnPropertyDescriptors() +* การใช้คอมม่า (,) ต่อท้ายในพารามิเตอร์ของฟังก์ชั่น ,ตอนเรียกใช้งานฟังก์ชั่น, ในอ็อบเจ็กต์ และอาเรย์ +* Async กับ await + +รายละเอียดหาอ่านเพิ่มได้ ในหนังสือแจกฟรีเล่มนี้นะครับ -สิ่งที่คาดว่าจะเพิ่มเข้ามาใน ES8 (ECMAScript 2017) (มีนิดเดียว) +http://www.ebooks.in.th/ebook/40184/รีวีวฟรีเจอร์ใหม่ในจาวาสคริปต์_(JavaScript)_มาตรฐาน_ES7__ES8__(ECMAScript_2016_กับ_ECMAScript_2017)/ -* Object.values() -* Object.entries() +![es7 es8](images/chap05/cover_ES7_ES8.png) + +## แนะนำ ES9 และ ES10 + +(รอก่อน) ## อ้างอิง * [1] หนังสือ “พัฒนาเว็บแอปพลิเคชั่นด้วย JavaScript” จะอธิบายถึงมาตรฐานตัวใหม่ ECMAScript 2015 หรือเรียกสั้น ๆ ว่า “ES6” หรือ “ES6 Harmony” โดยเล่มนี้ตีพิมพ์และจัดจำหน่ายโดยซีเอ็ด * [2] https://developer.mozilla.org/en-US/docs/Web/JavaScript/ * [3] https://github.com/nzakas/understandinges6/blob/master/manuscript/B-ECMAScript-7.md -* [4] https://tc39.github.io/ecma262/2016/ +* [4] http://www.ecma-international.org/ecma-262/7.0/ +* [5] https://tc39.github.io/ecma262/ +* [6] https://github.com/google/traceur-compiler/wiki/Getting-Started +* [7] https://github.com/babel/babel-standalone +* [8] http://exploringjs.com/es6.html +* [9] https://leanpub.com/exploring-es2016-es2017/read +* [10] https://leanpub.com/setting-up-es6/read#sec_es6-repls +* [11] https://leanpub.com/ecmascript2015es6guide/read +* [12] https://leanpub.com/understandinges6/read +* [13] https://github.com/nzakas/understandinges6/tree/master/manuscript +* [14] https://github.com/sirisian/ecmascript-types +* [15] http://exploringjs.com/es2016-es2017/ ## ทิ้งท้าย @@ -1334,8 +884,6 @@ let iterator = new generator(); // throws "TypeError: f is not a constructor" ด้วยเหตุนี้ .... * เนื้อหาทั้งหมดต่อไปนี้ จะเหมือนเป็น**ภาคต่อ**จากหนังสือดังกล่าว -* จะทบทวนจาวาสคริปต์ตามมาตรฐานเก่า ES5 นิดหน่อย -* จะเป็นการพาทัวร์ภาษาจาวาสคริปต์ (JavaScript) ยุคสมัยใหม่ตามมาตรฐาน ES6 คร่าวๆ ทวนเฉยๆ ไม่ลงรายละเอียดลึก * จะพูดถึงภาษาจาวาสคริปต์ (JavaScript) ยุคสมัยใหม่ตามมาตรฐาน ES7, ES8 (ไม่มีในหนังสือ) * รวมทั้งเพิ่มเนื้อหาที่ไม่อยู่ในหนังสือ (คือตอนแต่งหนังสือ เทคโนโลยีต่างๆ ยังไม่อื้ออำนวย ผมเลยไม่กล้าเขียนลงไปครับ) * **ทั้งนี้เนื้อหาจะต่างจากหนังสือข้างต้น ไม่เหมือนกันเท่าไร** @@ -1354,9 +902,9 @@ let iterator = new generator(); // throws "TypeError: f is not a constructor" ## สำหรับผู้ที่สนใจหนังสือเล่มนี้ -หนังสือเล่มแรกในประเทศไทยที่กล่าวถึงจาวาสคริปต์มาตรฐานใหม่เล่มนี้ พิมพ์ครั้งที่สองแล้วนะครับ มีการปรับปรุงแก้ไขคำผิดไป **แต่ทว่าตีพิม์จำนวนจำกัด** มีขายบางแห่งเท่านั้น +หนังสือ __ภาษาไทยเล่มแรก__ ที่กล่าวถึงจาวาสคริปต์มาตรฐานใหม่ ES6 **ตอนนี้ไม่ตีพิมพ์ซ้ำอีกแล้ว** ยังมีขายบางแห่งเท่านั้น ควรเช็คอีกที -![cover](images/cover_big5.png) +![cover](images/cover_big.jpg) * [ศูนย์หนังสือจุฬา]( http://www.chulabook.com/description.asp?barcode=9786160825394) * [ร้านนายอินทร์](https://www.naiin.com/product/detail/191081/) @@ -1365,3 +913,9 @@ let iterator = new generator(); // throws "TypeError: f is not a constructor" * [ผ่านฟ้าบุ๊คเซ็นเตอร์] (http://www.phanpha.com/item/พัฒนาเว็บแอปพลิเคชั่นด้วย-javascript) * [ซีเอ็ดบางสาขา]( https://www.se-ed.com/product/พัฒนาเว็บแอปพลิเคชั่นด้วย-JavaScript.aspx?no=9786160825394) * และร้านหนังสืออื่น ๆ ที่ไม่ได้กล่าว + +เล่มใหม่เนื้อหาอัปเดต เป็นจาวาสคริปต์ตั้งแต่ ES6 เป็นต้นไป (ล่าสุดเนื้อหาถึง ES14) เนื้อหาเกือบ 700 กว่าหน้า + +![cover](images/cover_new.png) + +[สั่งซ์้อได้ที่เว็บ MEB (ขายเป็นอีบุ๊กเท่านั้น)](https://www.mebmarket.com/web/index.php?action=BookDetails&data=YToyOntzOjc6InVzZXJfaWQiO3M6NzoiMTcyNTQ4MyI7czo3OiJib29rX2lkIjtzOjY6IjE1Njg1NCI7fQ) diff --git a/examples/budget_thailand/fiscal_year_2024.html b/examples/budget_thailand/fiscal_year_2024.html new file mode 100644 index 0000000..aab1c38 --- /dev/null +++ b/examples/budget_thailand/fiscal_year_2024.html @@ -0,0 +1,162 @@ + + + + + The Budget of Thailand 2024 + + + + + + +

ผ่างบประมาณของประเทศไทยปี 2567

+
+
+ +
+ + + +
+

โปรดติดตามแฟนเพจ https://www.facebook.com/programmerthai +

+ + \ No newline at end of file diff --git a/examples/calendar/README.md b/examples/calendar/README.md new file mode 100644 index 0000000..ce03bbd --- /dev/null +++ b/examples/calendar/README.md @@ -0,0 +1,5 @@ +# Calendar in hex, decimal and binary + +__I borrowed some code from__ + +* http://www.w3schools.com/howto/howto_css_calendar.asp diff --git a/examples/calendar/css/calendar.css b/examples/calendar/css/calendar.css new file mode 100644 index 0000000..3b69462 --- /dev/null +++ b/examples/calendar/css/calendar.css @@ -0,0 +1,82 @@ +/* + +
+
+

เป็นตัวอย่างเว็บอย่างง่ายๆ เพื่อแสดงวิธีใช้งาน JavaScript ตามมาตรฐานใหม่ ES6 (ใช้ Babel)

+

*** โค้ดนี้ผ่านการลองทดทดสอบบน Firefox, Google เท่านั้นนะครับ

+
+
+
+
+
+ เดือน + + ปี ค.ศ. + + ระบบตัวเลข + +
+
+
+
+
+
+
+ + + + + + + +
+
+

โค้ดตัวอย่างนี้ จะมีปัญหาเวลาเปิดด้วย Google Chrome

+

ถ้าเห็นว่าไม่ทำงาน ก็รบกวนดูลิงค์ข้างล่างนี้นะครับ มีวิธีแก้ เวลาเปิดด้วย Google Chrome

+

(หัวข้อ Cross-origin resource sharing)

+
+ + + diff --git a/examples/calendar/js/addEventToBtn.js b/examples/calendar/js/addEventToBtn.js new file mode 100644 index 0000000..605a470 --- /dev/null +++ b/examples/calendar/js/addEventToBtn.js @@ -0,0 +1,46 @@ + +let default_year = new Date().getFullYear(); +let default_num_sym = 10; + +let calendar = new MyCalendar("calendar_one"); +calendar.display(); + +let monthList = $('#monthList'); +let yearList = $( "#yearList"); +let systemList = $("#sytemNumList"); + +// set dropdow list for a month +let monthArray = ["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"]; +for( let i = 0; i', { + value: i, + text: monthArray[i] + })); +} +monthList.change(function() { + calendar.setMonth(this.value); + calendar.display(); +}); +monthList.val(calendar.getDate().getMonth()); + +// set dropdow list for a year +for( let y=1950; y<3000; y++){ + yearList.append($('