Những tính năng mới của ECMAScript 2017 (ES8) trong JavaScript

JavaScript Versions | by Học Javascript

JavaScript là ngôn ngữ lập trình phổ biến trong phát triển web, giúp tạo ra các trang web tương tác và động. Tuy nhiên, để đảm bảo tính nhất quán và cập nhật các tính năng mới, JavaScript cần có một tiêu chuẩn chung. Đây chính là vai trò của ECMAScript – tiêu chuẩn chính thức do tổ chức ECMA International phát triển và duy trì.

Kể từ khi ra mắt vào năm 1997, ECMAScript đã trải qua nhiều phiên bản nâng cấp, với mỗi bản cập nhật mang lại những tính năng mới giúp tối ưu hiệu suất, cải thiện cú pháp và làm cho JavaScript dễ sử dụng hơn. Đặc biệt, từ ECMAScript 2015 (ES6) trở đi, JavaScript liên tục được cải tiến mỗi năm, giúp lập trình viên làm việc hiệu quả hơn với các công cụ mạnh mẽ như arrow functions, classes, template literals, modules, promises, và nhiều cải tiến khác.

ECMAScript 2017 (ES8) là gì?

ECMAScript 2017 (ES8) là phiên bản tiếp theo của ECMAScript, được phát hành vào tháng 6 năm 2017. Đây là một bản nâng cấp quan trọng, giúp lập trình viên JavaScript xử lý bất đồng bộ dễ dàng hơn với async/await, đồng thời bổ sung các phương thức hữu ích để thao tác với object và string.

Một số tính năng quan trọng trong ES8 bao gồm:
Async/Await – Giúp xử lý bất đồng bộ dễ đọc và dễ hiểu hơn so với Promise.
Object.values() và Object.entries() – Giúp truy xuất dữ liệu từ object một cách nhanh chóng.
String padding (padStart() và padEnd()) – Hỗ trợ định dạng chuỗi dễ dàng hơn.
Trailing commas in function parameters – Hỗ trợ dấu phẩy cuối trong danh sách tham số hàm, giúp code rõ ràng hơn.
SharedArrayBuffer & Atomics – Tăng cường hiệu suất xử lý đa luồng trong JavaScript.

Tại sao ES8 quan trọng trong lập trình JavaScript hiện đại?

Trước ES8, việc xử lý bất đồng bộ trong JavaScript chủ yếu dựa vào callback hoặc Promise, nhưng cả hai phương pháp này đều có nhược điểm. Callback có thể dẫn đến callback hell, trong khi Promise, dù tốt hơn, vẫn khiến code trở nên phức tạp khi có nhiều thao tác liên tiếp. ES8 đã giải quyết vấn đề này bằng cách giới thiệu async/await, giúp code bất đồng bộ trông giống như code đồng bộ, dễ đọc hơn và ít lỗi hơn.

Ngoài ra, ES8 giúp thao tác với object và chuỗi dễ dàng hơn, giúp lập trình viên viết code gọn gàng và tối ưu hơn. Với sự phát triển của các framework hiện đại như React, Vue, Angular, ES8 trở thành một tiêu chuẩn quan trọng mà mọi lập trình viên JavaScript cần biết.

Các tính năng mới trong ES8 JavaScript

ECMAScript 2017 (ES8) mang đến nhiều tính năng giúp JavaScript mạnh mẽ và dễ sử dụng hơn. Dưới đây là các tính năng quan trọng mà ES8 đã giới thiệu:

Async/Await – Hỗ trợ xử lý bất đồng bộ dễ dàng hơn

Trước ES8, JavaScript sử dụng Promise để xử lý bất đồng bộ, nhưng cách viết này vẫn còn phức tạp khi có nhiều lời gọi lồng nhau. ES8 giới thiệu async/await, giúp xử lý bất đồng bộ một cách rõ ràng, dễ đọc và dễ debug hơn.

Ưu điểm của async/await:

Dễ đọc hơn – Trông giống như code đồng bộ, không cần .then().catch().
Tránh callback hell – Không bị lồng quá nhiều hàm như callback.
Dễ debug hơn – Có thể sử dụng try...catch để xử lý lỗi thay vì .catch().

Cách sử dụng async/await trong JavaScript:

  • Hàm async luôn trả về một Promise.
  • await chỉ có thể được sử dụng trong một hàm async.

Ví dụ sử dụng async/await để lấy dữ liệu từ API:

async function fetchData() {
    try {
        let response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
        let data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('Lỗi:', error);
    }
}

fetchData();
Kết quả:
{ userId: 1, id: 1, title: "delectus aut autem", completed: false }

So sánh với Promise:

Dùng Promise:

fetch('https://jsonplaceholder.typicode.com/todos/1')
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Lỗi:', error));

Dùng async/await (gọn hơn, dễ hiểu hơn):

async function fetchData() {
    try {
        let response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
        let data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('Lỗi:', error);
    }
}

Object.values() và Object.entries() – Duyệt object dễ dàng hơn

ES8 giới thiệu hai phương thức mới giúp thao tác với object dễ dàng hơn:

  • Object.values(obj) – Trả về một mảng chứa tất cả giá trị của object.
  • Object.entries(obj) – Trả về một mảng chứa các cặp [key, value] của object.

So sánh với Object.keys()

  • Object.keys(obj) trả về mảng chứa key của object.
  • Object.values(obj) trả về mảng chứa value của object.
  • Object.entries(obj) trả về mảng chứa cặp [key, value].

Ví dụ:

const user = { id: 1, name: "Alice", age: 25 };

console.log(Object.keys(user));    // ["id", "name", "age"]
console.log(Object.values(user));  // [1, "Alice", 25]
console.log(Object.entries(user)); // [["id", 1], ["name", "Alice"], ["age", 25]]

Ứng dụng thực tế:

Duyệt qua object bằng forEach:

Object.entries(user).forEach(([key, value]) => {
    console.log(`${key}: ${value}`);
});
Kết quả:
id: 1  
name: Alice  
age: 25  

String padding (padStart và padEnd) – Định dạng chuỗi

ES8 bổ sung hai phương thức giúp định dạng chuỗi dễ dàng hơn:

  • padStart(length, char) – Thêm ký tự vào đầu chuỗi đến khi đạt độ dài mong muốn.
  • padEnd(length, char) – Thêm ký tự vào cuối chuỗi đến khi đạt độ dài mong muốn.

Ứng dụng:

Hiển thị số liệu theo chuẩn (ví dụ: số tài khoản, mã đơn hàng)
Định dạng text đầu ra trong báo cáo

Ví dụ:

console.log("5".padStart(3, "0"));  // "005"
console.log("12".padStart(5, "X")); // "XXX12"

console.log("hello".padEnd(10, ".")); // "hello....."
console.log("JS".padEnd(6, "!"));    // "JS!!!!"

Object.getOwnPropertyDescriptors() – Lấy toàn bộ thuộc tính của object

Phương thức Object.getOwnPropertyDescriptors(obj) trả về tất cả thông tin mô tả của một object, bao gồm:

  • value (giá trị của thuộc tính)
  • writable (có thể thay đổi không)
  • enumerable (có thể lặp qua không)
  • configurable (có thể xóa hoặc chỉnh sửa không)

So sánh với Object.getOwnPropertyDescriptor()

  • Object.getOwnPropertyDescriptor(obj, prop) → Lấy mô tả của một thuộc tính.
  • Object.getOwnPropertyDescriptors(obj) → Lấy mô tả của tất cả thuộc tính trong object.

Ví dụ:

const user = {
    name: "Alice",
    age: 25,
    get info() {
        return `${this.name} - ${this.age}`;
    }
};

// Lấy mô tả tất cả thuộc tính
console.log(Object.getOwnPropertyDescriptors(user));

Ứng dụng: Sao chép object mà vẫn giữ được getter/setter:

const clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(user));
console.log(clone.info); // "Alice - 25"

Trailing commas trong function parameters – Cải thiện cú pháp code

ES8 cho phép thêm dấu phẩy cuối cùng (trailing comma) trong danh sách tham số của hàm.

Dễ đọc hơn, đặc biệt khi có nhiều tham số.
Hỗ trợ tốt hơn khi thêm/bớt tham số trong code dài.

Ví dụ:

Trước ES8 (Không hỗ trợ trailing comma):

function sum(a, b, c) {
    return a + b + c;
}

Sau ES8 (Hỗ trợ trailing comma):

function sum(
    a,
    b,
    c, // Dấu phẩy cuối hợp lệ
) {
    return a + b + c;
}

Hữu ích trong lập trình nhóm, khi thêm/bớt tham số dễ dàng mà không gây lỗi.

Ứng dụng của ES8 trong lập trình JavaScript

ES8 (ECMAScript 2017) mang đến nhiều tính năng quan trọng giúp lập trình JavaScript trở nên dễ dàng hơn. Các tính năng mới này không chỉ giúp code dễ đọc, dễ bảo trì mà còn cải thiện hiệu suất và tính ổn định của ứng dụng. Dưới đây là một số ứng dụng cụ thể của ES8 trong lập trình JavaScript.

Giúp code dễ đọc, dễ bảo trì hơn nhờ async/await

Trước ES8, việc xử lý bất đồng bộ thường dựa vào callback hoặc Promise, dễ dẫn đến callback hell hoặc các chuỗi .then() phức tạp.

Với async/await, code JavaScript trở nên đồng bộ hơn về mặt trực quan, giúp lập trình viên dễ đọc và dễ bảo trì hơn.

Ứng dụng thực tế:

Gọi API và xử lý dữ liệu đơn giản hơn

Ví dụ: Trước đây, khi sử dụng Promise, code có thể trở nên rối rắm:

fetch('https://jsonplaceholder.typicode.com/posts/1')
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Lỗi:', error));

Sau khi có async/await (đơn giản hơn, dễ đọc hơn):

async function fetchPost() {
    try {
        let response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
        let data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('Lỗi:', error);
    }
}

fetchPost();
  • Dễ đọc hơn – Không bị lồng nhiều .then().
  • Dễ bảo trì – Khi cần sửa đổi, chỉ cần thay đổi từng dòng lệnh như code đồng bộ.
  • Dễ debug hơn – Có thể dùng try...catch để xử lý lỗi.

Cải thiện hiệu suất xử lý object và chuỗi với các phương thức mới

ES8 bổ sung một số phương thức giúp thao tác với objectchuỗi hiệu quả hơn, tối ưu hóa hiệu suất khi làm việc với dữ liệu.

Xử lý Object dễ dàng hơn với Object.values()Object.entries()

Trong nhiều ứng dụng, ta cần thao tác với dữ liệu dạng object, ví dụ: lọc danh sách, hiển thị thông tin người dùng, trích xuất dữ liệu.

Ví dụ:

const user = { id: 1, name: "Alice", age: 25 };

console.log(Object.values(user));  // [1, "Alice", 25]
console.log(Object.entries(user)); // [["id", 1], ["name", "Alice"], ["age", 25]]
  • Duyệt object nhanh chóng: Dễ dàng lặp qua object để hiển thị danh sách thông tin.
  • Chuyển đổi dữ liệu linh hoạt: Object.entries() giúp dễ dàng tạo mảng từ object để xử lý dữ liệu hiệu quả hơn.

Định dạng chuỗi linh hoạt hơn với padStart()padEnd()

Các phương thức padStart()padEnd() rất hữu ích trong các ứng dụng định dạng số liệu, đặc biệt trong báo cáo tài chính, mã hóa dữ liệu, hoặc xử lý UI.

Ứng dụng thực tế: Hiển thị số tài khoản với định dạng chuẩn:

let accountNumber = "123";
console.log(accountNumber.padStart(10, "0")); // "0000000123"
Ứng dụng khác: Định dạng text trong báo cáo:
let title = "Total";
console.log(title.padEnd(10, ".") + "1000"); // "Total.....1000"

Giúp hiển thị dữ liệu rõ ràng hơn trên giao diện hoặc báo cáo.
Tự động căn chỉnh dữ liệu mà không cần xử lý thủ công.

Được hỗ trợ rộng rãi trên trình duyệt và Node.js

Một điểm mạnh của ES8 là được hỗ trợ trên hầu hết các trình duyệt hiện đại và trong Node.js, giúp các ứng dụng JavaScript chạy ổn định hơn mà không cần lo ngại về khả năng tương thích.

Lợi ích của việc hỗ trợ rộng rãi:
Không cần polyfill hoặc Babel để sử dụng các tính năng mới.
Code chạy nhanh hơn vì được tối ưu hóa trên các trình duyệt mới nhất.
Ứng dụng trên cả Frontend và Backend, đặc biệt với Node.js.

Ví dụ: Async/Await trong Node.js giúp xử lý file dễ dàng hơn:

const fs = require('fs').promises;

async function readFileContent() {
    try {
        let data = await fs.readFile('example.txt', 'utf-8');
        console.log(data);
    } catch (error) {
        console.error('Lỗi:', error);
    }
}

readFileContent();

Trước đây phải dùng callback hoặc Promise, nhưng với ES8, async/await giúp code Node.js gọn gàng và dễ bảo trì hơn.

So sánh ES8 với ES7 trong JavaScript

ECMAScript 2018 (ES8) mang lại nhiều thay đổi quan trọng so với ECMAScript 2017 (ES7), giúp lập trình viên viết code gọn gàng hơn, dễ đọc hơn và tối ưu hóa hiệu suất. Trong khi ES7 chỉ có hai tính năng mới, ES8 đã mở rộng nhiều hơn, đặc biệt tập trung vào xử lý bất đồng bộ và cải tiến thao tác với object. Dưới đây là những điểm so sánh chi tiết giữa ES8 và ES7.

ES8 có nhiều thay đổi hơn ES7, đặc biệt là trong bất đồng bộ và object handling

ES7 (ECMAScript 2016) chỉ có hai tính năng mới chính:

  • Array.prototype.includes() – Kiểm tra xem phần tử có tồn tại trong mảng hay không.
  • Toán tử lũy thừa ** – Viết gọn hơn thay vì dùng Math.pow().

ES8 (ECMAScript 2017) mang lại nhiều cải tiến quan trọng hơn, gồm:

  • Async/Await – Giúp xử lý bất đồng bộ tốt hơn.
  • Object.values() & Object.entries() – Đơn giản hóa việc thao tác với object.
  • String padding (padStart() & padEnd()) – Hỗ trợ định dạng chuỗi dễ dàng.
  • Object.getOwnPropertyDescriptors() – Lấy đầy đủ thông tin của các thuộc tính trong object.
  • Trailing commas trong function parameters – Giúp code dễ chỉnh sửa hơn.

Nhận xét: ES8 có nhiều cải tiến quan trọng hơn ES7, đặc biệt giúp xử lý bất đồng bộ và làm việc với object hiệu quả hơn.

async/await giúp xử lý bất đồng bộ tốt hơn nhiều so với Promise

Trước ES8, JavaScript chủ yếu sử dụng Promise để xử lý bất đồng bộ, nhưng code vẫn khá phức tạp và khó debug khi có nhiều .then() lồng nhau (callback hell).

ES8 giới thiệu async/await, giúp code dễ đọc như code đồng bộ:

Ví dụ với Promise (ES7 trở về trước):

function fetchData() {
    fetch('https://jsonplaceholder.typicode.com/posts/1')
        .then(response => response.json())
        .then(data => console.log(data))
        .catch(error => console.error('Lỗi:', error));
}

fetchData();

Code vẫn có .then() lồng nhau, dễ rối khi có nhiều thao tác bất đồng bộ.

Ví dụ với async/await (ES8):

async function fetchData() {
    try {
        let response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
        let data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('Lỗi:', error);
    }
}

fetchData();

Code ngắn hơn, dễ đọc hơn, ít lỗi hơn.
Dễ debug hơn vì có thể dùng try...catch để xử lý lỗi.

Nhận xét: ES8 giúp xử lý bất đồng bộ dễ dàng hơn nhiều so với ES7 nhờ async/await, giúp code gọn gàng hơn, dễ bảo trì hơn.

Object.values() và Object.entries() giúp đơn giản hóa việc thao tác object

Trước ES8, lập trình viên thường dùng Object.keys() để lấy danh sách key trong object, sau đó phải duyệt thủ công để lấy value.

ES8 thêm Object.values() và Object.entries(), giúp làm việc với object dễ dàng hơn.

Trước ES8 (ES7 sử dụng Object.keys() + map()):

const user = { id: 1, name: "Alice", age: 25 };
const values = Object.keys(user).map(key => user[key]);
console.log(values); // [1, "Alice", 25]

Cần thêm .map() để lấy value từ key, code dài hơn.

Sau ES8 (Dùng Object.values()Object.entries()):

console.log(Object.values(user));  // [1, "Alice", 25]
console.log(Object.entries(user)); // [["id", 1], ["name", "Alice"], ["age", 25]]

Code ngắn gọn hơn, trực quan hơn, dễ hiểu hơn.
Dễ dàng duyệt object mà không cần .map().

Nhận xét: Object.values()Object.entries() giúp đơn giản hóa thao tác với object, tiết kiệm thời gian và tăng hiệu suất.

Các cải tiến cú pháp giúp viết code linh hoạt hơn

Bên cạnh những cải tiến lớn, ES8 cũng bổ sung một số cải tiến cú pháp giúp code linh hoạt hơn, dễ bảo trì hơn.

String Padding (padStart() & padEnd()) – Hỗ trợ định dạng chuỗi

Ứng dụng thực tế: Định dạng số tài khoản hoặc căn chỉnh text.

let accountNumber = "123";
console.log(accountNumber.padStart(10, "0")); // "0000000123"

let title = "Total";
console.log(title.padEnd(10, ".") + "1000"); // "Total.....1000"

Giúp hiển thị dữ liệu rõ ràng hơn trên giao diện hoặc báo cáo.
Tự động căn chỉnh dữ liệu mà không cần xử lý thủ công.

Trailing commas trong function parameters – Dễ chỉnh sửa code hơn

Trước đây, khi viết danh sách tham số của hàm, nếu muốn thêm tham số mới, ta phải sửa dòng cuối cùng để thêm dấu phẩy ,. ES8 cho phép viết dấu phẩy cuối cùng, giúp chỉnh sửa dễ dàng hơn.

Trước ES8:

function test(a, b, c) { }

Nếu thêm tham số d, phải sửa lại dòng c.

Sau ES8:

function test(a, b, c,) { }

Thêm d dễ dàng mà không cần chỉnh sửa dòng c.

Nhận xét: Nhỏ nhưng hữu ích, giúp quản lý code dễ hơn khi làm việc với nhiều tham số.

Kết bài

ECMAScript 2017 (ES8) đánh dấu một bước tiến quan trọng trong sự phát triển của JavaScript, mang lại nhiều cải tiến giúp code dễ đọc hơn, bảo trì tốt hơn và tối ưu hiệu suất. Đặc biệt, async/await đã thay thế cách xử lý bất đồng bộ bằng Promise, giúp lập trình viên viết code gọn gàng hơn và dễ debug hơn. Bên cạnh đó, các phương thức như Object.values(), Object.entries() giúp làm việc với object hiệu quả hơn, trong khi padStart(), padEnd() hỗ trợ định dạng chuỗi một cách trực quan.

So với ES7, ES8 mang đến nhiều thay đổi hữu ích hơn, giúp lập trình viên viết code nhanh hơn, dễ hiểu hơn và ít lỗi hơn. Những tính năng này không chỉ hỗ trợ trong lập trình web mà còn có tác động lớn đến các framework và thư viện JavaScript hiện đại.

Bài viết liên quan