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

JavaScript trim: vì sao chuỗi trông rỗng vẫn còn ký tự?

Một ô nhập liệu trông rỗng chưa chắc trở thành chuỗi rỗng sau trim(). Ngược lại, gọi trim trên mã định danh có thể âm thầm thay đổi dữ liệu trước khi kiểm tra. Để tránh hai lỗi này, cần phân biệt thao tác cắt khoảng trắng với quy tắc hợp lệ của từng trường.

JavaScript trim: vì sao chuỗi trông rỗng vẫn còn ký tự?

Một ô nhập liệu trông rỗng chưa chắc trở thành chuỗi rỗng sau trim(). Ngược lại, gọi trim trên mã định danh có thể âm thầm thay đổi dữ liệu trước khi kiểm tra. Để tránh hai lỗi này, cần phân biệt thao tác cắt khoảng trắng với quy tắc hợp lệ của từng trường.

1. trim trả chuỗi mới và chỉ xử lý hai đầu

const raw = '  HT  Vietnam  ';
console.log(JSON.stringify(raw.trim())); // "HT  Vietnam"
console.log(JSON.stringify(raw)); // "  HT  Vietnam  "
console.log(JSON.stringify('\t ready\n'.trim())); // "ready"

Khoảng trắng giữa HT và Vietnam vẫn còn; biến raw cũng không bị sửa. Nếu cần dùng kết quả đã cắt, hãy gán hoặc trả về chuỗi mới. Theo MDN String.trim, tập ký tự được xử lý gồm WhiteSpace và LineTerminator của ECMAScript.

Đừng xem trim như bước dọn mọi vấn đề văn bản. Nó không gộp dấu cách giữa các từ, không chuẩn hóa Unicode và không xác thực định dạng mã nghiệp vụ. Mỗi thao tác đó có thể thay đổi ý nghĩa dữ liệu nên cần được quyết định riêng.

2. Ký tự vô hình không thuộc cùng một nhóm

console.log('\u00A0'.trim().length); // 0
console.log('\uFEFF'.trim().length); // 0
console.log('\u200B'.trim().length); // 1
console.log('\u200B'.trim() === ''); // false

U+00A0 là NO-BREAK SPACE; U+FEFF cũng thuộc tập được trim xử lý. U+200B ZERO WIDTH SPACE thì không. Bảng White Space trong đặc tả ECMAScript giúp xác định tập ký tự, thay vì suy luận từ việc mắt có nhìn thấy chúng hay không.

Điều kiện value.trim() !== '' vì thế chỉ chứng minh có dữ liệu còn lại sau phép cắt cụ thể này. Nó không chứng minh chuỗi có chữ hiển thị phù hợp với sản phẩm. Cũng không nên xóa hàng loạt mọi ký tự vô hình khỏi mọi trường: một chính sách cho mã sản phẩm chưa chắc phù hợp với tên người hoặc nội dung đa ngôn ngữ.

3. Kiểm tra mã theo tập ký tự cho phép

function parseProductCode(value) {
  if (typeof value !== 'string') {
    throw new TypeError('code must be a string');
  }
  if (!/^[A-Z0-9-]{1,20}$/.test(value)) {
    throw new RangeError('invalid product code');
  }
  return value;
}
console.log(parseProductCode('HT-2026')); // HT-2026
console.log(parseProductCode('0')); // 0

Contract minh họa chỉ cho phép 1–20 ký tự ASCII gồm chữ hoa, chữ số và dấu gạch nối. Không trim, không đổi chữ thường thành chữ hoa và không chuyển số thành chuỗi. Vì thế ' HT-2026 ' và mã chứa U+200B bị từ chối thay vì được sửa ngầm.

Đây chưa phải định dạng mã cho mọi doanh nghiệp: dấu gạch nối đứng một mình vẫn hợp lệ theo regex này. Nếu hệ thống yêu cầu tiền tố, vị trí dấu nối hoặc kiểm tra mã tồn tại, bổ sung quy tắc đó riêng. Tên người và văn bản tự do cần contract khác.

4. Xem code point khi điều tra dữ liệu khó nhìn

const value = '\u200BHT\u00A0';
const points = Array.from(value, char =>
  'U+' + char.codePointAt(0).toString(16).toUpperCase().padStart(4, '0')
);
console.log(points.join(' ')); // U+200B U+0048 U+0054 U+00A0
console.log(value.trim().length); // 3

Đầu ra chỉ rõ ký tự đầu không bị cắt còn ký tự cuối đã biến mất. Khi nhận báo cáo “hai mã giống hệt nhau nhưng không tìm thấy”, dùng một mẫu không nhạy cảm để đối chiếu code point và thứ tự xử lý ở frontend, backend.

Không cần ghi toàn bộ nội dung người dùng vào log để điều tra. Chọn dữ liệu mẫu tối thiểu; code point vẫn có thể khôi phục nội dung nên không phải cách ẩn danh hóa. Nếu hệ thống cho phép chuẩn hóa đầu vào, ghi rõ thời điểm và trả lại lỗi dễ hiểu khi dữ liệu không đạt contract.

5. Checklist cho form và API

  • Trường này cần giữ nguyên dữ liệu hay được phép cắt hai đầu?
  • Đã dùng kết quả trả về của trim thay vì chỉ gọi rồi bỏ qua?
  • Quy tắc ký tự hợp lệ có được kiểm tra độc lập không?
  • Có test chuỗi rỗng, tab, xuống dòng, U+00A0 và U+200B?
  • Frontend và backend có áp dụng cùng contract và thứ tự xử lý?

Tám khối mã Việt–Anh đã chạy bằng Node.js; helper được kiểm tra thêm kiểu dữ liệu sai, giới hạn độ dài và ký tự ngoài tập cho phép. Chưa kiểm thử form trình duyệt hoặc tích hợp API thực tế.

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.