Pengenalan Ringkas Javascript ES6

Ini adalah pengenalan ringkas antara asas 'next-gen' javascript(js). Syntax next-gen ini kalau dapat dikuasai sangatlah membantu terutamanya bila kita guna framework / library js modern macam ReactJ, VueJS atau AngularJS.

let & const

Baca lanjut mengenai let : let
Baca lanjut mengenai let const : const

let & const asasnya untuk menggantikan cara kita declare variable dalam js. Gantikan let dengan var dan guna const kalau kita tak plan lansung untuk assign semula variable tersebut. Const = constant kan?

contoh:

// es5
var nama = "Ashraf Pandang Tak Jemu"
var pi = 3.14

// es6
let nama = "Ashraf Pandang Tak Jemu"
const pi = 3.14

ES6 Arrow Functions

Bacaan lanjut : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Arrow functions (anak panah => ) adalah cara lain untuk kita buat satu function dalam js. Syntax yang lebih pendek dan juga memberi beberapa kelebihan bila kita nak kekalkan skop this dalam js. (rujuk here).

Biasanya function di js ditulis begini:

function panggilSaya(nama) {
  console.log(nama)
}

atau begini kan?

const panggilSaya = function(nama) {
  console.log(nama)
}

Dengan Arrow functions ditulis begini::

const panggilSaya = nama => {
  console.log(nama)
}

**Penting: **

Jika function itu tak ada arguments, function declaration perlu disertakan kurungan parentheses '()'

const panggilSaya = () => {
  console.log("Sayang!")
}

Kalau ada hanya satu (1) argument, tak perlu disertakan kurungan:

const panggilSaya = nama => {
  console.log(nama)
}

Kalau kita nak return value saja, boleh guna shortcut:

const returnNama = nama => nama

Syntax atas ni samalah dengan yang bawah tapi shortcut

const returnNama = nama => {
  return nama
}

Exports & Imports

Dalam projek js moden, kod js selalunya diasingkan menjadi modul supaya setiap fail atau modul lebih mudah untuk sela dan setiap modul lebih fokus mengenai fungsi modul tersebut. Setiap file atau module mempunyai skop tersendiri. misalnya fail a.js dan file b.js. variable dari file a.js tidak akan boleh di akses secara terus di file b.js.

Untuk membolehkan content dari file a.js diakses oleh file b.js, file a.js perlulah di'export' untuk membolehkan contentnya diakses terlebih dahulan dan file b.js perlu import file a.js untuk menggunakannya.

terdapat 2 jenis exports.

  1. default (unnamed)
export default ...;
  1. named exports
export const dataRandom = ...;

Untuk import default exports

import namaPilihanAnda from "./path/to/file.js"

Ya, namaPilihanAnda adalah pilihan hati anda. pilih lah apa yg anda suka. haha.

Untuk import Named exports pula perlu diimport dengan namanya yg ditetapkan:

import { dataRandom } from "./path/to/file.js"

Satu file hanya boleh ada 1 default exports dan untuk named exports pula unlimited. Export la berapa banyak yang anda suka Ya boleh campur 1 default exports dan beberapa banyak pun named export pun yang anda suka. Dah bagi tahu ni.

Semasa import named exports anda boleh import semua named exports sekali gus seperti ini:

import * as ObjSukaHatiKau from "./path/to/file.js"

ObjSukaHatiKau ada lah js object. Ya nama dia suka hati kau nak letak apa. tanya lagi. choi. Nak akses object? ObjSukaHatiKau.dataRandom.

Classes

Classes adalah 1 ciri baru yg dibawa 'next-gen' JavaScript yang secara asasnya untuk menggantikan constructor function dan prototypes. Kita boleh define blueprint untuk objek JavaScript dengan class.

Contoh:

class Person {
  constructor() {
    this.name = "Max"
  }
}

const person = new Person()
console.log(person.name) // prints 'Max'

Contoh diatas bukan class, property class itu juga turut ditakrifkan (defined) iaitu 'name'. Untuk pengetahuan anda, this.name = name adalah syntax 'lama' untuk kita define properties. Di 'next-gen' JavaScript, Kita bole gunakan syntax 'baharu' yang lebih senang dan mudah (ya tanpa perlu mula dengan constructor) seperti dibawah:

class Person {
  name = "Max"
}

const person = new Person()
console.log(person.name) // prints 'Max'

Method juga boleh di'defined' begini dengan syntax baharu:

class Person {
  name = "Max"
  printMyName() {
    console.log(this.name) // 'this' perlu untuk merujuk class!
  }
}

const person = new Person()
person.printMyName()

atau macam ni pun boleh (arrow function):

class Person {
  name = "Max"
  printMyName = () => {
    console.log(this.name)
  }
}

const person = new Person()
person.printMyName()

Cara kedua memiliki kelebihan yang sama pada semua arrow function. Keyword this tidak menukar rujukannya / tidak 'bind' di mana-mana.

Penggunaan inheritance boleh dibuat dengan class:

class Human {
  species = "human"
}

class Person extends Human {
  name = "Max"
  printMyName = () => {
    console.log(this.name)
  }
}

const person = new Person()
person.printMyName()
console.log(person.species) // prints 'human'

Spread & Rest Operator

Operator spread & operator Rest menggunakan syntax yang sama: ...

Ya, tiga dot tu operatornya. Cara penggunaannya yang menentukan ia adalah spread atau rest.

Menggunakan Operator Spread:

Operator spread membolehkan kita untuk menarik keluar atau salin elemen dari Array atau properties dari objek .

Contohnya penggunaan spread pada array:

const arrayLama = [1, 2, 3]
const arrayBaru = [...arrayLama, 4, 5] // Sekarang [1, 2, 3, 4, 5];

Contoh penggunaan spread pada objek:

const objekLama = {
  nama: "Ashraf",
}

const objekBaru = {
  ...objekLama,
  umur: 22,
}

objekBaru akan jadi:

    {
      nama: 'Max',
      umur: 28
    }

Operator spread sangat berguna jika kita nak klon array & objek sebab array & objek adalah jenis reference types (and not primitives).

Menyalin variable pada primitive type:

let nama = "Ashraf";
let namaBaru = nama;

// tukar nama
namaBaru = "Hensem";

console.log(namaBaru); // "Hensem"
console.log(nama); // "Ashraf"
Variable asal tidak berubah

Menyalin variable pada reference type:

let bulan = ['jan', 'feb', 'mar'];

let bulanBaru = bulan;

bulanBaru = "tukar ini bukan lagi array pun boleh";

console.log(bulan); // "tukar ini bukan lagi array pun boleh"
console.log(bulanBaru); // "tukar ini bukan lagi array pun boleh"
Variable asal turut berubah sebab variable baru hanya reference kepada variable lama

Jadi cara untuk salin variable reference type dengan selamat adalah dengan menggunakan spread operator.

let bulan = ['jan', 'feb', 'mar'];

let bulanBaru = [...bulan]; // cara ES6 dengan spread operator
// let bulanBaru = bulan.slice() // cara ES5

bulanBaru = "tukar ini bukan lagi array pun boleh";

console.log(bulan); // ['jan', 'feb', 'mar'];
console.log(bulanBaru); // "tukar ini bukan lagi array pun boleh"
Cara selamat untuk klon reference type variab;e

Destructuring

Menggunakan 'Destructuring' memudahkan kita untuk assign value dari array kepada variable.

Contoh menggunakan destructuring dengan array:

const array = [1, 2, 3]
const [a, b] = array

console.log(a) // prints 1
console.log(b) // prints 2
console.log(array) // prints [1, 2, 3]

Contoh menggunakan destructuring dengan objek:

const objOrang = {
  nama: "Ashraf",
  umur: 22,
}

const { nama } = objOrang;

console.log(nama) // prints 'Ashraf'
console.log(umur) // prints undefined
console.log(objOrang) // prints {nama: 'Ashraf', umur: 22}

Destructuring sangat berguna ketika kita melakukan sesuatu dengan argument / parameter function. Contoh function ini:

const printNama = objOrang => {
  console.log(objOrang.nama)
}

printNama({ nama: "Ashraf", umur: 22 }) // prints 'Ashraf'

Disini kita cuma nak print nama saja tapi kita pass keseluruhan objek kepada function ni. Ya tiada masalah pun, tapi cara ini memaksa kita untuk panggil objOrang.nama di dalam function ni. Kita boleh kecilkan lagi skop function ni dengan desctructuring. Sebagai contoh:

const printNama = ({ nama }) => {
  console.log(nama)
}

printNama({ nama: "Ashraf", umur: 22 }) // prints 'Ashraf')

Lihat, keputusannya sama tapi kita dah berjaya memendekkan kod kita. Menggunakan destructuring, Β kita dengan mudah dapat menarik keluar property nama dan simpan ke dalam variable / argument bernama nama yang kemudiannya kita gunakan di dalam body function tersebut.