JavaScript 浏览器特有内置对象和方法

简介

本文档介绍 浏览器环境中特有的内置对象和方法。这些 API 由浏览器(如 Chrome 的 V8 引擎所在的运行时)提供,不属于 ECMAScript 标准,因此在 Node.js 中不可用。

参考文档

  • js-builtins.md — V8/ECMAScript 标准内置对象(Math、Date、JSON、Map、Set、Symbol 等)
  • js-runtime.md — 浏览器和 Node.js 运行时对比

window 对象

window 是浏览器的全局对象。所有全局变量和函数都是 window 的属性。

基本用法

console.log(window);  // Window 对象

// 全局变量自动成为 window 的属性
var globalVar = 'hello';
console.log(window.globalVar);  // "hello"

// 全局函数
window.alert('Hello!');

// 在全局作用域中,this 指向 window(非严格模式)
console.log(this === window);  // true

弹窗函数

// alert — 提示框(只有"确定"按钮)
alert('操作成功!');

// confirm — 确认框(有"确定"和"取消")
let result = confirm('确定要删除吗?');
console.log(result);  // 点击"确定"返回 true,否则 false

// prompt — 输入框(返回输入的字符串或 null)
let name = prompt('请输入姓名:', '默认名');  // 第二个参数是默认值
if (name !== null) {
  console.log('你好,' + name);
}

注意:现代 Web 开发中不推荐使用这些弹窗,因为它们会阻塞线程且体验不佳,应使用自定义的模态框代替。


Document 对象(DOM)

documentwindow 的属性,表示当前网页的文档对象。

查找元素

// 通过 ID 查找(返回单个元素)
let title = document.getElementById('title');
console.log(title.textContent);

// 通过 CSS 选择器查找
let firstItem = document.querySelector('.item');   // 第一个匹配的元素
let allItems = document.querySelectorAll('.item'); // 所有匹配的元素(NodeList)

// 通过标签名、类名、名称查找
let divs = document.getElementsByTagName('div');
let items = document.getElementsByClassName('item');
let inputs = document.getElementsByName('username');

创建和插入元素

// 创建新元素
let div = document.createElement('div');
div.id = 'my-div';
div.className = 'container';
div.textContent = 'Hello World';

// 插入到页面
document.body.appendChild(div);  // 追加为最后一个子元素

let parent = document.getElementById('container');
let referenceNode = document.getElementById('ref');
parent.insertBefore(div, referenceNode);  // 插入到参考节点之前

// 现代方法(ES6+)
parent.prepend(div);   // 插入到开头
parent.append(div);    // 插入到末尾(可插入多个)
parent.before(div);   // 插入到元素前
parent.after(div);     // 插入到元素后

修改元素内容和属性

let elem = document.getElementById('my-element');

// 文本内容
elem.textContent = '新文本';           // 只设置/获取文本内容
elem.innerText = '新文本';            // 考虑样式的文本(不包含隐藏元素文本)

// HTML 内容(注意 XSS 风险)
elem.innerHTML = '<strong>加粗文本</strong>';  // 解析 HTML
elem.insertAdjacentHTML('beforeend', '<p>追加的内容</p>');
// 位置参数:beforebegin / afterbegin / beforeend / afterend

// 属性操作
elem.setAttribute('data-id', '123');
console.log(elem.getAttribute('data-id'));  // "123"
elem.removeAttribute('data-id');

// className 和 classList
elem.className = 'btn btn-primary';  // 设置类名(覆盖)
elem.classList.add('active');         // 添加类
elem.classList.remove('active');       // 移除类
elem.classList.toggle('active');       // 切换类
console.log(elem.classList.contains('active'));  // 是否包含类

// style 样式
elem.style.color = 'red';
elem.style.backgroundColor = 'blue';
elem.style.display = 'none';

删除元素

let elem = document.getElementById('to-remove');
elem.remove();  // 现代方法(ES6)

// 传统方法
if (elem.parentNode) {
  elem.parentNode.removeChild(elem);
}

事件监听

let btn = document.getElementById('my-btn');

// addEventListener — 推荐方式(可添加多个监听)
btn.addEventListener('click', function(event) {
  console.log('按钮被点击了!');
  console.log(event.target);  // 触发事件的元素
});

// 带选项的参数
btn.addEventListener('click', handler, {
  capture: false,   // 是否在捕获阶段(默认 false = 冒泡阶段)
  once: true          // 只执行一次
});

// 移除监听
function handler() { console.log('clicked'); }
btn.addEventListener('click', handler);
btn.removeEventListener('click', handler);

// 传统方式(不推荐,只能设置一个)
// btn.onclick = function() { console.log('clicked'); };
// btn.onclick = null;  // 移除

// 事件对象常用属性
btn.addEventListener('click', (e) => {
  e.preventDefault();   // 阻止默认行为(如链接跳转、表单提交)
  e.stopPropagation(); // 阻止事件冒泡
  console.log(e.type);    // "click"(事件类型)
  console.log(e.clientX, e.clientY);  // 鼠标坐标
});

事件传播:冒泡和捕获

// 冒泡(默认):从内到外
// 捕获:从外到内(addEventListener 第三个参数设为 true)

<div id="outer">
  <button id="inner">点击</button>
</div>

<script>
  let outer = document.getElementById('outer');
  let inner = document.getElementById('inner');

  // 捕获阶段
  outer.addEventListener('click', () => console.log('外层捕获'), true);

  // 冒泡阶段(默认)
  outer.addEventListener('click', () => console.log('外层冒泡'));
  inner.addEventListener('click', () => console.log('内层冒泡'));

  // 点击按钮输出顺序:
  // 外层捕获 → 内层冒泡 → 外层冒泡
</script>

常用事件速查表

事件类型 说明 适用元素
click 点击事件 大部分元素
dblclick 双击事件 大部分元素
mousedown / mouseup 鼠标按下/松开 大部分元素
mousemove 鼠标移动 大部分元素
keydown / keyup 键盘按下/松开 可聚焦元素
input 输入内容变化 input、textarea
change 值改变并提交 input、select
submit 表单提交 form
load 资源加载完成 window、img 等
DOMContentLoaded DOM 解析完成 document
resize 窗口大小变化 window
scroll 滚动 window、可滚动元素
focus / blur 获取/失去焦点 可聚焦元素

BOM(浏览器对象模型)

BOM 提供了与浏览器窗口交互的 API。

console.log(navigator.userAgent);    // 浏览器 UA 字符串
console.log(navigator.language);     // 浏览器语言(如 "zh-CN")
console.log(navigator.languages);    // 支持的语言列表
console.log(navigator.onLine);      // 是否在线
console.log(navigator.platform);     // 操作系统平台

// 检查是否在线
if (navigator.onLine) {
  console.log('当前在线');
} else {
  console.log('当前离线');
}

location — URL 信息

// location 对象包含当前 URL 的信息
console.log(location.href);      // 完整 URL
console.log(location.protocol);  // 协议(如 "https:")
console.log(location.host);      // 主机名+端口(如 "example.com:8080")
console.log(location.hostname);  // 主机名(如 "example.com")
console.log(location.port);      // 端口(如 "8080")
console.log(location.pathname);  // 路径(如 "/page/index.html")
console.log(location.search);    // 查询字符串(如 "?id=1&sort=name")
console.log(location.hash);      // 哈希(如 "#section1")

// 跳转(修改 location)
location.href = 'https://example.com';  // 跳转到新页面
location.assign('https://example.com');  // 同上,可跳转历史记录
location.replace('https://example.com'); // 替换当前页面(无历史记录)
location.reload();                  // 重新加载当前页面
location.reload(true);              // 强制从服务器重新加载(跳过缓存)

history — 浏览历史

// 前进后退
history.back();     // 后退一页
history.forward();  // 前进一页
history.go(-2);   // 后退两页(正数则前进)

// HTML5 History API(单页应用常用)
history.pushState({ page: 1 }, 'Title', '?page=1');  // 添加历史记录,不刷新页面
history.replaceState({ page: 2 }, 'Title', '?page=2'); // 替换当前历史记录

// 监听历史变化
window.addEventListener('popstate', (event) => {
  console.log('状态:', event.state);
});

screen — 屏幕信息

console.log(screen.width);   // 屏幕宽度
console.log(screen.height);  // 屏幕高度
console.log(screen.availWidth);  // 可用宽度(扣除任务栏等)
console.log(screen.availHeight); // 可用高度
console.log(screen.colorDepth);  // 颜色深度(如 24)

localStorage 和 sessionStorage

// localStorage — 持久化存储(除非手动清除,否则永久保存)
localStorage.setItem('theme', 'dark');
console.log(localStorage.getItem('theme'));  // "dark"
localStorage.removeItem('theme');
localStorage.clear();  // 清空所有数据

// 存储对象(需要序列化)
let user = { name: 'Alice', age: 25 };
localStorage.setItem('user', JSON.stringify(user));
let savedUser = JSON.parse(localStorage.getItem('user'));
console.log(savedUser.name);  // "Alice"

// sessionStorage — 会话存储(关闭标签页后清除)
sessionStorage.setItem('temp', 'value');
console.log(sessionStorage.getItem('temp'));  // "value"
// 关闭标签页后数据自动清除

// 存储事件(其他标签页修改 storage 时触发)
window.addEventListener('storage', (event) => {
  console.log('key:', event.key, 'old:', event.oldValue, 'new:', event.newValue);
});
特性 localStorage sessionStorage
生命周期 永久(除非手动清除) 标签页关闭后清除
作用域 同源的所有标签页 仅当前标签页
容量 约 5MB 约 5MB
API setItem/getItem/removeItem/clear 同上

浏览器全局函数

定时器(setTimeout / setInterval)

// setTimeout — 延迟执行一次
let timer1 = setTimeout(() => {
  console.log('1 秒后执行');
}, 1000);
clearTimeout(timer1);  // 取消定时器

// setInterval — 循环执行
let timer2 = setInterval(() => {
  console.log('每秒执行一次');
}, 1000);
clearInterval(timer2);  // 停止循环

// requestAnimationFrame — 动画帧(浏览器专有)
// let frameId;
// function animate() {
//   // 更新动画逻辑
//   frameId = requestAnimationFrame(animate);
// }
// cancelAnimationFrame(frameId);  // 停止动画

注意:更多定时器内容已添加在 js-builtins.md 的"定时器函数"章节,包括 setTimeout vs setInterval 对比、this 指向、防抖节流实现等。

fetch — 网络请求(现代方式)

// 基本 GET 请求
fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) throw new Error('请求失败');
    return response.json();  // 解析 JSON
  })
  .then(data => console.log(data))
  .catch(error => console.error('错误:', error));

// POST 请求
fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ name: 'Alice', age: 25 })
})
  .then(response => response.json())
  .then(data => console.log('创建成功:', data))
  .catch(console.error);

// 使用 async/await
async function getData() {
  try {
    let response = await fetch('https://api.example.com/data');
    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('请求失败:', error);
  }
}

XMLHttpRequest(传统方式,了解即可)

let xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data');
xhr.onreadystatechange = function() {
  if (xhr.readyState === 4) {  // 请求完成
    if (xhr.status === 200) {
      console.log(JSON.parse(xhr.responseText));
    } else {
      console.error('请求失败:', xhr.status);
    }
  }
};
xhr.send();

console 对象

console.log('普通日志');           // 普通输出
console.warn('警告信息');           // 黄色警告
console.error('错误信息');          // 红色错误
console.info('提示信息');           // 提示(部分浏览器同 log)
console.debug('调试信息');          // 调试

// 格式化输出
console.log('姓名: %s, 年龄: %d', 'Alice', 25);  // 格式化字符串
console.log('%c红色文字', 'color: red; font-size: 20px');  // 样式(Chrome)

// 分组
console.group('用户详情');
console.log('姓名: Alice');
console.log('年龄: 25');
console.groupEnd();

// 计时
console.time('循环耗时');
for (let i = 0; i < 100000; i++) {}
console.timeEnd('循环耗时');  // 输出耗时

// 表格
console.table([{ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }]);

// 断言
console.assert(1 === 2, '1 不等于 2');  // 条件为假时输出错误

Canvas(简要)

canvas 元素用于通过 JavaScript 绘制图形。

let canvas = document.getElementById('my-canvas');
let ctx = canvas.getContext('2d');

// 绘制矩形
ctx.fillStyle = 'blue';
ctx.fillRect(10, 10, 100, 50);  // x, y, width, height

ctx.strokeStyle = 'red';
ctx.strokeRect(120, 10, 100, 50);  // 描边矩形

// 绘制文本
ctx.font = '20px Arial';
ctx.fillStyle = 'black';
ctx.fillText('Hello Canvas', 10, 80);

// 绘制路径(线条)
ctx.beginPath();
ctx.moveTo(10, 100);   // 起点
ctx.lineTo(100, 100);  // 画线到
ctx.lineTo(100, 150);
ctx.stroke();           // 描边

WebSocket(简要)

WebSocket 提供浏览器与服务器之间的持久连接(全双工通信)。

// 创建 WebSocket 连接
let ws = new WebSocket('ws://localhost:8080');

// 连接建立
ws.onopen = () => {
  console.log('连接已建立');
  ws.send(JSON.stringify({ type: 'hello', data: 'Hello Server' }));
};

// 接收消息
ws.onmessage = (event) => {
  console.log('收到消息:', event.data);
};

// 连接关闭
ws.onclose = (event) => {
  console.log('连接关闭:', event.code, event.reason);
};

// 发生错误
ws.onerror = (error) => {
  console.error('WebSocket 错误:', error);
};

Web Workers(简要)

Worker 允许在后台线程中运行脚本,不阻塞主线程。

// 主线程
let worker = new Worker('worker.js');

worker.postMessage({ type: 'start', data: [1, 2, 3] });

worker.onmessage = (event) => {
  console.log('Worker 返回:', event.data);
};

worker.onerror = (error) => {
  console.error('Worker 错误:', error);
};

// worker.js(单独的文件)
// self.addEventListener('message', (e) => {
//   let result = e.data.data.map(x => x * 2);
//   self.postMessage(result);
// });

综合示例

示例 1:DOM 操作 — 简易待办事项

// HTML:
// <input id="todo-input"><button id="add-btn">添加</button>
// <ul id="todo-list"></ul>

let input = document.getElementById('todo-input');
let button = document.getElementById('add-btn');
let list = document.getElementById('todo-list');

button.addEventListener('click', () => {
  let text = input.value.trim();
  if (!text) return;

  let li = document.createElement('li');
  li.textContent = text;

  let removeBtn = document.createElement('button');
  removeBtn.textContent = '删除';
  removeBtn.addEventListener('click', () => li.remove());

  li.appendChild(removeBtn);
  list.appendChild(li);
  input.value = '';
});

示例 2:AJAX 请求 + localStorage 缓存

async function fetchWithCache(url) {
  let cacheKey = 'cache:' + url;

  // 先检查缓存
  let cached = localStorage.getItem(cacheKey);
  if (cached) {
    console.log('从缓存读取');
    return JSON.parse(cached);
  }

  // 发起请求
  try {
    let response = await fetch(url);
    if (!response.ok) throw new Error('请求失败');
    let data = await response.json();

    // 存入缓存(有效期 5 分钟)
    let cacheData = { data, expiry: Date.now() + 5 * 60 * 1000 };
    localStorage.setItem(cacheKey, JSON.stringify(cacheData));

    return data;
  } catch (error) {
    console.error('请求失败:', error);
    return null;
  }
}

// 使用时检查缓存是否过期
function getCachedData(key) {
  let cached = localStorage.getItem(key);
  if (!cached) return null;

  let { data, expiry } = JSON.parse(cached);
  if (Date.now() > expiry) {
    localStorage.removeItem(key);
    return null;  // 缓存过期
  }
  return data;
}

示例 3:监听页面可见性

// 当页面隐藏/显示时(切换标签页、最小化等)
document.addEventListener('visibilitychange', () => {
  if (document.hidden) {
    console.log('页面被隐藏,暂停动画/视频');
  } else {
    console.log('页面重新可见,恢复动画/视频');
  }
});

示例 4:表单验证 + 即时反馈

let emailInput = document.getElementById('email');
let feedback = document.getElementById('email-feedback');

emailInput.addEventListener('input', () => {
  let email = emailInput.value;
  if (!email) {
    feedback.textContent = '邮箱不能为空';
    feedback.style.color = 'red';
  } else if (!email.includes('@')) {
    feedback.textContent = '邮箱格式不正确';
    feedback.style.color = 'red';
  } else {
    feedback.textContent = '✓ 格式正确';
    feedback.style.color = 'green';
  }
});

总结:浏览器特有 API 速查表

类别 主要对象/方法 说明
全局对象 window 浏览器全局对象
弹窗 alert()confirm()prompt() 不推荐用于生产环境
DOM documentgetElementById()querySelector() 操作网页元素
事件 addEventListener()removeEventListener() 事件监听
BOM - Navigator navigator 浏览器信息
BOM - Location location URL 操作
BOM - History history 浏览历史
BOM - Screen screen 屏幕信息
存储 localStoragesessionStorage 本地存储
网络 fetch()XMLHttpRequest HTTP 请求
定时器 setTimeout()setInterval()requestAnimationFrame() 延迟/循环执行
调试 console 控制台输出
图形 canvas 2D/3D 绘图
通信 WebSocket 持久连接
多线程 Worker 后台线程

重要提示:本文档介绍的是浏览器特有的 API。ECMAScript 标准内置对象(Math、Date、JSON、Map、Set、Promise 等)请参考 js-builtins.md