Mô hình Đối tượng Trình duyệt (BOM) trong JavaScript

Giới thiệu về BOM

Mô hình Đối tượng Trình duyệt (Browser Object Model - BOM) cung cấp các đối tượng cho phép tương tác với cửa sổ trình duyệt, độc lập với nội dung trang web. Đối tượng trung tâm của BOM là window. Khác với DOM – được tiêu chuẩn hóa bởi W3C – BOM không có chuẩn chính thức, ban đầu được định nghĩa bởi Netscape.

Cấu trúc của BOM

BOM bao gồm nhiều đối tượng con, trong đó window là đối tượng cấp cao nhất. Nó đóng hai vai trò:

  • Là giao diện để JavaScript tương tác với cửa sổ trình duyệt.
  • Là đối tượng toàn cục: mọi biến và hàm khai báo ở phạm vi toàn cục đều trở thành thuộc tính/phương thức của window.

Ví dụ minh họa:

<script>
  let value = 42;
  console.log(value);         // 42
  console.log(window.value);  // 42

  function greet() {
    console.log("Hello!");
  }
  greet();           // Gọi trực tiếp
  window.greet();    // Gọi qua window

  console.log(window.name); // Thuộc tính đặc biệt
</script>

Sự kiện liên quan đến cửa sổ

1. Sự kiện tải trang hoàn chỉnh

window.onload = function() { /* xử lý */ };
// hoặc
window.addEventListener("load", function() { /* xử lý */ });

Sự kiện này kích hoạt khi toàn bộ tài nguyên (HTML, CSS, ảnh, script...) đã tải xong. Lưu ý:

  • Dùng onload truyền thống chỉ gán được một lần (ghi đè nếu gán nhiều lần).
  • Dùng addEventListener có thể đăng ký nhiều listener.

2. Sự kiện DOM sẵn sàng

document.addEventListener("DOMContentLoaded", function() { /* xử lý */ });

Kích hoạt ngay khi cây DOM được xây dựng xong, không chờ tải ảnh/CSS. Hỗ trợ từ IE9 trở lên. Phù hợp để khởi tạo giao diện sớm mà không cần đợi toàn bộ tài nguyên.

3. Sự kiện thay đổi kích thước cửa sổ

window.addEventListener("resize", function() {
  if (window.innerWidth <= 800) {
    document.querySelector("div").style.display = "none";
  } else {
    document.querySelector("div").style.display = "block";
  }
});

Sự kiện này kích hoạt mỗi khi kích thước cửa sổ thay đổi (theo pixel). Thường dùng để xây dựng giao diện responsive.

Hai loại bộ hẹn giờ

1. setTimeout – Thực thi một lần sau thời gian chờ

let timerId = setTimeout(() => {
  console.log("Chạy sau 2 giây");
}, 2000);

// Hủy bộ hẹn giờ
clearTimeout(timerId);

Hàm callback được gọi một lần sau khoảng thời gian (tính bằng mili giây). Có thể hủy bằng clearTimeout với ID trả về.

2. setInterval – Lặp lại theo chu kỳ

let countdown = 5;
let intervalId = setInterval(() => {
  if (countdown <= 0) {
    clearInterval(intervalId);
    console.log("Hết giờ!");
  } else {
    console.log(`Còn lại: ${countdown}s`);
    countdown--;
  }
}, 1000);

Hàm callback được gọi lặp lại mỗi khoảng thời gian. Dừng bằng clearInterval.

Ví dụ ứng dụng: Đếm ngược đến sự kiện

<div>
  <span class="hour">00</span>:
  <span class="minute">00</span>:
  <span class="second">00</span>
</div>

<script>
const hourEl = document.querySelector(".hour");
const minuteEl = document.querySelector(".minute");
const secondEl = document.querySelector(".second");

const targetTime = new Date("2025-12-31T23:59:59").getTime();

function updateCountdown() {
  const now = new Date().getTime();
  const diff = targetTime - now;

  if (diff <= 0) {
    hourEl.textContent = "00";
    minuteEl.textContent = "00";
    secondEl.textContent = "00";
    return;
  }

  const h = String(Math.floor(diff / (1000 * 60 * 60))).padStart(2, "0");
  const m = String(Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))).padStart(2, "0");
  const s = String(Math.floor((diff % (1000 * 60)) / 1000)).padStart(2, "0");

  hourEl.textContent = h;
  minuteEl.textContent = m;
  secondEl.textContent = s;
}

updateCountdown(); // Gọi ngay để tránh trống lúc load
setInterval(updateCountdown, 1000);
</script>

Ví dụ: Nút gửi mã OTP bị khóa 60 giây

<button id="sendBtn">Gửi mã</button>

<script>
const btn = document.getElementById("sendBtn");
btn.addEventListener("click", () => {
  let seconds = 60;
  btn.disabled = true;
  btn.textContent = `Chờ ${seconds}s`;

  const timer = setInterval(() => {
    seconds--;
    if (seconds <= 0) {
      clearInterval(timer);
      btn.disabled = false;
      btn.textContent = "Gửi mã";
    } else {
      btn.textContent = `Chờ ${seconds}s`;
    }
  }, 1000);
});
</script>

Đối tượng location

Thuộc tính window.location chứa thông tin URL hiện tại và cho phép điều hướng.

Thuộc tính quan trọng

  • href: Toàn bộ URL.
  • search: Chuỗi query string (phần sau dấu ?).

Phương thức điều hướng

// Chuyển hướng và lưu vào lịch sử
location.assign("https://example.com");

// Chuyển hướng KHÔNG lưu lịch sử
location.replace("https://example.com");

// Tải lại trang
location.reload();        // Từ cache
location.reload(true);    // Từ server

Đối tượng navigator

Chứa thông tin về trình duyệt. Thường dùng navigator.userAgent để phát hiện thiết bị:

const isMobile = /Android|iPhone|iPad|iPod|BlackBerry|Windows Phone/i.test(navigator.userAgent);
if (isMobile) {
  window.location.href = "/mobile.html";
}

Đối tượng history

Cho phép tương tác với lịch sử duyệt web:

// Quay lại trang trước
history.back();

// Tiến tới trang tiếp
history.forward();

// Di chuyển n bước (âm: lùi, dương: tiến)
history.go(-1); // tương đương back()
history.go(1);  // tương đương forward()

Thẻ: BOM JavaScript window location navigator

Đăng vào ngày 29 tháng 5 lúc 09:07