JavaScript · ES2026

ES17 Interactive Hub — ECMAScript 2026

Explicit Resource Management (using/await using với Symbol.dispose), Error.isError() cross-realm safe, RegExp pattern modifiers (?i:...) scope flag inline, Iterator.range/zip — nâng cấp ergonomics + an toàn resource management.

Kinh Nghiệm
0 XP
Hoàn thành khóa học0%

Explicit Resource Management (using)

Chuyên đề cốt lõi

Khó10 phút

💡 Khái niệm tóm tắt

Từ khoá `using` và `await using` tự động dọn dẹp resource khi rời scope thông qua Symbol.dispose / Symbol.asyncDispose — như "with" của Python, "using" của C#.

🤔 Tại sao cần tính năng này?

Pattern dọn resource (đóng file, release lock, close DB connection, abort fetch) trước phải dùng try/finally — verbose, dễ quên, hỗn loạn khi có nhiều resource. ES17 giới thiệu syntax `using x = ...` để JS engine tự gọi x[Symbol.dispose]() khi rời block, kể cả khi throw. `await using` cho async cleanup.

Trước (cách viết cũ)Verbose / Cồng kềnh
// Trước ES17 — try/finally thủ công, lồng nhau khi nhiều resource
function readFiles() {
    const file1 = openFile('a.txt');
    try {
        const file2 = openFile('b.txt');
        try {
            const file3 = openFile('c.txt');
            try {
                return processAll(file1, file2, file3);
            } finally {
                file3.close();
            }
        } finally {
            file2.close();
        }
    } finally {
        file1.close();
    }
}

// Pattern còn tệ hơn với async (cần phải await trong finally)
async function readAsync() {
    const conn = await openDB();
    try {
        const tx = await conn.beginTransaction();
        try {
            return await tx.query('...');
        } finally {
            await tx.rollback();
        }
    } finally {
        await conn.close();
    }
}
ES17 (Hiện đại)Tối ưu & Khuyên dùng
// ES17 — using tự gọi dispose khi rời scope
function createResource(name) {
    return {
        name,
        [Symbol.dispose]() {
            console.log(`Closing ${name}`);
        }
    };
}

function readFiles() {
    using file1 = createResource('a.txt');
    using file2 = createResource('b.txt');
    using file3 = createResource('c.txt');
    return process(file1, file2, file3);
    // → tự động gọi dispose theo thứ tự ngược: file3, file2, file1
    // → kể cả khi throw, dispose vẫn chạy
}

// async version với Symbol.asyncDispose
function createAsyncResource(name) {
    return {
        name,
        async [Symbol.asyncDispose]() {
            await new Promise(r => setTimeout(r, 10));
            console.log(`Async closed ${name}`);
        }
    };
}

async function readAsync() {
    await using conn = createAsyncResource('DB');
    await using tx = createAsyncResource('TX');
    // ... use them
    // → await dispose theo LIFO order khi rời async function
}
Bạn đã nắm chắc? Thử chạy code thật hoặc làm trắc nghiệm!

Bảng Tra Cứu Nhanh ES17

Xem nhanh cấu trúc + copy snippet

Explicit Resource Management (using)

Từ khoá `using` và `await using` tự động dọn dẹp resource khi rời scope thông qua Symbol.dispose / Symbol.asyncDispose — như "with" của Python, "using" của C#.

function createResource(name) {
    return {
        name,
...
Error.isError()

Static method kiểm tra robust một giá trị có phải Error instance không — hoạt động xuyên realm (iframe, worker, structuredClone) mà `instanceof Error` không xử lý được.

console.log(Error.isError(new Error("ok")));        // true
console.log(Error.isError(new TypeError("ok")));    // true
console.log(Error.isError(new RangeError("ok")));   // true
...
RegExp Pattern Modifiers

Cú pháp `(?i:abc)` và `(?-i:abc)` bật/tắt flag (i, m, s) chỉ trong một phần của regex thay vì toàn bộ — giảm độ phức tạp khi viết regex kết hợp nhiều case sensitivity.

const pattern = /[A-Z]+(?i:end)/;
console.log(pattern.test("HELLOend"));  // true
console.log(pattern.test("HELLOEND"));  // true
...
Iterator.range() & Iterator.zip()

Hai static method tạo iterator built-in: range(start, end, step) sinh dải số, zip(...iters) ghép song song nhiều iterator — không cần Array.from hay loop tay.

for (const i of Iterator.range(1, 6)) {
    console.log(i); // 1, 2, 3, 4, 5
}
...