พื้นฐาน ES2015 (ES6) สำหรับการเขียน JavaScript สมัยใหม่

Nuttavut Thongjor

ยุคของ ES2015 มาถึงแล้ว ผมเชื่อว่าเพื่อนๆหลายคนน่าจะกำลังใช้ ES2015 ในการเขียน JavaScript ปัจจุบันอยู่ สำหรับบทความนี้ผมจะแนะนำการใช้ ES2015 ในแบบฉบับที่เพื่อนๆจะได้พบเห็นในโลกของ JavaScript สมัยใหม่ พร้อมทั้งแนะนำจุดบอดหรือมุมมองที่เพื่อนๆอาจยังไม่เข้าใจหรือใช้ผิดกันอยู่ อย่าเสียเวลาแล้วลุยกันเลย!

ลาก่อน semicolon เพื่อนยาก

สำหรับ ES2015 นั้นไม่มีความจำเป็นที่คุณต้องใส่ semicolon หรือ ; อีกต่อไป ที่ผมพูดว่าไม่ต้องใส่นี้ไม่ได้หมายความว่า JavaScript เป็นภาษาที่สลัด semicolon ทิ้งเสียแล้ว แท้ที่จริงนั้น JavaScript ยังต้องการ semicolon อยู่ เพียงแต่ ES2015 นั้นฉลาดพอที่จะเติม semicolon ให้เราอัตโนมัติ (automatic semicolon insertion) ไร้ซึ่ง semicolon โค๊ดของเราจึงดูสวยขึ้น นี่ไม่ใช่สิ่งมหัศจรรย์ถ้าคุณไปเห็นโค๊ดของไลบรารี่ของใครซักคนในโลก React ที่ไม่ปิดท้ายด้วย ;

JavaScript
1// โค๊ดที่เปลือยเปล่าไร้ semicolon ของฟังก์ชัน applyMiddleware ใน Redux
2export default function applyMiddleware(...middlewares) {
3 return (createStore) => (reducer, initialState, enhancer) => {
4 var store = createStore(reducer, initialState, enhancer)
5 var dispatch = store.dispatch
6 var chain = []
7
8 var middlewareAPI = {
9 getState: store.getState,
10 dispatch: (action) => dispatch(action),
11 }
12 chain = middlewares.map((middleware) => middleware(middlewareAPI))
13 dispatch = compose(...chain)(store.dispatch)
14
15 return {
16 ...store,
17 dispatch,
18 }
19 }
20}

หมายเหตุ: ASI มีมาก่อน ES6 ออก แต่ สมัย ES5 แม้เราจะละ semicolon ออกได้ แต่เราก็จะไม่ทำกันนั่นเพราะเครื่องมือหลายตัวจะทำเอาเจ๊งถ้าเอา semicolon ออก เช่นพวก compressors

การมาของ ES6 มาพร้อมกับเครื่องมือที่ทำให้ความหนักใจของการเอา semicolon ออกลดลง จนเราเริ่มนิยมเอา semicolon ออกสำหรับโค้ด ES6 และยังคง semicolon ไว้สำหรับโค้ด ES5 ครับ

จาก var สู่ let และ const

ผมว่าเพื่อนๆคงเริ่มใช้ทั้ง let และ const กันแล้ว แต่ทราบหรือไม่ว่า let/const นั้นมีขอบเขตการมีตัวตนหรือ scope ที่แตกต่างจาก var กล่าวคือ var นั้นเป็น function-scoped หรือพูดง่ายๆคือเราใช้ var ประกาศตัวแปรตรงจุดไหนก็ตาม แต่เมื่อ JavaScript เริ่มทำงาน การประกาศตัวแปรด้วย var นั้นจะกระดึ๊บๆตัวเองไปอยู่ใกล้กับจุดประกาศฟังก์ชันที่ใกล้ที่สุดหรือที่เราเรียกกันว่า hoisting

JavaScript
1function foo(isValid) {
2 if (isValid) {
3 var x = 1
4 return x
5 }
6
7 return x
8}
9
10// มีค่าเท่ากับ
11function foo(isValid) {
12 var x // ดีดตัวเองมาอยู่ใกล้จุดประกาศฟังก์ชัน
13 if (isValid) {
14 var x = 1
15 return x
16 }
17
18 return x
19}

สำหรับ let และ const นั้นเป็น block-scoped หมายถึงประกาศตัวแปรอยู่ในบลอคไหนก็จะอยู่แค่ในบลอคนั้น ไม่เสนอหน้าดีดตัวเองออกไปใกล้ฟังก์ชันแบบที่ var ทำ

JavaScript
1// พิมพ์ 2 ออกมาทั้งสองครั้ง
2for (var i = 0; i < 2; i++) {
3 // เนื่องจากในจังหวะที่ console.log ทำงาน loop ได้วนไปจนครบแล้ว
4 // ทำให้ในขณะนั้่นค่า i มีค่าเป็น 2
5 // อย่าลืมว่า i ประกาศโดยใช้ var มันจึงผลักตัวเองออกจาก for
6 // หรือพูดง่ายๆคือ i นั้นเป็นตัวแปรตัวเดียวทุกครั้งที่วนลูปก็เพิ่มค่าใส่ตัวแปรเดิม
7 setTimeout(function () {
8 console.log(i)
9 }, 100)
10}
11
12// ผลลัพธ์ได้ 0 และ 1
13// ใช้ let ประกาศตัวแปรทำให้ตัวแปรเป็น block-scoped
14// พูดง่ายๆคือ i จะเกิดขึ้นทุกครั้งที่วนลูป
15// และไม่ซ้ำกับ i ก่อนหน้า
16// เนื่องจากเป็น block-scoped มันจึงมีช่วงชีวิตอยู่แค่ใน {}
17for (let i = 0; i < 2; i++) {
18 setTimeout(function () {
19 console.log(i)
20 }, 100)
21}

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

JavaScript
1let a = 0
2a = 1
3
4const PI = 3.14
5PI = 1 // "PI" is read-only เปลี่ยนค่าไม่ได้อีกแล้วนะ
6
7// obj เก็บ address หรือที่อยู่ของ { a: 1 }
8// เราเปลี่ยน address ไม่ได้ เช่น obj = {} แบบนี้คือเปลี่ยน memory address ทำไม่ได้
9const obj = { a: 1 }
10// แต่การเปลี่ยนค่าภายใน object ไม่ได้ทำให้ memory address เปลี่ยนไป
11obj.a = 2
12console.log(obj) // { a: 2 }

เพื่อนๆที่เคยใช้ Redux จะทราบว่าเรานิยมใช้ switch/case กันใน reducer

JavaScript
1export default (state = initialState, action) => {
2 switch (action.type) {
3 case LOAD_PAGES_SUCCESS:
4 // ลดการเรียกชื่อยาวๆด้วยการประกาศตัวแปรมารองรับ
5 // มั่นใจ 100% ว่า pages นี้ไม่เปลี่ยนแปลงแน่นอนเลยใช้ const ซะเลย
6 const pages = action.result.entities.pages
7 return { ...state, loading: false, items: pages }
8 default:
9 return state
10 }
11}

การเขียนแบบข้างบนฟังดูดีนะครับ เราอาจจะใช้ pages ไปทำสารพัดอย่างก่อน return ออกไปข้างนอก เราเลยสร้างตัวแปรมารองรับมัน แต่ถ้ามี case เพิ่มมาอีกอันแบบนี้หละ?

JavaScript
1export default (state = initialState, action) => {
2 switch (action.type) {
3 case LOAD_PAGES_SUCCESS:
4 const pages = action.result.entities.pages
5 return { ...state, loading: false, items: pages }
6 case LOAD_PAGE_SUCCESS:
7 // ประกาศแบบนี้พังทันที นั่นเป็นเพราะ const เป็น block-scoped
8 // ทำให้ scope ของมันอยู่ภายใต้ {} ของ switch
9 // ใน case ก่อนหน้าเราประกาศ pages ไปแล้วจึงชนกัน
10 // ควรย้ายการประกาศตัวแปรที่ทำซ้อนแบบนี้ออกไปข้างนอก
11 const pages = action.result.entities.pages
12 return { ...state, loading: false, items: [pages[0]] }
13 default:
14 return state
15 }
16}

อย่าคิดว่าเรื่องแบบนี้ไม่เคยเกิดขึ้นนะครับ เพราะมันมีคำถามใน stackoverflow มาแล้ว

ES2015 Module

JavaScript ไม่เคยจัดการโมดูลได้ด้วยตัวเองมาก่อนต้องทำผ่านไลบรารี่อย่าง CommonJS หรือ AMD การมาของ ES2015 มาพร้อมกับการสนับสนุนการทำงานกับโมดูลในตัว ตอนนี้คุณสามารถใช้ ES2015 เพื่อ import/export ของจากไฟล์หนึ่งไปอีกไฟล์หนึ่งได้แล้ว ดังนี้

JavaScript
1// dog.js
2export const DEFAULT_COLOR = 'white'
3export function walk() {
4 console.log('Walking...')
5}
6
7// main.js
8// เลือกนำเข้าเฉพาะ DEFAULT_COLOR
9import { DEFAULT_COLOR } from './dog.js'
10
11// main.js
12// นำเข้าทุกสรรพสิ่งที่ export จาก dog
13// แล้วตั้งชื่อใหม่ให้ว่า lib
14import * as lib from './dog.js'

ถ้าหากโมดูลนั้นมีแค่สิ่งเดียวที่อยาก export ทำได้ดังนี้

JavaScript
1// circle.js
2// สังเกตคำว่า default
3export default class Circle {
4 area() {}
5}
6
7// main.js
8import Circle from './circle.js'

ES2015 module นั้นฉลาด มันมีการตรวจสอบว่าเรา import อะไรเข้ามาบ้าง ถ้าสิ่งไหนไม่ได้ import มันจะไม่นำมารวม ทำให้ไฟล์มีขนาดเล็กกว่าการใช้ CommonJS module เนื่องจาก CommonJS จะ import ทุกสรรพสิ่งที่โมดูลนั้น export ออกมา

JavaScript
1// dog.js
2export const DEFAULT_COLOR = 'white'
3export function walk() {
4 console.log('Walking...')
5}
6
7// main.js
8// เลือกนำเข้าเฉพาะ walk
9import { walk } from './dog.js'
10walk()
11
12// ผลลัพธ์สุดท้ายจะเป็น...
13// สังเกตว่าไม่มี DEFAULT_COLOR ติดมาด้วย
14function walk()
15 console.log('Walking...')
16}
17walk()

เรื่องที่ต้องพึงระวังในการใช้ ES2015 module มีดังนี้

  • ให้ import เฉพาะสิ่งที่จำเป็นต้องใช้จริงๆ
JavaScript
1import _ from 'lodash'
2
3_.map([1, 2, 3], (item) => item * 2)
4
5// จากตัวอย่างนี้เรา import ทุกสิ่งที่ lodash มีมาใส่ตัวแปร _
6// ทั้งๆที่ความจริงเราใช้แค่ map
7// วิธีนี้จะทำให้ไฟล์ผลลัพธ์ของเรามีขนาดใหญ่ เพราะอุดมไปด้วยของที่ไม่ใช้
8// วิธีต่อไปนี้จึงเหมาะสมกว่า
9
10import map from 'lodash/map'
11map([1, 2, 3], (item) => item * 2)
  • นอกจากนี้เพื่อนๆควรตรวจสอบให้แน่ใจว่าไลบรารี่ที่เรานำมาใช้นั้นมีอะไรใน JavaScript ที่ใช้ทดแทนได้หรือไม่ เพื่อจะได้ไม่ทำให้ไฟล์ผลลัพธ์มีขนาดใหญ่จากการใช้ไลบรารี่เหล่านั้น เช่น จากตัวอย่างข้างบนพบว่าสามารถใช้ Array#map ใน JavaScript แทนได้โดยไม่ต้องพึ่ง lodash

  • ตรวจสอบให้แน่ใจว่าขั้นตอนการทำงานของ build tool ของคุณ แอบแปลงโค๊ดคุณเป็น CommonJS ก่อนหรือไม่ ถ้ามีการแปลงนั่นหมายความว่า แม้คุณจะ import บางสิ่งเข้ามา แต่ด้วยความเป็น CommonJS มันจะ import ทุกสรรพสิ่งแม้คุณไม่ต้องการ ตัวอย่างเช่นการใช้ import/export ใน Webpack1

JavaScript
1// ถ้าเพื่อนๆใช้ Webpack1 แม้เราจะเลือกเฉพาะสามตัวนี้ให้ import เข้ามา
2// แต่ด้วยความที่ Webpack1 แปลงเป็น CommonJS ก่อน
3// import ที่เราทำจึงกลายเป็นการ import ทุกสิ่งเข้ามาในไฟล์อยู่ดี
4// เพียงแต่มี map, filter และ reduce ที่เรียกใช้งานได้
5import { map, filter, reduce } from 'lodash'
6
7// ควรเปลี่ยนแปลงเป็นสิ่งนี้
8import map from 'lodash/map'
9import filter from 'lodash/filter'
10import reduce from 'lodash/reduce'

สำหรับเพื่อนๆคนไหนที่เผลอเรียก import _ from 'lodash' ไปแล้วก็ไม่ต้องเสียใจ ผมมี babel plugin ตัวนึงมาฝาก ที่จะทำแปลงการ import ของเพื่อนๆให้เป็นตามที่ผมแนะนำ รออะไรอยู่เล่า โหลดเลยซิ

ที่กล่าวไปทั้งหมดในหัวข้อนี้เป็นการอิมพอร์ตแบบ static แต่ถ้าเราต้องการอิมพอร์ตแบบ dynamic หรืออิมพอร์ตในช่วย runtime หละ? โดยปกติเรามักใช้ require ในการอิมพอร์ตกันใช่ไหมครับ แต่มันมีข้อเสียอยู่คือถ้าอิมพอร์ตไม่สำเร็จเราก็ไม่สามารถจัดการกับข้อผิดพลาดที่เกิดขึ้นได้ ใน ES2015 มีของเล่นใหม่ดังนี้

JavaScript
1System.import('module_name')
2 .then(module => { ... })
3 // จัดการ error ในนี้
4 .catch(error => ...)

Destructuring

Destructuring เป็นฟีเจอร์สำหรับการดึงส่วนของข้อมูลออกมาทำให้เราเขียนโค๊ดได้ง่ายขึ้น

JavaScript
1let person = {
2 age: 24,
3 gender: 'male',
4 name: {
5 firstName: 'firstName',
6 lastName: 'lastName',
7 },
8}
9
10// ถ้าเราต้องการค่าเหล่านี้ออกจากอ็อบเจ็กต์ ต้องมาประกาศตัวแปรแบบนี้
11let age = person.age
12let genger = person.gender
13let name = person.name
14let firstName = name.firstName
15let lastName = name.lastName
16
17// หากใช้ Destructuring จะเหลือแค่นี้
18let { age, gender, name } = person
19let { firstName, lastName } = name
20
21// แต่ในความเป็นจริงแล้ว name เป็นเพียงแค่ทางผ่าน
22// เราไม่ต้องการมัน เราต้องการแค่ firstName และ lastName
23// จึงใช้ Destructuring ซ้อนเข้าไปอีกครั้ง
24// เพียงเท่านี้ตัวแปร name ก็จะไม่เกิดขึ้นมาให้รำคาญใจ
25let {
26 age,
27 gender,
28 name: { firstName, lastName },
29} = person

รู้จักกับ Spread Operator

Spread Operator หรือผมขอเรียกมันง่ายๆว่าเครื่องหมายแตกตัวแล้วกัน เป็นจุดไข่ปลาสามจุด (...) ที่เอาไปวางหน้าอาร์เรย์หรืออ็อบเจ็กต์แล้วมีผลทำให้เครื่องหมายที่ครอบมันอยู่หลุดออก ดูตัวอย่างกันเลย

JavaScript
1let obj1 = { a: 1, b: 2 }
2let obj2 = { c: 3, d: 4 }
3console.log({ ...obj1, ...obj2 }) // {"a":1,"b":2,"c":3,"d":4}
4
5let arr1 = [1, 2, 3]
6let arr2 = [4, 5, 6]
7console.log([...arr1, ...arr2]) // [1,2,3,4,5,6]

สารพัดวิธีแบบใหม่ในการจัดการกับฟังก์ชัน

ES2015 มาพร้อมกับความสามารถในการจัดการฟังก์ชันที่มากขึ้นดังนี้

Arrow Function

จากเดิมที่เราต้องประกาศฟังก์ชันด้วยการใช้คีย์เวิร์ด function ใน ES2015 เราลดรูปการประกาศให้เหลือเพียงลูกศรสองเส้นหรือ fat arrow เหมือนในภาษา CoffeeScript ดังนี้

JavaScript
1// ES5
2function(arguments) {
3
4}
5
6// ES2015
7(arguments) => {
8
9}

Arrow function ไม่ได้ต่างเพียงแค่ไวยากรณ์ที่เปลี่ยนไป แต่ arrow function นั้นยังเข้าถึง this จาก scope ที่ครอบมันอยู่ (Lexical binding) ดังนี้

JavaScript
1function Dog() {
2 this.color = 'white'
3
4 setTimeout(function () {
5 // this ตัวนี้หมายถึง this ใน context ของฟังก์ชันนี้
6 // จึงไม่มีการพิมพ์อะไรออกไป เพราะในฟังก์ชันนี้ this ไม่มีค่าของ color
7 console.log(this.color)
8 }, 100)
9}
10
11new Dog()
12
13// ถ้าต้องการให้พิมพ์ค่า color ออกมาต้องแก้ไขใหม่เป็น
14function Dog() {
15 this.color = 'white'
16 let self = this
17
18 setTimeout(function () {
19 // เรียกผ่านตัวแปร self แทน
20 console.log(self.color)
21 }, 100)
22}
23
24// หรือใช้ arrow function ดังนี้
25function Dog() {
26 this.color = 'white'
27
28 setTimeout(() => {
29 // this ของ arrow function นี้จะหมายถึง
30 // this ตัวบน
31 console.log(this.color)
32 }, 100)
33}

กรณีของ Arrow Function ถ้าตัว body ของฟังก์ชันไม่ครอบด้วย {} และมี statement เดียว จะถือว่าค่านั้นคือค่าที่ return ออกจากฟังก์ชัน

JavaScript
1const fn = () => 3
2
3console.log(fn()) // 3

นอกจากนี้เราสามารถละ () ได้ถ้าพารามิเตอร์นั้นมีเพียงตัวเดียว

JavaScript
1const arr = [1, 2, 3]
2// มีค่าเท่ากับ arr.map((x) => x * x)
3arr.map((x) => x * x)

Default Values

ใน ES5 เราตรวจสอบค่าของพารามิเตอร์ที่ส่งเข้ามาในฟังก์ชัน หากไม่มีการส่งค่าเข้ามาเราอาจตั้งค่าเริ่มต้นของตัวแปรไว้ภายในฟังก์ชัน สำหรับ ES2015 เราสามารถกำหนดค่าเริ่มต้นของพารามิเตอร์ได้เลยด้วยการประกาศไว้ในส่วนประกาศฟังก์ชัน ดังนี้

JavaScript
1// ES5
2function foo(genger) {
3 gender = gender || 'male;
4}
5
6// ES2015
7function foo(gender = 'male') {
8
9}

Named Parameters

ใน ES5 บางครั้งเราส่ง object เข้าไปในฐานะของ options พร้อมทั้งมีการตรวจสอบค่าต่างๆในอ็อบเจ็กต์ ถ้าค่าไหนไม่มีก็จะกำหนดค่าเริ่มต้นให้ ใน ES2015 เราสามารถใช้ destructuring เพื่อทำสิ่งเดียวกันกับที่ทำใน ES5 ได้ดังนี้

JavaScript
1// ES5
2function request(options) {
3 var method = options.method || 'GET'
4 var ssl = options.ssl || false
5 console.log(method)
6}
7request({})
8
9// ES2015
10function request({ method = 'GET', ssl = false }) {
11 console.log(method)
12}
13request({})

นอกจากนี้เราอาจต้องการตรวจสอบค่าที่อ็อบเจ็กต์ที่ส่งเข้ามาก่อนด้วยว่ามีค่าหรือไม่ ถ้าไม่มีให้กำหนดค่าเริ่มต้นเป็น {} ดังนี้

JavaScript
1// ES5
2function request(options) {
3 options = options || {}
4 var method = options.method || 'GET'
5 var ssl = options.ssl || false
6 console.log(method)
7}
8request()
9
10// ES2015
11// กำหนดค่าเริ่มต้นเป็น {}
12function request({ method = 'GET', ssl = false } = {}) {
13 console.log(method)
14}

Rest Parameters

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

JavaScript
1// ไม่ว่าจะส่งตัวเลขเข้ามากี่ตัว ตัวแรกจะเป็น initial
2// ส่วนตัวอื่นจะเก็บอยู่ในอาร์เรย์ชื่อ rest
3function sum(initial, ...rest) {
4 return rest.reduce((prev, cur) => prev + cur, initial)
5}
6
7console.log(sum(10, 1, 2, 3)) // 16

ลดความซ้ำซ้อนด้วยการเขียนให้สั้นลง

ใน ES2015 นั้นเพื่อนๆสามารถลดรูปการประกาศฟังก์ชันในอ็อบเจ็กต์ โดยละคีย์เวิร์ด function ดังนี้

JavaScript
1// ES5
2const obj = {
3 foo: function () {},
4}
5
6// ES2015
7const obj = {
8 foo() {},
9}

นอกจากนี้ถ้า key ของอ็อบเจ็กต์มีชื่อตรงกับตัวแปลที่จะใส่เข้าไปเป็น value แล้ว เพื่อนๆสามารถละรูปได้เช่นกันดังนี้

JavaScript
1// ES5
2const foo = 'foo'
3const bar = 'bar'
4
5const obj = {
6 foo: foo,
7 bar: bar,
8}
9
10// ES2015
11const foo = 'foo'
12const bar = 'bar'
13
14const obj = {
15 foo,
16 bar,
17}

Template String

เมื่อก่อนเราใช้ + เพื่อต่อข้อความ แต่สำหรับ ES2015 นั้น Template String ทำให้การต่อข้อความเป็นเรื่องง่ายขึ้น ใช้ `` ครอบข้อความที่จะทำเป็น template string จากนั้นใช้ ${} สำหรับส่วนที่ต้องการแทรกส่วนของ JavaScript

JavaScript
1const name = 'Nuttavut Thongjor'
2console.log(`สวัสดีชาวโลก ผมชื่อ${name}`)
3
4// นอกจากนี้ template string ยังเอื้อต่อการทำ multiline string ด้วย
5const longString = `
6 Lorem Ipsum is simply dummy text of the printing
7 and typesetting industry.
8 Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
9 when an unknown printer took a galley of type and scrambled
10 it to make a type specimen book.
11`

การใช้งานคลาสใน ES2015

เป็นที่ทราบกันดีว่า JavaScript นั้นเป็นภาษาแบบ prototype-based เราจำลองฟังก์ชันให้เป็นคลาสและสร้างเมธอดผ่าน prototype นั่นเป็นสิ่งที่เราทำมากันเสมอ ใน ES2015 ได้นำการสร้างคลาสเข้ามาสู่ไวยากรณ์ทางภาษา แต่นั่นไม่ได้หมายความว่า prototype-based แบบเดิมๆจะหายไป

JavaScript
1// ประกาศคลาสผ่านคีย์เวิร์ด class
2class Person {
3 constructor(name, age) {
4 this.name = name
5 this.age = age
6 }
7
8 static species = 'Homo sapiens sapiens'
9
10 walk() {
11 console.log("I'm walking...")
12 }
13
14 print() {
15 console.log(`My name is ${this.name}`)
16 console.log(`I'm ${this.age}'`)
17 }
18}
19
20const person = new Person('MyName', 99)
21person.walk() // I'm walking...
22person.print() // My name is MyName \n I'm 99'
23
24// static method เรียกตรงผ่านคลาสได้เลย
25console.log(Person.species) // Homo sapiens sapiens
26
27// สำหรับการทำ inheritance สามารถใช้คีย์เวิร์ด extends ดังนี้
28class Female extends Person {}

Promise

เพื่อไม่ให้เป็นการเขียนบทความทับซ้อน เชิญเพื่อนๆอ่านบทความที่ผมเคยเขียนแล้วในเรื่องกำจัด Callback Hell ด้วย Promise และ Async/Await

Lodash และ ES2015

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

JavaScript
1;[1, 2, 3].includes(1)
2'Hello World'.startsWith('Hello')

บทความนี้ต้องการนำเสนอ ES2015 ที่น้อยที่สุดที่ควรรู้ ความจริงแล้ว ES2015 เป็นเรื่องค่อนข้างใหญ่ มีหลายหัวข้อที่เปิดมิติการเรียนรู้ใหม่ๆในโลก JavaScript เพื่อนๆที่สนใจสามารถอ่านเพิ่มเติมได้ครับ

สารบัญ

สารบัญ

  • ลาก่อน semicolon เพื่อนยาก
  • จาก var สู่ let และ const
  • ES2015 Module
  • Destructuring
  • รู้จักกับ Spread Operator
  • สารพัดวิธีแบบใหม่ในการจัดการกับฟังก์ชัน
  • ลดความซ้ำซ้อนด้วยการเขียนให้สั้นลง
  • Template String
  • การใช้งานคลาสใน ES2015
  • Promise
  • Lodash และ ES2015