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:
- Default Parameters in ES6
- Template Literals in ES6
- Multi-line String in ES6
- Destructuring Assignment in ES6
- Enhanced Object Literals in ES6
- Arrow Function in ES6
- Promises in ES6
- Block-Scoped Constructs Let and Cont
- Classes in ES6
- 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.

![[React JS] Sức mạnh của react-query](/_next/image?url=https%3A%2F%2Fviblo.asia%2Fog-facebook-3.png&w=640&q=75)



