Lập trình · 21/10/2026

JavaScript: xuống dòng không luôn kết thúc câu lệnh

Chỉ đổi vị trí xuống dòng mà hàm không còn trả dữ liệu, hoặc một mảng bỗng gây TypeError. Xuống dòng giúp người đọc chia đoạn mã, nhưng ranh giới câu lệnh JavaScript còn phụ thuộc cú pháp. Bốn ví dụ dưới đây tái hiện lỗi và cách viết rõ điểm bắt đầu, kết thúc của biểu thức.

JavaScript: xuống dòng không luôn kết thúc câu lệnh

Chỉ đổi vị trí xuống dòng mà hàm không còn trả dữ liệu, hoặc một mảng bỗng gây TypeError. Xuống dòng giúp người đọc chia đoạn mã, nhưng ranh giới câu lệnh JavaScript còn phụ thuộc cú pháp. Bốn ví dụ dưới đây tái hiện lỗi và cách viết rõ điểm bắt đầu, kết thúc của biểu thức.

1. Xuống dòng ngay sau return làm mất giá trị dự định trả

function buildResult() {
  return
  { status: 'ready' };
}
console.log(buildResult() === undefined); // true

Ở đây JavaScript xử lý return như một câu lệnh không có biểu thức theo sau, nên kết quả là undefined. Khối có status ở dòng dưới không trở thành object được trả về. Quy tắc cấm line terminator giữa return và biểu thức được mô tả trong MDN return.

Lỗi này có thể đi qua test chỉ kiểm tra “hàm không ném exception”. Với hàm tạo dữ liệu cho giao diện, hãy kiểm tra chính xác cấu trúc và giá trị trả về. Đừng chỉ thêm giá trị mặc định ở nơi gọi để che mất kết quả undefined ngoài ý muốn.

2. Đặt phần mở biểu thức trên cùng dòng với return

function buildResult() {
  return (
    { status: 'ready', count: 0 }
  );
}
console.log(JSON.stringify(buildResult())); // {"status":"ready","count":0}

Dấu ngoặc mở sau return cho thấy biểu thức đã bắt đầu trước khi xuống dòng. Viết return { rồi xuống dòng cho các thuộc tính cũng phù hợp. Lựa chọn cách trình bày theo formatter của dự án, sau đó kiểm tra đầu ra vẫn đúng contract.

Thêm dấu chấm phẩy sau object ở ví dụ đầu không sửa được lỗi, vì ranh giới đã nằm ngay sau return. Vị trí bắt đầu biểu thức mới là chi tiết cần sửa trong trường hợp đó.

3. Dòng bắt đầu bằng dấu ngoặc vuông có thể tiếp tục dòng trước

const events = [];
try {
  const label = 'abc'
  [0, 1].forEach(index => events.push(index));
} catch (error) {
  console.log(error instanceof TypeError); // true
}
console.log(events.length); // 0

Đoạn mã có thể được phân tích như một biểu thức liên tục: 'abc'[0, 1].forEach(...). Biểu thức dấu phẩy trong ngoặc vuông cho khóa 1; ký tự 'b' không có phương thức forEach như mảng. Đây là phân tích của ví dụ cụ thể, không phải lỗi từ dữ liệu events.

Automatic semicolon insertion, thường gọi là ASI, không đơn giản chèn chấm phẩy sau mọi dòng. Xem MDN lexical grammar và ASI. Nếu token ở dòng sau vẫn ghép được vào cú pháp trước, xuống dòng có thể không chia hai câu lệnh như người viết mong đợi.

4. Kết thúc câu lệnh trước khi bắt đầu mảng độc lập

const events = [];
const label = 'abc';
[0, 1].forEach(index => events.push(label[index]));
console.log(events.join('|')); // a|b

const other = 'xyz'
;[0, 1].forEach(index => events.push(other[index]));
console.log(events.join('|')); // a|b|x|y

Nửa đầu dùng dấu chấm phẩy cuối câu lệnh. Nửa sau minh họa dấu chấm phẩy phòng vệ ở đầu dòng mảng trong mã dùng phong cách bỏ chấm phẩy cuối dòng. Chọn một quy ước thống nhất theo dự án và để công cụ định dạng hỗ trợ.

Khi ghép các đoạn mã, sửa thủ công hoặc chép ví dụ vào file khác, đọc cả dòng ngay trước điểm ghép. Một đoạn mảng tự chạy đúng khi đứng riêng vẫn có thể bị ghép vào biểu thức phía trên trong ngữ cảnh mới.

5. Kiểm tra thay đổi định dạng như thay đổi hành vi

  • Giữ biểu thức trả về bắt đầu trên cùng dòng với return.
  • Kiểm tra dòng mở đầu bằng [ hoặc ( trong đoạn mã vừa chỉnh.
  • Test giá trị trả về, không chỉ việc không có exception.
  • Test cả số lần callback chạy và tác dụng phụ mong đợi.
  • Chạy formatter, lint và test theo quy trình hiện có của dự án.

Tám khối mã Việt–Anh đã chạy bằng Node.js, kèm kiểm tra trực tiếp object trả về và dữ liệu mảng. Bài không thay đổi cấu hình formatter hay thử mọi trường hợp ASI của ngôn ngữ.

Thảo luận

Bình luận 0

Đăng nhập để bình luận

Bạn cần có tài khoản để tham gia thảo luận và trả lời độc giả khác.

Đăng nhậpĐăng ký

Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.