在JavaScript中,BOW通常指Browser Object Model(浏览器对象模型),而DOM指Document Object Model(文档对象模型)。两者都是JavaScript与浏览器交互的核心API,但作用范围不同。
一、BOM(Browser Object Model)详解
BOM提供了与浏览器窗口进行交互的对象和方法,其顶层对象是window。
1.1 核心API与用法
| API/对象 | 说明 | 主要用途 | 示例代码 |
|---|---|---|---|
window | 浏览器窗口对象,全局对象 | 控制浏览器窗口、对话框、定时器等 | window.alert('提示') |
location | 当前窗口URL信息 | 获取或设置URL,页面跳转 | location.href = 'https://example.com' |
navigator | 浏览器信息 | 检测浏览器类型、版本、插件等 | navigator.userAgent |
history | 浏览器历史记录 | 前进、后退、跳转历史页面 | history.back() |
screen | 屏幕信息 | 获取屏幕尺寸、颜色深度等 | screen.width |
document | 文档对象(DOM的入口) | 访问和操作页面内容 | document.getElementById() |
1.2 关键方法示例
// 定时器 - 延迟执行 setTimeout(() => { console.log('3秒后执行'); }, 3000); // 定时器 - 间隔执行 let timer = setInterval(() => { console.log('每隔1秒执行一次'); }, 1000); // 5秒后停止定时器 setTimeout(() => { clearInterval(timer); }, 5000); // 打开新窗口 let newWindow = window.open('https://example.com', '_blank', 'width=800,height=600'); // 关闭窗口 newWindow.close(); // 获取浏览器信息 console.log('浏览器名称:', navigator.appName); console.log('浏览器版本:', navigator.appVersion); console.log('用户代理:', navigator.userAgent);二、DOM(Document Object Model)详解
DOM将HTML文档解析为树形结构,每个节点都是一个对象,JavaScript可以通过这些对象操作网页内容。
2.1 DOM树结构
document (根节点) ├── <html> │ ├── <head> │ │ ├── <title> │ │ └── <meta> │ └── <body> │ ├── <div id="container"> │ │ ├── <h1>标题</h1> │ │ └── <p class="content">内容</p> │ └── <ul> │ ├── <li>项目1</li> │ └── <li>项目2</li> └── 文本节点、属性节点等2.2 核心API分类
2.2.1 节点查询与获取
// 通过ID获取元素(返回单个元素) let elementById = document.getElementById('myId'); // 通过类名获取元素(返回HTMLCollection) let elementsByClass = document.getElementsByClassName('myClass'); // 通过标签名获取元素(返回HTMLCollection) let elementsByTag = document.getElementsByTagName('div'); // 通过CSS选择器获取(返回第一个匹配元素) let elementBySelector = document.querySelector('#container .item'); // 通过CSS选择器获取所有匹配元素(返回NodeList) let elementsBySelectorAll = document.querySelectorAll('.items li'); // 获取父节点 let parent = element.parentNode; // 获取子节点列表 let children = element.children; // 仅元素节点 let childNodes = element.childNodes; // 所有类型节点 // 获取兄弟节点 let nextSibling = element.nextElementSibling; // 下一个元素兄弟 let prevSibling = element.previousElementSibling; // 上一个元素兄弟2.2.2 节点创建与操作
// 创建新元素 let newDiv = document.createElement('div'); newDiv.id = 'newElement'; newDiv.className = 'box'; // 创建文本节点 let textNode = document.createTextNode('这是新内容'); // 添加子节点 newDiv.appendChild(textNode); document.body.appendChild(newDiv); // 插入节点(在指定节点前插入) let referenceNode = document.querySelector('.reference'); document.body.insertBefore(newDiv, referenceNode); // 替换节点 let oldNode = document.getElementById('old'); let newNode = document.createElement('div'); newNode.textContent = '新节点'; oldNode.parentNode.replaceChild(newNode, oldNode); // 克隆节点 let clonedNode = element.cloneNode(true); // true表示深度克隆(包括子节点) // 删除节点 let elementToRemove = document.getElementById('removeMe'); elementToRemove.parentNode.removeChild(elementToRemove); // 或使用现代方法 elementToRemove.remove();2.2.3 内容与属性操作
let element = document.getElementById('myElement'); // 内容操作 element.innerHTML = '<strong>带HTML的内容</strong>'; // 解析HTML element.innerText = '纯文本内容'; // 不解析HTML element.textContent = '文本内容(包括隐藏元素)'; // 属性操作 element.setAttribute('data-custom', 'value'); // 设置自定义属性 let attrValue = element.getAttribute('data-custom'); // 获取属性值 element.removeAttribute('data-custom'); // 删除属性 // class操作 element.classList.add('new-class'); // 添加类 element.classList.remove('old-class'); // 删除类 element.classList.toggle('active'); // 切换类 element.classList.contains('active'); // 检查是否包含类 // 样式操作 element.style.color = 'red'; element.style.backgroundColor = '#f0f0f0'; element.style.fontSize = '16px';2.2.4 事件处理
// 传统方式 element.onclick = function() { console.log('点击事件'); }; // 推荐方式 - addEventListener element.addEventListener('click', function(event) { console.log('事件类型:', event.type); console.log('目标元素:', event.target); console.log('当前元素:', event.currentTarget); // 阻止默认行为 event.preventDefault(); // 停止事件冒泡 event.stopPropagation(); }); // 移除事件监听 function handleClick() { console.log('点击处理'); } element.addEventListener('click', handleClick); element.removeEventListener('click', handleClick); // 常用事件类型 element.addEventListener('mouseover', () => {}); // 鼠标移入 element.addEventListener('mouseout', () => {}); // 鼠标移出 element.addEventListener('keydown', () => {}); // 按键按下 element.addEventListener('submit', () => {}); // 表单提交 element.addEventListener('change', () => {}); // 值改变2.3 实际应用案例
案例1:动态表格操作
// 创建表格行 function addTableRow(tableId, data) { let table = document.getElementById(tableId); let newRow = table.insertRow(); data.forEach(cellData => { let cell = newRow.insertCell(); cell.textContent = cellData; }); // 添加删除按钮 let deleteCell = newRow.insertCell(); let deleteBtn = document.createElement('button'); deleteBtn.textContent = '删除'; deleteBtn.onclick = function() { table.deleteRow(newRow.rowIndex); }; deleteCell.appendChild(deleteBtn); } // 使用示例 addTableRow('userTable', ['张三', 'zhangsan@example.com', '管理员']);案例2:表单验证与动态反馈
function validateForm() { let form = document.getElementById('myForm'); let username = form.querySelector('#username'); let errorDiv = document.getElementById('error-message'); // 清空之前的错误信息 errorDiv.innerHTML = ''; username.classList.remove('error'); if (username.value.length < 3) { // 显示错误信息 errorDiv.innerHTML = '用户名至少需要3个字符'; errorDiv.style.color = 'red'; // 添加错误样式 username.classList.add('error'); username.style.borderColor = 'red'; // 聚焦到错误字段 username.focus(); return false; } return true; } // 实时验证 document.getElementById('username').addEventListener('input', function() { if (this.value.length >= 3) { this.classList.remove('error'); this.style.borderColor = ''; document.getElementById('error-message').innerHTML = ''; } });案例3:图片懒加载
// 监听滚动事件实现图片懒加载 window.addEventListener('scroll', function() { let images = document.querySelectorAll('img[data-src]'); images.forEach(img => { // 判断图片是否进入可视区域 if (isInViewport(img)) { // 加载图片 img.src = img.getAttribute('data-src'); img.removeAttribute('data-src'); // 添加加载完成效果 img.addEventListener('load', function() { this.style.opacity = '1'; this.style.transition = 'opacity 0.5s'; }); } }); }); function isInViewport(element) { let rect = element.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); }三、BOM与DOM的关系与区别
| 特性 | BOM (Browser Object Model) | DOM (Document Object Model) |
|---|---|---|
| 作用对象 | 浏览器窗口、历史、位置等 | HTML/XML文档内容 |
| 顶层对象 | window | document |
| 标准化 | 没有统一标准,各浏览器实现有差异 | W3C标准,各浏览器基本一致 |
| 主要用途 | 浏览器控制、导航、窗口操作等 | 文档内容操作、样式修改、事件处理 |
| 包含关系 | BOM包含DOM(document是window的属性) | DOM是BOM的一部分 |
| 核心API | window、location、navigator、history、screen | document、元素节点、属性节点、文本节点等 |
四、最佳实践与注意事项
性能优化
// 避免频繁DOM操作 // 不好:多次重排 for (let i = 0; i < 100; i++) { element.style.left = i + 'px'; } // 好:使用文档片段 let fragment = document.createDocumentFragment(); for (let i = 0; i < 100; i++) { let div = document.createElement('div'); div.textContent = 'Item ' + i; fragment.appendChild(div); } document.body.appendChild(fragment);事件委托
// 不好:为每个列表项绑定事件 let items = document.querySelectorAll('.item'); items.forEach(item => { item.addEventListener('click', handleClick); }); // 好:使用事件委托 document.querySelector('.list').addEventListener('click', function(event) { if (event.target.classList.contains('item')) { handleClick(event); } });兼容性处理
// 添加事件监听的兼容写法 function addEvent(element, type, handler) { if (element.addEventListener) { element.addEventListener(type, handler, false); } else if (element.attachEvent) { element.attachEvent('on' + type, handler); } else { element['on' + type] = handler; } }内存管理
// 及时清理事件监听器 function createComponent() { let element = document.createElement('div'); let handler = () => console.log('click'); element.addEventListener('click', handler); // 提供清理方法 return { element: element, destroy: function() { element.removeEventListener('click', handler); element.remove(); } }; }
BOM和DOM共同构成了JavaScript在浏览器环境中的核心能力,BOM负责与浏览器窗口交互,DOM负责操作文档内容。在实际开发中,两者经常结合使用,例如通过BOM的window对象获取视口尺寸,然后通过DOM调整页面布局;或者通过DOM监听表单提交事件,然后使用BOM的location进行页面跳转。掌握这两者的API和使用场景,是进行前端开发的基础。
参考来源
- JavaScript中DOW和BOW;笔记分享;知识回顾
- JS(JavaScript)的DOM操作
- js:日期对象和dom节点
- 【Anime.js】——JavaScript动画库:Anime.js——学习笔记
- DOM 基础详解
- 黑马JS学习笔记——DOM