深入理解浏览器中的 JavaScript:BOM、DOM、网络与性能优化

个人空间:

https://blog.csdn.net/m0_73589512https://blog.csdn.net/m0_73589512?spm=1011.2415.3001.5343接续上文:

https://blog.csdn.net/m0_73589512/article/details/157698485?https://blog.csdn.net/m0_73589512/article/details/157698485?spm=1001.2014.3001.5501

目录

[深入理解浏览器中的 JavaScript:BOM、DOM、网络与性能优化](#深入理解浏览器中的 JavaScript:BOM、DOM、网络与性能优化)

一、BOM:浏览器对象模型

[1.1 location 对象:URL 操作核心](#1.1 location 对象:URL 操作核心)

[核心属性(URL 解析)](#核心属性(URL 解析))

核心方法(页面导航)

关键考点:同源判断

[1.2 history 对象:历史记录与 SPA 路由](#1.2 history 对象:历史记录与 SPA 路由)

核心方法与属性

[关键考点:popstate 事件](#关键考点:popstate 事件)

[1.3 navigator 对象:浏览器与系统信息](#1.3 navigator 对象:浏览器与系统信息)

核心用法

[1.4 screen 与元素尺寸:视口与布局计算](#1.4 screen 与元素尺寸:视口与布局计算)

核心尺寸属性

[关键考点:clientHeight vs offsetHeight](#关键考点:clientHeight vs offsetHeight)

二、DOM:文档对象模型与事件系统

[2.1 事件模型:捕获与冒泡](#2.1 事件模型:捕获与冒泡)

事件流详解

事件对象核心方法(面试高频)

[2.2 事件委托:性能优化核心](#2.2 事件委托:性能优化核心)

[传统方式 vs 事件委托](#传统方式 vs 事件委托)

[三、网络请求:XMLHttpRequest 与缓存策略](#三、网络请求:XMLHttpRequest 与缓存策略)

[3.1 XMLHttpRequest 完整用法](#3.1 XMLHttpRequest 完整用法)

[3.2 核心考点:HTTP 方法与状态码](#3.2 核心考点:HTTP 方法与状态码)

[常用 HTTP 方法(RESTful 规范)](#常用 HTTP 方法(RESTful 规范))

关键状态码

[3.3 缓存策略:强缓存与协商缓存](#3.3 缓存策略:强缓存与协商缓存)

[缓存优先策略示例(Service Worker)](#缓存优先策略示例(Service Worker))

四、核心面试考点与性能优化

[4.1 高频面试题总结](#4.1 高频面试题总结)

[4.2 性能优化实战](#4.2 性能优化实战)

[1. 减少重排重绘](#1. 减少重排重绘)

[2. 防抖与节流](#2. 防抖与节流)

[3. 虚拟列表(大数据渲染优化)](#3. 虚拟列表(大数据渲染优化))

五、总结

[浏览器 JS 核心面试题汇总(高频考点 + 标准答案)](#浏览器 JS 核心面试题汇总(高频考点 + 标准答案))

一、BOM(浏览器对象模型)高频题

[1. 什么是同源策略?同源的判断依据是什么?](#1. 什么是同源策略?同源的判断依据是什么?)

[2. location.assign ()、location.replace ()、location.reload () 的区别?](#2. location.assign ()、location.replace ()、location.reload () 的区别?)

[3. history.pushState () 和 history.replaceState () 的作用?如何监听浏览器前进 / 后退?](#3. history.pushState () 和 history.replaceState () 的作用?如何监听浏览器前进 / 后退?)

[4. 如何通过 navigator 判断浏览器类型和设备类型?](#4. 如何通过 navigator 判断浏览器类型和设备类型?)

[5. clientHeight、offsetHeight、scrollHeight 的区别?](#5. clientHeight、offsetHeight、scrollHeight 的区别?)

[二、DOM 事件模型高频题](#二、DOM 事件模型高频题)

[1. JS 事件流的三个阶段是什么?如何控制事件传播?](#1. JS 事件流的三个阶段是什么?如何控制事件传播?)

[2. 什么是事件委托?它的优势是什么?适用场景?](#2. 什么是事件委托?它的优势是什么?适用场景?)

[3. event.preventDefault () 和 event.stopPropagation () 的区别?](#3. event.preventDefault () 和 event.stopPropagation () 的区别?)

[4. 相同元素绑定多个同类事件,执行顺序是什么?如何阻止?](#4. 相同元素绑定多个同类事件,执行顺序是什么?如何阻止?)

三、网络请求与缓存高频题

[1. XMLHttpRequest 的核心步骤是什么?readyState 的取值含义?](#1. XMLHttpRequest 的核心步骤是什么?readyState 的取值含义?)

[2. HTTP 状态码 304 的含义是什么?与浏览器缓存的关系?](#2. HTTP 状态码 304 的含义是什么?与浏览器缓存的关系?)

[3. RESTful API 的核心规范是什么?常用 HTTP 方法的含义?](#3. RESTful API 的核心规范是什么?常用 HTTP 方法的含义?)

[4. 什么是跨域?OPTIONS 请求的作用是什么?](#4. 什么是跨域?OPTIONS 请求的作用是什么?)

四、性能优化高频题

[1. 如何减少 DOM 重排和重绘?](#1. 如何减少 DOM 重排和重绘?)

[2. 防抖和节流的区别是什么?实现原理?适用场景?](#2. 防抖和节流的区别是什么?实现原理?适用场景?)

[3. 浏览器的渲染流程是什么?如何优化渲染性能?](#3. 浏览器的渲染流程是什么?如何优化渲染性能?)

五、核心误区辨析题

[1. HTTP 协议和 XMLHttpRequest/Fetch/axios 的关系?](#1. HTTP 协议和 XMLHttpRequest/Fetch/axios 的关系?)

[2. history 模式和 hash 模式的 SPA 路由有什么区别?](#2. history 模式和 hash 模式的 SPA 路由有什么区别?)


深入理解浏览器中的 JavaScript:BOM、DOM、网络与性能优化

JavaScript 在浏览器中的运行离不开三大核心体系:BOM(浏览器对象模型)、DOM(文档对象模型)和网络请求 。它们共同支撑起前端交互、页面操作和数据通信的基础,也是面试高频考点。本文将系统拆解这些核心知识点,结合实战案例和面试方向,帮你建立完整的浏览器 JS 知识体系。

一、BOM:浏览器对象模型

BOM(Browser Object Model)是操作浏览器功能的 API 集合,核心对象包括locationhistorynavigatorscreen,直接对接浏览器的地址栏、历史记录、系统信息等功能。

1.1 location 对象:URL 操作核心

location封装了当前页面的 URL 信息,提供了 URL 解析和导航功能,是路由管理、地址跳转的关键。

核心属性(URL 解析)

https://www.hkc.com:8080/search?class=browser#comments 为例:

复制代码
console.log(location.href);      // 完整URL:"https://www.hkc.com:8080/search?class=browser#comments"
console.log(location.protocol);  // 协议:"https:"
console.log(location.host);      // 主机(含端口):"www.hkc.com:8080"
console.log(location.hostname);  // 主机名:"www.hkc.com"
console.log(location.port);      // 端口:"8080"
console.log(location.pathname);  // 路径:"/search"
console.log(location.search);    // 查询字符串:"?class=browser"
console.log(location.hash);      // 锚点:"#comments"
console.log(location.origin);    // 源(协议+域名+端口):"https://www.hkc.com:8080"
核心方法(页面导航)
复制代码
location.assign('https://new.url');  // 导航到新URL,保留历史记录(可后退)
location.replace('https://new.url'); // 替换当前URL,不保留历史记录(不可后退)
location.reload();                  // 重新加载页面(默认使用缓存)
location.reload(true);              // 强制从服务器加载(忽略缓存)
关键考点:同源判断

"同源" 指 协议、域名、端口号完全相同,是浏览器跨域限制的核心依据。例如:

  • https://www.hkc.comhttp://www.hkc.com 不同源(协议不同)

  • https://www.hkc.comhttps://blog.hkc.com 不同源(域名不同)

  • https://www.hkc.com:80https://www.hkc.com:8080 不同源(端口不同)

1.2 history 对象:历史记录与 SPA 路由

history 管理浏览器的会话历史,核心用于单页应用(SPA)的路由控制,避免页面刷新。

核心方法与属性
复制代码
// 添加历史记录(不刷新页面)
history.pushState({ page: 1 }, '页面1', '/page1'); 
// 替换当前历史记录(不刷新页面)
history.replaceState({ page: 2 }, '页面2', '/page2');
// 获取当前状态数据
console.log(history.state); // { page: 2 }
// 历史记录长度
console.log(history.length); // 2
​
// 前进/后退操作
history.back();    // 后退一步(等同于点击浏览器后退按钮)
history.forward(); // 前进一步(等同于点击浏览器前进按钮)
history.go(-2);    // 后退两步(参数为正数前进,负数后退)
关键考点:popstate 事件

监听浏览器前进 / 后退操作,实现 SPA 路由切换:

复制代码
window.addEventListener('popstate', (event) => {
  console.log('路由变化:', event.state); // 获取pushState/replaceState存储的状态
  // 执行路由更新逻辑
});

navigator 提供浏览器和操作系统的核心信息,常用于浏览器兼容性判断、用户画像收集

核心用法
复制代码
// 用户代理字符串(关键!判断浏览器类型)
const ua = navigator.userAgent; 
// 示例:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...
​
// 浏览器检测函数(面试高频)
function detectBrowser() {
  const ua = navigator.userAgent.toLowerCase();
  return {
    isChrome: ua.includes('chrome') && !ua.includes('edge'),
    isFirefox: ua.includes('firefox'),
    isSafari: ua.includes('safari') && !ua.includes('chrome'),
    isEdge: ua.includes('edge'),
    isIE: ua.includes('trident') || ua.includes('msie'),
    isMobile: /mobile|android|iphone/i.test(ua)
  };
}
​
// 其他常用属性
console.log(navigator.language);    // 浏览器语言:"zh-CN"
console.log(navigator.onLine);      // 是否在线:true/false
console.log(navigator.cookieEnabled); // 是否启用Cookie:true/false
​
// 现代API(拓展功能)
navigator.clipboard.readText(); // 读取剪贴板(需授权)
navigator.geolocation.getCurrentPosition(pos => { // 获取地理位置
  console.log('经纬度:', pos.coords.latitude, pos.coords.longitude);
});

1.4 screen 与元素尺寸:视口与布局计算

screen 描述屏幕信息,结合元素尺寸属性,可实现响应式布局、元素定位等功能。

核心尺寸属性
复制代码
// 视口尺寸(浏览器可视区域)
const viewport = {
  innerWidth: window.innerWidth,  // 视口宽度(含滚动条)
  innerHeight: window.innerHeight, // 视口高度
  outerWidth: window.outerWidth,  // 浏览器窗口总宽度
  outerHeight: window.outerHeight // 浏览器窗口总高度
};
​
// 屏幕尺寸
const screenInfo = {
  width: screen.width,          // 屏幕总宽度
  height: screen.height,        // 屏幕总高度
  availWidth: screen.availWidth, // 屏幕可用宽度(不含任务栏)
  availHeight: screen.availHeight // 屏幕可用高度
};
​
// 元素尺寸(面试高频考点)
const el = document.getElementById('myEl');
const elSize = {
  // client:内容+内边距,不含边框、滚动条、外边距
  clientWidth: el.clientWidth,
  clientHeight: el.clientHeight,
  // offset:内容+内边距+边框+滚动条
  offsetWidth: el.offsetWidth,
  offsetHeight: el.offsetHeight,
  offsetTop: el.offsetTop, // 相对于父定位元素的顶部距离
  offsetLeft: el.offsetLeft, // 相对于父定位元素的左侧距离
  // scroll:元素实际内容尺寸(含滚动隐藏部分)
  scrollWidth: el.scrollWidth,
  scrollHeight: el.scrollHeight,
  scrollTop: el.scrollTop, // 垂直滚动距离
  scrollLeft: el.scrollLeft // 水平滚动距离
};
关键考点:clientHeight vs offsetHeight
  • clientHeight:内容区 + 内边距(padding),不含边框、滚动条、外边距;

  • offsetHeight:内容区 + 内边距 + 边框(border) + 滚动条,不含外边距。

二、DOM:文档对象模型与事件系统

DOM(Document Object Model)是 HTML 文档的结构化表示,提供了操作页面元素的 API。核心重点是 事件模型元素操作

2.1 事件模型:捕获与冒泡

JS 的事件传播遵循 "捕获→目标→冒泡" 的完整流程,这是事件委托的核心原理。

事件流详解
复制代码
<div id="parent">
  <button id="child">点击我</button>
</div>
复制代码
// 捕获阶段:从顶层(document)到目标元素(child)
document.addEventListener('click', () => console.log('捕获:document'), true);
parent.addEventListener('click', () => console.log('捕获:parent'), true);
​
// 冒泡阶段:从目标元素(child)到顶层(document)
parent.addEventListener('click', () => console.log('冒泡:parent'), false);
document.addEventListener('click', () => console.log('冒泡:document'), false);

点击按钮后输出顺序:

复制代码
捕获:document → 捕获:parent → 冒泡:parent → 冒泡:document
事件对象核心方法(面试高频)
复制代码
element.addEventListener('click', (event) => {
  // 阻止事件传播(停止捕获/冒泡)
  event.stopPropagation();
  
  // 阻止同元素的其他事件监听器执行
  event.stopImmediatePropagation();
  
  // 阻止默认行为(如a标签跳转、表单提交)
  event.preventDefault();
  
  // 关键属性
  console.log(event.target);        // 实际触发事件的元素(点击的按钮)
  console.log(event.currentTarget); // 绑定事件的元素(parent)
  console.log(event.eventPhase);    // 事件阶段:1=捕获,2=目标,3=冒泡
});

2.2 事件委托:性能优化核心

事件委托利用 冒泡机制,将子元素的事件统一绑定到父元素,减少事件监听器数量,提升性能(尤其适用于列表、动态渲染元素)。

传统方式 vs 事件委托
复制代码
<ul class="list">
  <li>项目1</li>
  <li>项目2</li>
  <li>项目3</li>
  <!-- 可能动态添加更多li -->
</ul>

传统方式(低效)

复制代码
const lis = document.querySelectorAll('li');
lis.forEach(li => {
  li.addEventListener('click', () => {
    console.log('点击了:', li.textContent);
  });
});
// 动态添加的li需要重新绑定事件

事件委托(高效)

复制代码
const list = document.querySelector('.list');
list.addEventListener('click', (event) => {
  // 判断点击的是li元素
  if (event.target.tagName === 'LI') {
    console.log('点击了:', event.target.textContent);
    // 获取li索引
    const index = Array.from(list.children).indexOf(event.target);
    console.log('索引:', index);
  }
});
// 动态添加的li自动继承事件,无需重新绑定

三、网络请求:XMLHttpRequest 与缓存策略

前端与后端通信的核心是网络请求,XMLHttpRequest 是传统方案,现代开发中常用 Fetch API 或 Axios,但理解 XHR 是掌握网络请求原理的关键

3.1 XMLHttpRequest 完整用法

复制代码
// 1. 创建XHR对象
const xhr = new XMLHttpRequest();
​
// 2. 配置请求(方法、URL、异步标识)
xhr.open('POST', 'https://api.example.com/data', true);
​
// 3. 设置请求头
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Bearer token123');
​
// 4. 监听状态变化
xhr.onreadystatechange = function() {
  // readyState=4 表示请求完成
  if (xhr.readyState === XMLHttpRequest.DONE) {
    if (xhr.status >= 200 && xhr.status < 300) {
      // 成功:解析响应数据
      const data = JSON.parse(xhr.responseText);
      console.log('请求成功:', data);
    } else {
      // 失败:处理错误
      console.error('请求失败:', xhr.status);
    }
  }
};
​
// 5. 监听进度(可选)
xhr.upload.onprogress = (e) => {
  if (e.lengthComputable) {
    const progress = (e.loaded / e.total) * 100;
    console.log('上传进度:', progress + '%');
  }
};
​
// 6. 发送请求(POST请求需传参)
xhr.send(JSON.stringify({ username: 'test' }));
​
// 7. 中止请求(可选)
// xhr.abort();

3.2 核心考点:HTTP 方法与状态码

常用 HTTP 方法(RESTful 规范)
  • GET:查询数据(幂等,可缓存)

  • POST:提交数据(非幂等,不可缓存)

  • PUT:更新数据(幂等)

  • DELETE:删除数据(幂等)

  • OPTIONS:预检请求(跨域时触发)

关键状态码
  • 2xx:成功(200 OK、204 No Content)

  • 3xx:重定向 / 缓存(301 永久重定向、304 协商缓存命中)

  • 4xx:客户端错误(400 Bad Request、401 未授权、403 禁止访问、404 资源不存在)

  • 5xx:服务端错误(500 服务器内部错误、503 服务不可用)

3.3 缓存策略:强缓存与协商缓存

浏览器缓存是性能优化的核心,分为强缓存和协商缓存:

  • 强缓存 :通过 Cache-ControlExpires 控制,直接从缓存读取,不发请求;

  • 协商缓存 :通过 ETag/If-None-MatchLast-Modified/If-Modified-Since 控制,需发请求验证缓存是否有效。

缓存优先策略示例(Service Worker)
复制代码
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        // 缓存命中则返回缓存,否则从网络获取
        return response || fetch(event.request)
          .then(networkResponse => {
            // 缓存新的响应
            caches.open('v1').then(cache => {
              cache.put(event.request, networkResponse.clone());
            });
            return networkResponse;
          });
      })
  );
});

四、核心面试考点与性能优化

4.1 高频面试题总结

  1. BOM 相关

    • 同源策略的定义(协议、域名、端口相同);

    • location.assignlocation.replace 的区别;

    • 如何通过 history 实现 SPA 路由。

  2. DOM 事件相关

    • 事件流的三个阶段(捕获、目标、冒泡);

    • 事件委托的原理与应用场景;

    • stopPropagationstopImmediatePropagation 的区别。

  3. 网络相关

    • 304 状态码的含义(协商缓存命中);

    • OPTIONS 请求的作用(跨域预检);

    • 强缓存与协商缓存的区别。

4.2 性能优化实战

1. 减少重排重绘
  • 批量 DOM 操作:使用 DocumentFragment 一次性插入多个元素;

  • 避免频繁修改样式:通过修改 class 而非直接操作 style

  • 脱离文档流操作:使用 position: absolute/fixed 减少重排影响。

2. 防抖与节流
复制代码
// 防抖:触发后延迟执行,频繁触发则重置延迟
function debounce(func, delay) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => func.apply(this, args), delay);
  };
}
​
// 节流:固定时间内只执行一次
function throttle(func, limit) {
  let inThrottle;
  return (...args) => {
    if (!inThrottle) {
      func.apply(this, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}
​
// 应用:监听窗口resize
window.addEventListener('resize', debounce(handleResize, 300));
3. 虚拟列表(大数据渲染优化)

核心思路:只渲染可视区域内的元素,避免一次性渲染大量 DOM:

复制代码
class VirtualList {
  constructor(container, items, itemHeight) {
    this.container = container;
    this.items = items; // 所有数据
    this.itemHeight = itemHeight; // 单个元素高度
    this.visibleCount = Math.ceil(container.clientHeight / itemHeight); // 可视元素数量
    this.container.addEventListener('scroll', () => this.render());
    this.render();
  }
​
  render() {
    const scrollTop = this.container.scrollTop;
    const startIndex = Math.floor(scrollTop / this.itemHeight); // 可视区域起始索引
    const endIndex = startIndex + this.visibleCount; // 可视区域结束索引
    const visibleItems = this.items.slice(startIndex, endIndex); // 只取可视数据
​
    // 渲染可视元素(省略DOM操作)
    this.container.innerHTML = visibleItems.map(item => `<div style="height: ${this.itemHeight}px">${item}</div>`).join('');
    // 偏移容器,模拟滚动效果
    this.container.style.transform = `translateY(${startIndex * this.itemHeight}px)`;
  }
}

五、总结

浏览器中的 JavaScript 核心围绕 "交互""操作""通信" 三大场景:

  • BOM 负责与浏览器交互(地址、历史、系统信息);

  • DOM 负责操作页面元素(事件、布局、渲染);

  • 网络请求负责与后端通信(数据交互、缓存策略)。

掌握这些知识点,不仅能应对日常开发中的交互、布局、性能问题,更能轻松搞定面试中的高频考点。建议结合实战多练习(如实现 SPA 路由、封装事件委托、优化大数据渲染),将理论转化为实际能力。

浏览器 JS 核心面试题汇总(高频考点 + 标准答案)

以下是浏览器环境中 JavaScript 的高频面试题,涵盖 BOM、DOM、事件模型、网络请求、性能优化等核心模块,每个题目均附标准答案和关键考点解析,适合面试冲刺和知识梳理。

一、BOM(浏览器对象模型)高频题

1. 什么是同源策略?同源的判断依据是什么?

标准答案

同源策略是浏览器的安全机制,限制不同源的文档或脚本对当前文档的资源访问。

判断依据:协议、域名、端口号三者完全相同(缺一不可)。

示例:

  • 同源:https://www.test.comhttps://www.test.com:443(默认端口可省略);

  • 不同源:https://www.test.comhttp://www.test.com(协议不同)、https://blog.test.com(域名不同)、https://www.test.com:8080(端口不同)。

关键考点:跨域限制的核心原因,后续跨域解决方案的前置知识。

2. location.assign ()、location.replace ()、location.reload () 的区别?

标准答案

  • location.assign('url'):导航到新 URL,保留当前页面历史记录(可通过浏览器后退返回);

  • location.replace('url'):替换当前 URL,不保留历史记录(无法后退到原页面);

  • location.reload():重新加载当前页面,默认使用缓存;location.reload(true) 强制从服务器加载(忽略缓存)。

关键考点:路由跳转的历史记录管理,SPA 路由实现的基础。

3. history.pushState () 和 history.replaceState () 的作用?如何监听浏览器前进 / 后退?

标准答案

  • 两者均用于修改浏览器历史记录,

    不触发页面刷新

    (SPA 路由核心 API);

    • pushState(state, title, url):新增一条历史记录,URL 可自定义;

    • replaceState(state, title, url):替换当前历史记录,不新增条目;

  • 监听前进 / 后退:通过 popstate 事件,只能监听浏览器主动触发的历史记录变化(push/replaceState 调用不会触发)。

示例代码:

复制代码
window.addEventListener('popstate', (e) => {
  console.log('历史记录变化:', e.state); // 获取push/replaceState存储的state数据
});

关键考点:SPA 路由的实现原理(history 模式)。

标准答案

通过 navigator.userAgent(用户代理字符串)解析,核心逻辑:

复制代码
function detectEnv() {
  const ua = navigator.userAgent.toLowerCase();
  return {
    browser: {
      isChrome: ua.includes('chrome') && !ua.includes('edge'),
      isFirefox: ua.includes('firefox'),
      isSafari: ua.includes('safari') && !ua.includes('chrome'),
      isIE: ua.includes('trident') || ua.includes('msie'),
      isEdge: ua.includes('edge')
    },
    isMobile: /mobile|android|iphone|ipad/i.test(ua)
  };
}

关键考点:浏览器兼容性处理的前置逻辑,用户画像收集方案。

5. clientHeight、offsetHeight、scrollHeight 的区别?

标准答案

三者均用于获取元素尺寸,核心差异在于包含的范围:

  • clientHeight:内容区高度 + 内边距(padding),不含边框、滚动条、外边距

  • offsetHeight:内容区高度 + 内边距 + 边框(border) + 滚动条,不含外边距

  • scrollHeight:元素实际内容高度(含滚动隐藏部分),不含滚动条、外边距

关键考点:元素尺寸计算,滚动逻辑实现,响应式布局开发。

二、DOM 事件模型高频题

1. JS 事件流的三个阶段是什么?如何控制事件传播?

标准答案

事件流顺序:捕获阶段 → 目标阶段 → 冒泡阶段

  • 捕获阶段:事件从顶层(document)向下传播到目标元素;

  • 目标阶段:事件到达实际触发的元素;

  • 冒泡阶段:事件从目标元素向上传播回顶层。

控制事件传播的方法:

  • event.stopPropagation():阻止事件继续传播(中断捕获 / 冒泡);

  • event.stopImmediatePropagation():不仅阻止传播,还会阻止当前元素上的其他同类事件监听器执行。

关键考点:事件委托的核心原理,事件传播的实际应用。

2. 什么是事件委托?它的优势是什么?适用场景?

标准答案

事件委托是利用事件冒泡机制,将子元素的事件统一绑定到父元素,通过判断事件源(event.target)执行对应逻辑。

优势:

  1. 减少事件监听器数量,降低内存消耗;

  2. 支持动态新增的子元素(无需重新绑定事件);

  3. 简化代码维护,统一事件处理逻辑。

适用场景:列表渲染、动态元素(如表单新增字段)、大量相似元素的事件处理。

示例代码:

复制代码
const list = document.querySelector('.list');
list.addEventListener('click', (e) => {
  if (e.target.tagName === 'LI') { // 判断事件源
    console.log('点击了:', e.target.textContent);
  }
});

关键考点:性能优化方案,DOM 事件的实际应用。

3. event.preventDefault () 和 event.stopPropagation () 的区别?

标准答案

  • event.preventDefault():阻止元素的默认行为(如 a 标签跳转、表单提交、鼠标右键菜单),不影响事件传播

  • event.stopPropagation():阻止事件在捕获 / 冒泡阶段传播,不影响默认行为

示例:点击 a 标签时,既阻止跳转(preventDefault),又阻止事件冒泡(stopPropagation)。

关键考点:事件对象的核心方法,避免混淆默认行为和事件传播。

4. 相同元素绑定多个同类事件,执行顺序是什么?如何阻止?

标准答案

  • 执行顺序:按事件绑定的先后顺序执行;

  • 阻止后续事件:使用 event.stopImmediatePropagation(),会中断当前元素上后续同类事件的执行,同时阻止事件传播。

示例代码:

复制代码
const btn = document.querySelector('button');
btn.addEventListener('click', () => console.log('事件1'));
btn.addEventListener('click', (e) => {
  console.log('事件2');
  e.stopImmediatePropagation(); // 阻止后续事件和传播
});
btn.addEventListener('click', () => console.log('事件3')); // 不会执行

关键考点:事件监听器的执行机制,特殊场景下的事件控制。

三、网络请求与缓存高频题

1. XMLHttpRequest 的核心步骤是什么?readyState 的取值含义?

标准答案

核心步骤(异步请求):

  1. 创建 XHR 对象:const xhr = new XMLHttpRequest()

  2. 配置请求:xhr.open(method, url, async)(async 为 true 表示异步);

  3. 设置请求头(可选):xhr.setRequestHeader('Content-Type', 'application/json')

  4. 监听状态变化:xhr.onreadystatechange = () => {}

  5. 发送请求:xhr.send(data)(POST 请求需传参)。

readyState 取值含义:

  • 0:未初始化(open 未调用);

  • 1:加载中(open 已调用,send 未调用);

  • 2:已加载(send 已调用,响应头接收完成);

  • 3:交互中(响应体部分接收);

  • 4:完成(响应体完全接收)。

关键考点:网络请求底层原理,传统请求方案的理解。

2. HTTP 状态码 304 的含义是什么?与浏览器缓存的关系?

标准答案

304 表示 "协商缓存命中",服务器告知浏览器:"当前资源未修改,可直接使用本地缓存"。

与缓存的关系:

  • 浏览器缓存分为强缓存(Cache-Control/Expires)和协商缓存(ETag/Last-Modified);

  • 强缓存失效后,浏览器会发送协商缓存请求(携带 If-None-Match/If-Modified-Since);

  • 服务器验证资源未修改时,返回 304,浏览器直接使用缓存;资源修改则返回 200 和新资源。

关键考点:浏览器缓存机制,性能优化方案。

3. RESTful API 的核心规范是什么?常用 HTTP 方法的含义?

标准答案

RESTful API 是基于 HTTP 协议的接口设计规范,核心是 "资源导向",使用 HTTP 方法表达操作意图:

  • GET:查询资源(幂等,可缓存);

  • POST:创建资源(非幂等,不可缓存);

  • PUT:更新资源(幂等,全量更新);

  • DELETE:删除资源(幂等);

  • OPTIONS:预检请求(跨域时触发,验证服务器是否允许跨域)。

关键考点:接口设计规范,HTTP 协议的实际应用。

4. 什么是跨域?OPTIONS 请求的作用是什么?

标准答案

跨域是指浏览器因同源策略限制,阻止不同源的脚本访问当前文档的资源(如接口请求、DOM 操作)。

OPTIONS 请求的作用:

属于 "预检请求",当跨域请求满足以下条件时触发:

  1. 请求方法不是 GET/POST/HEAD;

  2. 请求头包含自定义字段(如 Authorization);

  3. POST 请求的 Content-Type 不是 application/x-www-form-urlencoded、multipart/form-data、text/plain。

OPTIONS 请求的目的是让服务器告知浏览器:"是否允许该跨域请求的方法、请求头等"。

关键考点:跨域解决方案的前置知识,HTTP 协议细节。

四、性能优化高频题

1. 如何减少 DOM 重排和重绘?

标准答案

重排(回流)是计算元素位置和大小,重绘是填充像素,两者都会影响性能,优化方案:

  1. 批量 DOM 操作:使用 DocumentFragment 一次性插入多个元素,避免频繁修改 DOM;

  2. 样式集中修改:通过修改 class 而非直接操作 style,减少样式变更次数;

  3. 脱离文档流操作:使用 position: absolute/fixed 或 display: none,操作后再恢复;

  4. 避免频繁读取尺寸:读取 offsetHeight、clientWidth 等属性会触发重排,应集中读取后批量操作;

  5. 使用虚拟列表:大数据渲染时,只渲染可视区域的元素(如 10000 条数据只渲染 10 条)。

关键考点:浏览器渲染机制,前端性能优化核心方案。

2. 防抖和节流的区别是什么?实现原理?适用场景?

标准答案

两者都是限制函数执行频率的优化方案,核心差异在于执行时机:

  • 防抖(debounce):触发后延迟 n 秒执行,若 n 秒内再次触发则重置延迟,适用于高频触发后只需要一次结果(如搜索框输入、窗口 resize);

  • 节流(throttle):固定 n 秒内只执行一次,适用于高频触发但需要持续响应(如滚动加载、按钮点击防重复提交)。

实现代码:

复制代码
// 防抖
function debounce(func, delay) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => func.apply(this, args), delay);
  };
}
​
// 节流
function throttle(func, limit) {
  let inThrottle;
  return (...args) => {
    if (!inThrottle) {
      func.apply(this, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

关键考点:性能优化方案,高频事件处理。

3. 浏览器的渲染流程是什么?如何优化渲染性能?

标准答案

渲染流程:

  1. 解析 HTML,构建 DOM 树;

  2. 解析 CSS,构建 CSSOM 树;

  3. 合并 DOM 和 CSSOM,生成渲染树(只包含可见元素);

  4. 布局(重排):计算元素的位置和大小;

  5. 绘制(重绘):根据渲染树填充像素;

  6. 合成:将绘制的图层组合成最终页面。

渲染性能优化:

  1. 减少 CSS 阻塞:避免 @import,使用 link 引入 CSS,关键 CSS 内联;

  2. 减少 JS 阻塞:使用 defer/async 加载脚本,避免同步脚本阻塞渲染;

  3. 优化 DOM 结构:简化 DOM 层级,减少不必要的元素;

  4. 优化 CSS 选择器:避免复杂选择器(如后代选择器),减少 CSSOM 构建时间;

  5. 使用 CSS 硬件加速:通过 transform、opacity 等属性触发 GPU 渲染(避免重排重绘)。

关键考点:浏览器底层原理,前端性能优化的核心思路。

五、核心误区辨析题

1. HTTP 协议和 XMLHttpRequest/Fetch/axios 的关系?

标准答案

  • HTTP 协议是客户端与服务器通信的 "规范 / 标准",定义了请求方法、状态码、报文格式等;

  • XMLHttpRequest、Fetch API 是浏览器提供的 "HTTP 协议实现工具"(原生 API);

  • axios 是基于 XMLHttpRequest 封装的 "第三方库",简化了请求配置、拦截器、错误处理等逻辑。

三者的关系:工具(XMLHttpRequest/Fetch/axios)实现了规范(HTTP 协议)。

2. history 模式和 hash 模式的 SPA 路由有什么区别?

标准答案

两者都是 SPA 路由的实现方式,核心差异在于 URL 格式和底层原理:

  • hash 模式:URL 包含 #(锚点),如http://test.com/#/page1,通过监听hashchange事件实现路由切换,无需后端配置(# 后的内容不会发送到服务器);

  • history 模式:URL 无 #,如http://test.com/page1,通过 history.pushState/replaceState 修改 URL,需要后端配置(所有路由都指向 index.html,否则刷新会 404)。

关键考点:SPA 路由的实现细节,前后端配合方案。

相关推荐
lang201509281 小时前
一键生成Java Web项目:Tomcat-Maven原型解析
java·前端·tomcat
开开心心就好1 小时前
免费批量抠图软件大模型,复杂倒影精准去除
网络·windows·pdf·计算机外设·电脑·硬件架构·材料工程
heartbeat..1 小时前
JVM 参数配置指南:内存调优、收集器选择与问题排查
java·运维·jvm·性能优化
We་ct2 小时前
LeetCode 242. 有效的字母异位词:解法解析与时空优化全攻略
前端·算法·leetcode·typescript
百***07452 小时前
进阶实战:Veo3.1 4K API深度集成短剧/漫剧系统,避坑与性能优化指南
python·性能优化
David凉宸2 小时前
Vue 3生态系统深度解析与最佳实践
前端·javascript·vue.js
郝学胜-神的一滴2 小时前
跨平台通信的艺术与哲学:Qt与Linux Socket的深度对话
linux·服务器·开发语言·网络·c++·qt·软件构建
Highcharts.js2 小时前
用 Highcharts如何创建一个音频图表
javascript·信息可视化·音视频·highcharts·音频图表
WJ.Polar2 小时前
华为交换机STP与链路聚合实战
运维·网络