Skip to content

浏览器环境,规格

浏览器环境提供了 JavaScript 运行所需的所有功能,包括:

  1. 核心 JavaScript 语言:ECMAScript 规范定义的语言特性
  2. DOM(文档对象模型):用于操作 HTML 和 XML 文档
  3. BOM(浏览器对象模型):用于操作浏览器窗口和导航
  4. Web API:如 WebSocket、Web Storage、Web Workers 等

浏览器环境的主要对象

javascript
// 全局对象
window // 浏览器窗口对象
document // 文档对象
navigator // 浏览器信息对象
location // URL 对象
history // 历史记录对象
screen // 屏幕对象

DOM 树

DOM 树是 HTML 文档的树形结构表示,每个 HTML 元素都是一个节点:

  1. 文档节点:整个文档的根节点
  2. 元素节点:HTML 标签
  3. 文本节点:文本内容
  4. 属性节点:HTML 属性
  5. 注释节点:HTML 注释

DOM 树示例

html
<!DOCTYPE html>
<html>
  <head>
    <title>示例</title>
  </head>
  <body>
    <div class="container">
      <h1>标题</h1>
      <p>段落文本</p>
    </div>
  </body>
</html>

对应的 DOM 树结构:

Document
└── html
    ├── head
    │   └── title
    │       └── "示例"
    └── body
        └── div.container
            ├── h1
            │   └── "标题"
            └── p
                └── "段落文本"

遍历 DOM

1. 节点类型

javascript
// 节点类型常量
Node.ELEMENT_NODE // 1
Node.TEXT_NODE // 3
Node.COMMENT_NODE // 8
Node.DOCUMENT_NODE // 9

// 检查节点类型
element.nodeType === Node.ELEMENT_NODE

2. 节点属性

javascript
// 获取节点名称
element.nodeName // 元素标签名
element.nodeValue // 文本节点的内容

// 获取节点类型
element.nodeType // 节点类型数字

3. 遍历方法

javascript
// 遍历子节点
function traverseChildren(node) {
    let child = node.firstChild;
    while (child) {
        console.log(child.nodeName);
        child = child.nextSibling;
    }
}

// 遍历所有后代节点
function traverseDescendants(node) {
    let current = node.firstChild;
    while (current) {
        console.log(current.nodeName);
        if (current.firstChild) {
            traverseDescendants(current);
        }
        current = current.nextSibling;
    }
}

// 使用 TreeWalker 遍历
const walker = document.createTreeWalker(
    document.body,
    NodeFilter.SHOW_ELEMENT,
    null,
    false
);

let node;
while (node = walker.nextNode()) {
    console.log(node.nodeName);
}

4. 节点集合

javascript
// 获取所有子节点
const children = element.childNodes;

// 获取所有元素子节点
const elements = element.children;

// 获取第一个子节点
const firstChild = element.firstChild;

// 获取最后一个子节点
const lastChild = element.lastChild;

// 获取父节点
const parent = element.parentNode;

// 获取下一个兄弟节点
const nextSibling = element.nextSibling;

// 获取上一个兄弟节点
const previousSibling = element.previousSibling;

5. 节点操作

javascript
// 添加子节点
parent.appendChild(child);

// 在指定节点前插入
parent.insertBefore(newNode, referenceNode);

// 替换节点
parent.replaceChild(newNode, oldNode);

// 删除节点
parent.removeChild(child);

// 克隆节点
const clone = node.cloneNode(true); // true 表示深度克隆

Document 对象

Document 对象是 Web 页面的根节点,提供了对页面所有 HTML 元素的访问。

基本概念

Document 对象是 Window 对象的一部分,可通过 window.documentdocument 直接访问。

javascript
console.log(document === window.document); // true

常用属性

1. 文档元数据

javascript
// 获取文档标题
console.log(document.title);
// 设置文档标题
document.title = '新标题';

// 获取当前 URL
console.log(document.URL);

// 获取域名
console.log(document.domain);

// 获取最后修改日期
console.log(document.lastModified);

2. 文档状态

javascript
// 检查文档是否准备完毕
console.log(document.readyState); // 'loading', 'interactive' 或 'complete'

// DOM 内容加载完成事件
document.addEventListener('DOMContentLoaded', () => {
    console.log('DOM 已加载完成');
});

选择元素

1. 通过 ID 选择

javascript
const element = document.getElementById('myId');

2. 通过类名选择

javascript
const elements = document.getElementsByClassName('myClass');

3. 通过标签名选择

javascript
const elements = document.getElementsByTagName('div');

4. 通过 CSS 选择器选择

javascript
// 选择第一个匹配的元素
const element = document.querySelector('.myClass');

// 选择所有匹配的元素
const elements = document.querySelectorAll('div.item');

创建和修改元素

1. 创建元素

javascript
// 创建新元素
const div = document.createElement('div');
div.className = 'container';
div.textContent = '这是一个新元素';

// 添加到文档
document.body.appendChild(div);

2. 插入 HTML

javascript
// 使用 innerHTML
element.innerHTML = '<span>新内容</span>';

// 使用 insertAdjacentHTML
element.insertAdjacentHTML('beforeend', '<span>新内容</span>');

3. 删除元素

javascript
// 删除子元素
parent.removeChild(child);

// 元素自删除
element.remove();

操作属性

1. 获取和设置属性

javascript
// 获取属性
const value = element.getAttribute('data-id');

// 设置属性
element.setAttribute('data-id', '123');

// 删除属性
element.removeAttribute('data-id');

2. 数据属性

javascript
// 使用 dataset 访问 data-* 属性
element.dataset.id = '123';
console.log(element.dataset.id); // '123'

DOM 遍历

1. 父子关系

javascript
// 获取父元素
const parent = element.parentNode;

// 获取子元素
const children = element.children;
const firstChild = element.firstElementChild;
const lastChild = element.lastElementChild;

2. 兄弟关系

javascript
// 获取前一个兄弟元素
const prev = element.previousElementSibling;

// 获取后一个兄弟元素
const next = element.nextElementSibling;

操作样式

1. 内联样式

javascript
// 设置内联样式
element.style.color = 'red';
element.style.fontSize = '16px';

// 获取内联样式
console.log(element.style.color);

2. 计算样式

javascript
// 获取计算后的样式
const style = window.getComputedStyle(element);
console.log(style.color);

3. 类操作

javascript
// 添加类
element.classList.add('active');

// 删除类
element.classList.remove('active');

// 切换类
element.classList.toggle('active');

// 检查是否包含类
console.log(element.classList.contains('active'));

事件管理

javascript
// 添加事件监听器
document.addEventListener('click', function(event) {
    console.log('点击了文档');
});

// 移除事件监听器
document.removeEventListener('click', handler);

文档片段

javascript
// 创建文档片段(提高性能)
const fragment = document.createDocumentFragment();

// 添加多个元素到片段
for (let i = 0; i < 10; i++) {
    const div = document.createElement('div');
    div.textContent = `项目 ${i}`;
    fragment.appendChild(div);
}

// 一次性添加到 DOM
document.body.appendChild(fragment);

表单操作

javascript
// 获取表单
const form = document.forms[0]; // 或 document.forms['myForm']

// 获取表单元素
const input = form.elements['username'];

// 表单提交
form.addEventListener('submit', function(event) {
    event.preventDefault(); // 阻止默认提交
    console.log('表单提交');
});

性能优化

1. 避免频繁 DOM 操作

javascript
// 不好的做法
for (let i = 0; i < 1000; i++) {
    document.body.innerHTML += `<div>${i}</div>`;
}

// 好的做法
let html = '';
for (let i = 0; i < 1000; i++) {
    html += `<div>${i}</div>`;
}
document.body.innerHTML = html;

2. 使用事件委托

javascript
// 不好的做法:为每个按钮添加事件
const buttons = document.querySelectorAll('button');
buttons.forEach(button => {
    button.addEventListener('click', handleClick);
});

// 好的做法:使用事件委托
document.addEventListener('click', function(event) {
    if (event.target.tagName === 'BUTTON') {
        handleClick(event);
    }
});

安全考虑

1. 防止 XSS 攻击

javascript
// 不安全的做法
element.innerHTML = userInput;

// 安全的做法
element.textContent = userInput;

2. 安全地插入 HTML

javascript
// 使用 DOMPurify 库清理 HTML
const clean = DOMPurify.sanitize(userInput);
element.innerHTML = clean;

最佳实践

  1. 尽量减少 DOM 操作,避免重绘和重排
  2. 使用事件委托处理多元素事件
  3. 使用文档片段进行批量操作
  4. 缓存频繁使用的 DOM 引用
  5. 使用 querySelector 而非较旧的 DOM 选择方法
  6. 小心处理用户输入,防止 XSS 攻击
  7. 利用 dataset 属性存储数据,避免自定义属性