[JS6] มาลองเล่น ECMAScript 6

หลังจาก Blog ตอนก่อน ก้าวเข้าสู่โลกของ Frontend เริ่มเล่น Nodejs ลงเพื่อให้ได้ตัว NPM มานะครับ คราวนี้ผมลองศึกษาตัว ECMAScript 6 โดยดูจาก GitHub ECMAScript 6 Tutorial ใส่ตัวอย่างจาก Git เข้ายก Mortgage Calculator ที่มี amortization และเราลองทำตามขั้นตอนที่ผู้เขียนแนะนำครับ

ECMAScript 6 คือ JavaScript แหละ ที่ปรับเปลี่ยนให้ตามยุคสมัยมากขึ้น

กลับมาลองดูของเดิมบ้าง โดยผมอาจจะมีแทรกของใหม่ เข้าไป
- Use Strict

อันนี้มีมาตั้งแต่ ECMAScript 5 แล้ว แต่ถ้าใครมาจากภาษาที่แบบเคร่งอยากให้เปิดไว้ เช่น

  • มันจะได้เตือน Error มา และเขียน Code ได้ดีขึ้นด้วย
// Non-strict mode
function divide(x, y) {
 return x / y;
}
console.log(divide(10, 0)); // Output: Infinity (no error thrown)
// Strict mode
"use strict";
function divideStrict(x, y) {
 return x / y;
}
console.log(divideStrict(10, 0)); // Output: Infinity (TypeError: Division by zero)
  • Optimization Enhancements มันไม่จำเป็นต้องมาตรวจ Type ตอน Runtime
'use strict';  //unnecessary runtime checks / behaviors related ถูกตัดออกไป 
function sum(a, b) {
 return a + b;
}
sum(10, 20);
  • Undeclared Variables - เมื่อก่อน javascript มันประกาศตัวแปรลอยได้เลยไง อันนี้แหละ ผมไม่ชอบ ตัว 'use strict' มาช่วยบังคับตรงนี้ จะได้ throw a ReferenceError ออกมา

จริงๆ เรื่องนี้มีอีกหลายอันเลย เรื่อง use strict แต่เอาเท่านี้ก่อน

JavaScript ใช้ reference pointer - เราไปยุ่งตรงๆไม่ได้ แต่มันอยู่เบื้องหลังให้เราใช้งาน https://stackoverflow.com/a/17382443/20000255

- การประกาศตัวแปร

ของเดิม var แล้วจะทำอะไรก็ได้ แต่ปัญหาของมัน คือ ตัวแปรประเภท var มี Scope เป็น Global ครับ

  • Code ตัวอย่าง
var num = 10

console.log('before num = '+ num)

if (num == 10){
    var num = 26
    console.log('inside if block num = '+ num)
}

console.log('after num = '+ num)
  • ผลลัพธ์
before num = 10
inside if block num = 26 //ใน IF มีการแก้ค่า ถ้าเว็บใหญ่นี้หากันตายเลย
after num = 26

ของใหม่เพิ่ม let / const เข้ามา

let เหมือน var แต่มี Scope อยู่ใน Block ของการทำงานครับ จะเป็นโมดูล หรือ Function

  • Code ตัวอย่าง
let num = 10

console.log('before num = '+ num)

if (num == 10){
    let num = 26
    console.log('inside if block num = '+ num)
}

console.log('after num = '+ num)
  • ผลลัพธ์
before num = 10
inside if block num = 26 //ตัวแปร ใน IF กับนอก IF เป็นคนะตัว
after num = 10

อีกตัวเป็น const เก็บค่างคงที ห้ามแก้ไขหลังประกาศ

  • Code ตัวอย่าง
const num = 10

console.log('before num = '+ num)

if (num == 10){
    num = 26
    console.log('inside if block num = '+ num)
}

console.log('after num = '+ num)
  • ผลลัพธ์ - ระบบมันด่าเราครับ ดังนี้
- Data Type

ใหม่ Destructoring  - ดึงข้อมูลบางส่วนมาจาก Array

ใหม่  template string แทนที่เราต้องเอาตัวแปร + เชื่อม String ต่อกัน ยิ่งข้อความยาวๆ ผิดที่งงเลย เรามาทำเป็น Template แล้วใช้งานมันแทน

  • Code ตัวอย่าง
const message = [
     'Chatri',
     'Ngambenchawong',
     'Ping'
]
const [first,,third] = message
console.log(- Old way)
console.log('Hi, My name is '+ first + ' ('+third+')' )
console.log(- Template String)
console.log(`Hi, My name is ${first} (${third})`)
  • สำหรับ Template String ข้อความ Template ต้องอยู่ในตัว ` (Grave ที่ใช้เปลี่ยนภาษาครับ) อ้างถึงตัวแปรโดยใช้ ${ชื่อตัวแปร} ครับ โดยผลลัพธ์ที่ได้ตามนี้ครับ
- Old way
Hi, My name is Chatri (Ping)
- Template String
Hi, My name is Chatri (Ping)
- function

เดิม วางที่ไหนก็ได้ ผลลัพธ์เท่ากัน

  • Code ตัวอย่าง
function add (x, y){
    return x + y
}
console.log('Result from add function is ' + add(5,3))

console.log('Result from minus function is ' + add(5,3))
function minus (x, y){
    return x + y
}
  • ผลลัพธ์
Result from add function is 8
Result from minus function is 8

ใหม่ Arrow Function

Arrow Function บังคับให้ประกาศก่อนใช้งานครับ สังเกตุดีๆมีคำว่า Const

  • Code ตัวอย่าง
const addArrowStype = (x,y) => x + y
console.log('Result from add(ArrowStype) function is ' + addArrowStype(5,3))

console.log('Result from minus(ArrowStype) function is ' + minusArrowStype(5,3))
const minusArrowStype = (x,y) => x + y
  • ผลลัพธ์ ถ้าลองมาดูผลลัพธ์ที่ได้ อันแรกไม่มีปัญหา แต่ Function ที่ minusArrowStype ดันมาเรียกใช้ก่ออนประกาศ โดนโปรแกรมด่าครับ

ถ้า Arrow Function มีหลายบรรทัดหละ ใส่ { } ได้

  • Code ตัวอย่าง
const mulArrowStype = (x,y) => { 
    let z = x * y
    return z
}

console.log('Result from add(ArrowStype) function is ' + mulArrowStype(5,3))
  • ถ้าลองมาดูผลลัพธ์ที่ได้
Result from add(ArrowStype) function is 15
- Structure กับ this

มาลอง Function  แบบเดิมๆกัน

  • Code ตัวอย่าง
const obj = {
    x: 26,
    y: 28,
    sum: function () {
        return this.x + this.y
    }
}

console.log(obj.sum())
  • Note: Code ข้างบนนี้ทำงานได้ครับ โดยได้ผลลัพธ์เท่ากับ 54 แต่ถ้ามาลองกับ Arrow Function หละ
const obj1 = {
    x: 26,
    y: 28,
    sum: () => {
        return this.x + this.y
    }
}

console.log(obj1.sum())
  • ผลลัพธ์ที่ได้ คือ NaN เพราะ ตอนนี้ Arrow Function ยังไม่รู้จักกับ this ครับ
- ระวัง side effect ของ Function

ระวัง side effect - ค่าตัวแปรที่อยู่นอก เมื่อเข้าไปใน Function แล้วถูกแก้ไขค่า ถ้าเป็นฝั่ง Java, C# โยน Object เข้าไป แต่มันส่ง Reference เข้าไป เวลาแก้ไขต้องระวังด้วย

  • Code ตัวอย่าง
let x = 0
console.log('Intial')
console.log(x)
function addSideEffect(a){
    console.log('In Function')
    x = x + a
    console.log(x)
}

addSideEffect(15)
console.log('After Call FN addSideEffect')
console.log(x)
  • ผลลัพธ์ที่ได้
Intial
0
In Function
15
After Call FN addSideEffect
15

แล้วเราจะป้องกันอย่างไร ต้องดูก่อนครับ ว่า Function นั้นจำเป็นต้องแก้ค่าของตัวแปรที่ส่งเข้าไปไหม ถ้าไม่ก็สร้างตัวแปรใหม่แยกไปเลย ดังนี้

  • Code ตัวอย่าง
console.log('Prevent FN addSideEffect')
const y = 0
console.log('Intial')
console.log(y)
function preventSideEffect(b){
    console.log('In Function')
    console.log( y + b)
    return y + b
}

const newY = preventSideEffect(15)
console.log('After Call FN preventSideEffect')
console.log(y)
console.log('new y return from FN preventSideEffect')
console.log(newY)
  • ผลลัพธ์ที่ได้
Prevent FN addSideEffect
Intial
0
In Function
15
After Call FN preventSideEffect
0
new y return from FN preventSideEffect
15
- Class

เดิม ประกาศ function เอา ใช้ไปเยอะมันจะงง ดังนี้

  • Code ตัวอย่าง
function Student (firstname, lastname){
 this.firstname = firstname
 this.lastname = lastname

 this.sayhi = function(){
 console.log('Hi, My name is ' + this.firstname + ' ' + this.lastname)
 }
}

//หรือใช้ Prototype
Student.prototype.sayMajor = function(major){
 console.log(this.firstname + ' is study in major Computer Science-'+major)
}

var adminping = new Student('Chatri', 'Ngambenchawong')
adminping.sayhi()
adminping.sayMajor('Software Engineering')
  • ผลลัพธ์ที่ได้
Hi, My name is Chatri Ngambenchawong
Chatri is study in major Computer Science-Software Engineering

ใหม่มี Class ให้เล่นเลย ลองแปลง Code ก่อนหน้ามาเป็น class ครับ

  • Code ตัวอย่าง
class Student {
    constructor(firstname, lastname)
    {
        this.firstname = firstname
        this.lastname = lastname
    }

    //Method
    sayhi (){
        console.log('Hi, My name is ' + this.firstname + ' ' + this.lastname)
    }

    sayMajor (major){
        console.log(this.firstname + ' is study in major Computer Science-'+major)
    }
}

var adminping = new Student('Chatri', 'Ngambenchawong')
adminping.sayhi()
adminping.sayMajor('Software Engineering')
  • ผลลัพธ์ที่ได้
Hi, My name is Chatri Ngambenchawong
Chatri is study in major Computer Science-Software Engineering

เมื่อมันเป็น Class มันมีคุณสมบัติของ OO มาด้วย เช่น Extend ลองดูตัวอย่างครับ โดยผมมาโม Code ก่อนหน้านี้เป็น ดังนี้

  • Code ตัวอย่าง
class Student {
    constructor(firstname, lastname)
    {
        this.firstname = firstname
        this.lastname = lastname
    }

    //Method
    sayhi (){
        console.log('Hi, My name is ' + this.firstname + ' ' + this.lastname)
    }

    sayMajor (major){
        console.log(this.firstname + ' is study in major Computer Science-'+major)
    }
}

class bachelorStudent extends Student {
    constructor(firstname, lastname, interest)
    {
       super(firstname, lastname)
       this.interest = interest
    }

    sayMajor (major){
        console.log(this.firstname + ' is study in major Computer Science-'+major)
    }

    sayInterest(){
        console.log('My Interest is ' + this.interest)
    }
}

var adminping = new Student('Chatri', 'Ngambenchawong')
adminping.sayhi()
adminping.sayMajor('Software Engineering')

var pingkunga = new bachelorStudent('Pingkung', 'Debugging', 'Technology, food mania')
pingkunga.sayhi()
pingkunga.sayMajor('Data Science')
pingkunga.sayInterest()
  • ผลลัพธ์ที่ได้
Hi, My name is Chatri Ngambenchawong
Chatri is study in major Computer Science-Software Engineering

Hi, My name is Pingkung Debugging
Pingkung is study in major Computer Science-Data Science
My Interest is Technology, food mania
- Object

เดิม Object สามารถสร้าง และเพิ่ม Property ระหว่างทำงานได้ ด้วย

  • Code ตัวอย่าง
const Equity = {
    security_id: 26,
    security_code: 'IFEC',
    mtmdate : '2016-09-29',
    mtmprice : 6.23
}
console.log('-------------------------------------------')
var sec_id = Equity.security_id
var sec_code = Equity.security_code
var mtmdate = Equity.mtmdate
var mtmprice = Equity.mtmprice

console.log(sec_id)
console.log(sec_code)
console.log(mtmdate)
console.log(mtmprice)
console.log('-------------------------------------------')
console.log('Add new property')
Equity.par = 1
console.log(Equity.par)
  • ผลลัพธ์ที่ได้
-------------------------------------------
26
IFEC
2016-09-29
6.23
-------------------------------------------
Add new property
1
> Object Destructoring  

Object Destructoring ดึงข้อมูลบางส่วนมาจาก Object ดังนี้

  • ของเดิม Code ตัวอย่าง
//ของเดิม 3 บรรทัด
var sec_id = Equity.security_id
var sec_code = Equity.security_code
var sec_par = Equity.par
  • ของใหม่ - สั้นกระทัดรัด
//ของใหม่สั้นกระทัดรัด
const {security_id, security_code, par} = Equity
> Object.assign

ต้องมาดูก่อนว่าทำไม ถึงมี Method นี้ ขั้นแรกเลย ลองสร้าง Object มาก่อน

const Equity = {
    security_id: 26,
    security_code: 'IFEC',
    mtmdate : '2016-09-29',
    mtmprice : 6.23
}
console.log(Equity)
  • ลองดูผลลัพธ์
{ security_id: 26,
  security_code: 'IFEC',
  mtmdate: '2016-09-29',
  mtmprice: 6.23 }
  • ลองสร้าง Object ใหม่ แล้วเพิ่ม Property ดูครับ
console.log('--------------------------------')
console.log('JavaScript is a reference')
const newEquity = Equity
Equity.regisdate = '1990-04-24'
console.log('After add property')
console.log('- Old Object')
console.log(Equity)
console.log('- New Object')
console.log(newEquity)
  • ลองดูผลลัพธ์ เมื่อเพิ่ม Property ใหม่ มันดันไปแก้ของเก่าด้วย
--------------------------------
JavaScript is a reference
After add property
- Old Object
{ security_id: 26,
  security_code: 'IFEC',
  mtmdate: '2016-09-29',
  mtmprice: 6.23,
  regisdate: '1990-04-24' }
- New Object
{ security_id: 26,
  security_code: 'IFEC',
  mtmdate: '2016-09-29',
  mtmprice: 6.23,
  regisdate: '1990-04-24' }
  • เปลี่ยนมาให้ใช้แบบถึกๆ ยัดตรงๆที่ละตัวเลย
const BruteforceEquity = {}
console.log('- Empty Object')
console.log(BruteforceEquity)
console.log('- Assign Value')
BruteforceEquity.security_id = Equity.security_id
BruteforceEquity.security_code = Equity.security_code
BruteforceEquity.mtmdate = Equity.mtmdate
BruteforceEquity.mtmprice = Equity.mtmprice
console.log('- Print Object')
console.log(Equity)
console.log('- Add new property')
BruteforceEquity.regisdate = '1990-04-24'
console.log('- Old Object')
console.log(Equity)
console.log('- New Object')
console.log(BruteforceEquity)
  • ลองดูผลลัพธ์
--------------------------------
Brute force assign
- Empty Object
{}
- Assign Value
- Print Object
 { security_id: 26,
  security_code: 'IFEC',
  mtmdate: '2016-09-29',
  mtmprice: 6.23 }
- Add new property
- Old Object
 { security_id: 26,
  security_code: 'IFEC',
  mtmdate: '2016-09-29',
  mtmprice: 6.23 }
- New Object
{ security_id: 26,
  security_code: 'IFEC',
  mtmdate: '2016-09-29',
  mtmprice: 6.23,
  regisdate: '1990-04-24' }

ลองใช้ Object.assign

  • Code ตัวอย่าง
console.log('Use Object.assign')
const AssignEquity = Object.assign({}, Equity, { regisdate: '1990-04-24'})
console.log('- Old Object')
console.log(Equity)
console.log('- New Object')
console.log(AssignEquity)
  • ผลลัพธ์ ก่อนอื่น Code สั้นลงเยอะครับ แต่มีข้อจำกัด Object.assign ตัว Web Browser ยังไม่รองรับ ต้องใช้ Tools ไปแปลงเป็น ES5 อีกที
--------------------------------
Use Object.assign
- Old Object
 { security_id: 26,
  security_code: 'IFEC',
  mtmdate: '2016-09-29',
  mtmprice: 6.23 }
- New Object
{ security_id: 26,
  security_code: 'IFEC',
  mtmdate: '2016-09-29',
  mtmprice: 6.23,
  regisdate: '1990-04-24' }

จบไปแล้ว แต่ยังไม่ได้ลองเล่นตัว GitHub ที่แชร์ไว้เลย 5555

lodash.js คือ Library ช่วยให้การเขียน javascript บน browser เข้าใจว่าเป็นพวก Utility

 


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts sent to your email.