Tính năng ES6 trong javascript cần phải biết

Giới thiệu


Bài viết này sẽ giới thiệu nhanh cho bạn về ES6. Nếu bạn chưa biết ES6 là gì, thì nó là một phiên bản mới của Javascript. Nếu bạn là một kỹ sư phần mềm bận rộn (có ai lại không nhỉ), hãy dành thời gian để học 10 tính năng tốt nhất thế hệ tiếp theo của ngôn ngữ lập trình phổ biến nhất trong lập trình Javascript.


Đây là danh sách 10 tính năng tốt nhất của ES6:

  1. Default Parameters in ES6
  2. Template Literals in ES6
  3. Multi-line String in ES6
  4. Destructuring Assignment in ES6
  5. Enhanced Object Literals in ES6
  6. Arrow Function in ES6
  7. Promises in ES6
  8. Block-Scoped Constructs Let and Cont
  9. Classes in ES6
  10. Modules in ES6

1. Default Parameters in ES6


Default paramters trong ES6 giúp chúng ta đặt giá trị mặc định cho tham số


//ES5

var link = function (height, color, url) {
    var height = height || 50
    var color = color || 'red'
    var url = url || 'http://azat.co'
    ...
}

// ES6

const link = function(height = 50, color = 'red', url = 'http://azat.co') {
  ...
}


2. Template Literals in ES6


Sử dụng dấu `` trong ES6 ta có thể sử dụng cú pháp ${tien_bien} bên trong chuỗi


// ES5

var name = 'Your name is ' + first + ' ' + last + '.'
var url = 'http://localhost:3000/api/messages/' + id

// ES6

var name = `Your name is ${first} ${last}.`
var url = `http://localhost:3000/api/messages/${id}`


3. Multi-line String in ES6


Một syntactic sugar khác là chuỗi có nhiều dòng (multi-line string). Trong ES5, chúng ta làm như thế này:


var roadPoem = 'Then took the other, as just as fair,\n\t'
    + 'And having perhaps the better claim\n\t'
    + 'Because it was grassy and wanted wear,\n\t'
    + 'Though as for that the passing there\n\t'
    + 'Had worn them really about the same,\n\t'

var fourAgreements = 'You have the right to be you.\n\
    You can only be you when you do your best.'


Trong ES6, chỉ cần sử dụng dấu backticks:


var roadPoem = `Then took the other, as just as fair,
    And having perhaps the better claim
    Because it was grassy and wanted wear,
    Though as for that the passing there
    Had worn them really about the same,`

var fourAgreements = `You have the right to be you.
    You can only be you when you do your best.`


4. Destructuring Assignment in ES6


Destructuring có thể là một khái niệm khó hiểu, nhưng sài quen rồi cũng dễ hiểu thui :))


Đây là lấy ví dụ lấy thuộc tính trong Object giữa ES5 và ES6

var info= {
   name:"Hoài Nam",
   age:16,
}

// ES5
var name= info.name;
var age= info.age

-------------------

// ES6
const { name, age} = info;


Điều này cũng làm việc với mảng:

const number=[3,2,5,4,2,1,4,5,3];
const [n1,n2,n3,n4] = number;

// bạn có thể dùng để hoán đổi 2 giá trị

let a = 10, b = 30;
[a,b] = [b,a];
console.log(a, b) // a = 30; b = 10


Có lẽ phải mất một khoảng thời gian để sử dụng cú pháp gán destructuring, nhưng nó rất hữu ích.


5. Enhanced Object Literals in ES6


Bây giờ chúng ta đã có thể binding biến vào trong object và nó sẽ nhận luôn tên của biến đó là thuộc tính trong object (điều mà trước đây không thể làm được).


Ví dụ: Tạo một đối tưởng student có 2 trường là name và age;

//ES5
var name = "Phạm Hoài Nam";
var age = 20;
var student = { name: name , age: age };

// ES6
const student= { name , age };


Computed Property Names dịch ra tiếng việt là tính toán các giá trị trên tên của thuộc tính. Đây là một thứ mình thấy rất hay mà ES6 đã update. Bây giờ chúng ta đã có thể làm các phép tính toán, hay biểu thức, để tạo ra thuộc tính cho object ngay trong khi chúng ta khai báo object (trước đây thì phải khai báo xong object mới làm được).


var n = "Name";
var student = {
    ["student" + n] : "Vũ Thanh Tài",
    age: 22
};
console.log(student);
//{studentName: "Vũ Thanh Tài", age: 22}


Khai báo phương thức ngắn gọn hơn

//ES5

var student = {
    name: "Vũ Thanh Tài",
    age: 22,
    getName: function () {
        return this.name;
    },
    getAge: function () {
        return this.age;
    }
};
console.log(student.getName());
//Vũ Thanh Tài
console.log(student.getAge());
//22

-----------------------------------------------------------------------

// ES6
var student = {
    name: "Vũ Thanh Tài",
    age: 22,
    getName() {
        return this.name;
    },
    getAge() {
        return this.age;
    }
};
console.log(student.getName());
//Vũ Thanh Tài
console.log(student.getAge());
//22


6. Arrow Functions in ES6


Arrow Functions cú pháp gắn gọn ()=>{};


// ES5
var multiTestEs5 = function(a, b) {
  return a + b;
};

// ES6
const multiTestEs6 = (a, b) => a + b;


// ES5
var docLogEs5 = function docLog() {
    console.log(document);
};

// ES6
var docLogEs6 = () => { console.log(document); };
docLogEs6();


Khác nhau cơ bản giữa Arrow function và funtion thường:

  • Cú pháp ()=>, function(){}
  • Không có bind this (Tìm hiểu bind)
  • Không bind arguments
  • Không sử dụng hàm contructor
  • Không có cơ chế hoised
  • Không có thuộc tính prototye

7. Promises trong ES6


Promises là một chủ đề gây tranh cãi. Có nhiều phiên bản promise với một chút khác biệt về cú pháp như: Q, Bluebird, deferred.js, avow, jquery deferred là một vài ví dụ. Một số người nói không cần promise và chỉ cần sử dụng async, generators, callbacks, ...May mắn là hiện tại đã có sẵn một chuẩn Promise trong ES6.


Hãy xem xét một ví dụ bất đồng bộ với setTimeout():


setTimeout(function(){
  console.log('Yay!')
}, 1000)


Chúng ta có thể viết lại code trong ES6 với Promise:


var wait1000 =  new Promise(function(resolve, reject) {
  setTimeout(resolve, 1000)
}).then(function() {
  console.log('Yay!')
})


Hoặc với arrow function:


var wait1000 =  new Promise((resolve, reject)=> {
  setTimeout(resolve, 1000)
}).then(()=> {
  console.log('Yay!')
})


Bạn có thể thấy số dòng code tăng từ 3 lên 5 mà không rõ lợi ích của Promise. Đúng vậy. Lợi ích sẽ rõ ràng nếu có nhiều khối lệnh logic lồng trong hàm setTimeout():


setTimeout(function(){
  console.log('Yay!')
  setTimeout(function(){
    console.log('Wheeyee!')
  }, 1000)
}, 1000)


Đoạn code trên có thể viết lại trong ES6 với promise:


var wait1000 =  ()=> new Promise((resolve, reject)=> {setTimeout(resolve, 1000)})

wait1000()
    .then(function() {
        console.log('Yay!')
        return wait1000()
    })
    .then(function() {
        console.log('Wheeyee!')
    });


Bạn vẫn chưa bị thuyết phục rằng Promises tốt hơn các hàm callback thông thường? Tôi cũng vậy. Tôi nghĩ rằng một khi bạn có ý tưởng sử dụng callback và suy nghĩ cẩn thận về chúng thì không cần thêm sự phức tạp của promise.


Tuy nhiên, ES6 có Promises là dành cho những ai yêu thích chúng. Promise có tính năng hữu ích là catch lỗi cho tất cả các hàm callback. Bạn có thể đọc thêm bài viết này để biết nhiều hơn về promise: Giới thiệu Promise trong ES6.

Techmaster cũng có một loạt bài giới thiệu về Promise, qua các ví dụ thực tế. Bạn có thể đọc thêm ở đây: Lập trình Promise với BlueBird qua ví dụ. 


8. Block-Scoped Constructs Let and Const


Let cho phép chúng ta khai báo biến trong phạm vi các khối lệnh. Các khối lệnh được định nghĩa bởi cặp ngoặc nhọn {}. Trong ES5, các khối không giới hạn phạm vi của các biến:


function calculateTotalAmount (vip) {
  var amount = 0
  if (vip) {
    var amount = 1
  }
  { // more crazy blocks!
    var amount = 100
    {
      var amount = 1000
      }
  }  
  return amount
}


Kết quả của đoạn code trên là 1000. Wow! Đó thực sự là bug. Trong ES6, chúng sử dụng let để giới hạn phạm của biến trong các khối lệnh.


function calculateTotalAmount (vip) {
  var amount = 0 // probably should also be let, but you can mix var and let
  if (vip) {
    let amount = 1 // first amount is still 0
  } 
  { // more crazy blocks!
    let amount = 100 // first amount is still 0
    {
      let amount = 1000 // first amount is still 0
      }
  }  
  return amount
}

console.log(calculateTotalAmount(true))


Kết quả của đoạn code trên là 0, bởi vì khối lệnh if sử dụng let. Nếu nó không có từ khóa let (amount = 1) kết quả sẽ là 1.

Khi ES6 giới thiệu từ khóa const, mọi thứ trở lên dễ dàng hơn, nó chỉ là một biến không thay đổi, và cũng giới hạn phạm vi trong các khối lệnh giống như let. Ví dụ, đoạn code bên dưới gồm nhiều hằng số trong các khối lệnh khác nhau:


function calculateTotalAmount (vip) {
  const amount = 0  
  if (vip) {
    const amount = 1 
  } 
  { // more crazy blocks!
    const amount = 100 
    {
      const amount = 1000
      }
  }  
  return amount
}

console.log(calculateTotalAmount(true))


Theo ý kiến của cá nhân tôi, let và const làm cho ngôn ngữ trở lên phức tạp hơn. Không có chúng, chúng ta chỉ có một hành vi, giờ chúng ta phải xem xét nhiều kịch bản hơn.


9. Classes trong ES6


Nếu bạn yêu lập trình hướng đối tượng (OOP), bạn sẽ thích tính năng này. Nó làm cho việc viết class và kế thừa từ chúng dễ dàng như viết một comment trên Facebook.


Tạo và sử dụng class trong ES5 khá đau khổ, bởi vì không có từ khóa class. Ngoài ra, nhiều mẫu (pattern) kế thừa giống như pseudo classical, classical, functional chỉ làm tăng sự nhầm lẫn, giống như thêm dầu vào lửa trong cuộc chiến giữa các quan điểm lập trình JavaScript khác nhau.


Tôi sẽ không cho bạn thấy cách viết một class trong ES5, bởi vì có quá nhiều thứ. Hãy xem một ví dụ về class trong ES6 ngay. Tôi có thể nói với bạn rằng class của ES6 sử dụng prototype, không phải hướng tiếp cận funtion factory. Chúng ta có một class baseModel cái định nghĩa một hàm khởi tạo (constructor) và một phương thức getName():


class baseModel {
    constructor(options = {}, data = []) { // class constructor
        this.name = 'Base'
        this.url = 'http://azat.co/api'
        this.data = data
        this.options = options
    }

    getName() { // class method
        console.log(`Class name: ${this.name}`)
    }
}


Chú ý tôi sử dụng các giá trị tham số mặc định cho options và data. Vì thế tên phương thức không cần có từ khóa function hoặc dấu (:). Một điểm khác biệt lớn nữa là bạn không thể gán thuộc tính this.name theo cách giống với các phương thức. Để thiết lập giá trị của một thuộc tính, đơn giản gán một giá trị trong hàm khởi tạo (constructor).


AccountModel kế thừa từ baseModel với class NAME extends PARENT_NAME:


class AccountModel extends baseModel {
    constructor(options, data) {


Để gọi hàm khởi tạo cha, sử dụng super() với các tham số:

        super({private: true}, ['32113123123', '524214691']) // call the parent method with super
        this.name = 'Account Model'
        this.url +='/accounts/'
    }


Nếu bạn muốn đẹp, bạn có thể thiết lập getter giống như thế này và accountsData sẽ có một thuộc tính:

    get accountsData() { //calculated attribute getter
    // ... make XHR
        return this.data
    }
}


Vậy làm thế nào để sử dụng câu thần chú này? Nó dễ như lừa một đứa trẻ 3 tuổi nghĩ rằng ông già Noel là có thật:

let accounts = new AccountModel(5)
accounts.getName()
console.log('Data is %s', accounts.accountsData)


Kết quả sẽ là:

Class name: Account Model
Data is %s 32113123123,524214691


10. Module


JavaScript cung cấp cơ chế module từ phiên bản ES6 (ES2015) trở đi. Cách sử dụng module trong JavaScript rất đơn giản và hiệu quả.


Lợi ích

  • Dễ bảo trì
  • Tái sử dụng cao
  • Tính đóng gói
  • Quản lý code dễ dàng

Đầu tiên, bạn cần tạo một module. Đây là một file JavaScript được định nghĩa với từ khóa export để đánh dấu các biến, hàm, hoặc lớp mà bạn muốn sử dụng ở ngoài module đó.


Ví dụ: Tạo một file mathModule.js

export function add(x, y) {
 return x + y;
}

export function subtract(x, y) {
 return x - y;
}


Sau khi đã tạo module, bạn có thể sử dụng nó trong file JavaScript khác bằng cách dùng từ khóa import.


Ví dụ: Trong file app.js:

import { add, subtract } from './mathModule.js';

console.log(add(2, 3)); // Kết quả: 5
console.log(subtract(5, 2)); // Kết quả: 3


import as math from './mathModule.js';

console.log(math.add(2, 3)); // Kết quả:  5
console.log(math.subtract(5, 2)); // Kết quả: 3


Lưu ý rằng việc sử dụng module trong JavaScript như trên chỉ hoạt động trên môi trường hỗ trợ ES6 hoặc cao hơn, hoặc trong môi trường Node.js từ phiên bản 13.2.0 trở đi với option --experimental-modules hoặc đặt type là "module" trong file package.json. Trong trình duyệt, bạn cần phải thêm thuộc tính type="module" trong thẻ <script> khi muốn sử dụng module.

quản trị viên

Chia sẻ bài viết:

Tin tức liên quan

[React JS] Sức mạnh của react-query

[React JS] Sức mạnh của react-query

React Query là một thư viện phổ biến được sử dụng để quản lý và lưu trữ dữ liệu bất đồng bộ trong các ứng dụng React. Thư viện cung cấp một cách đơn giản và hiệu quả để lấy dữ liệu, lưu trữ dữ liệu vào bộ nhớ cache và cập nhật dữ liệu trong các thành phần. Điều này giúp dễ dàng xử lý logic liên quan đến dữ liệu mà không cần phải sử dụng các giải pháp phức tạp quản lý trạng thái.

Cách sử dụng Async Await Fetch Axios trong lập trình JavaScript

Cách sử dụng Async Await Fetch Axios trong lập trình JavaScript

Trong lập trình JavaScript, async/await và fetch/axios là những khái niệm quan trọng giúp xử lý các tác vụ bất đồng bộ một cách dễ dàng và hiệu quả. Trên thực tế, chúng đã trở thành tiêu chuẩn cho việc làm việc với API và tương tác với dữ liệu từ máy chủ. Trong bài viết này, chúng ta sẽ khám phá sâu hơn về async/await, fetch, axios và cách chúng hoạt động trong lập trình JavaScript.

Gửi mail trong nodejs với Nodemailer đơn giản trong lập trình Javascript

Gửi mail trong nodejs với Nodemailer đơn giản trong lập trình Javascript

Trong bài viết này mình hướng dẫn chi tiết gửi mail thông qua Nodemailer đơn giản nhất, việc gửi email không chỉ đơn giản là gửi văn bản thông điệp nữa. Email đã trở thành một phần quan trọng của ứng dụng và dịch vụ trực tuyến, từ việc xác nhận tài khoản, thông báo sự kiện cho đến marketing. Trong bài viết này, chúng ta sẽ khám phá cách sử dụng thư viện Nodemailer trong Node.js để dễ dàng gửi email từ ứng dụng của bạn.

Xem thêm...