2024.08.10 更新前端面试问题总结(20道题)

2024.07.12 - 2024.08.10 更新前端面试问题总结(20道题)

获取更多面试相关问题可以访问

github 地址: github.com/pro-collect...

gitee 地址: gitee.com/yanleweb/in...

目录:

  • 初级开发者相关问题【共计 1 道题】

    • 814.盒模型【热度: 753】【CSS】
  • 中级开发者相关问题【共计 10 道题】

    • 795.axios 是否可以取消请求【热度: 532】【网络、web应用场景】【出题公司: TOP100互联网】
    • 796.cookie 可以实现不同域共享吗【热度: 533】【网络】【出题公司: TOP100互联网】
    • 798.px 如何转为 rem【热度: 545】【CSS】
    • 801.富文本里面, 是如何做到划词的(鼠标滑动选择一组字符, 对组字符进行操作)?【热度: 100】【web应用场景】【出题公司: TOP100互联网】
    • 802.如何在划词选择的文本上添加右键菜单(划词:鼠标滑动选择一组字符, 对组字符进行操作)【热度: 100】【web应用场景】【出题公司: TOP100互联网】
    • 803.如何实现预览 PDF 文件【热度: 173】【web应用场景】
    • 806.如何减少项目里面 if-else【热度: 310】【web应用场景】【出题公司: 美团】
    • 807.[React] hooks 调用是可以写在 if 语句里面吗【热度: 337】【web框架】【出题公司: 腾讯】
    • 809.ajax 和 xhr 是什么关系?【热度: 332】【网络】【出题公司: TOP100互联网】
    • 810.axios 请求的底层依赖是什么?【热度: 266】【网络】【出题公司: TOP100互联网】
  • 高级开发者相关问题【共计 4 道题】

    • 797.浏览器有同源策略, 但是为何 cdn 请求资源的时候不会有跨域限制【热度: 579】【网络】【出题公司: TOP100互联网】
    • 804.[React] 生态有哪些【热度: 442】【web框架】【出题公司: 腾讯】
    • 805.babel-runtime 作用是啥【热度: 200】【工程化】【出题公司: 腾讯】
    • 808.日志监控问题:可有办法将请求的调用源码地址包括代码行数也上报上去?【热度: 814】【web应用场景】【出题公司: 阿里巴巴】
  • 资深开发者相关问题【共计 5 道题】

    • 799.如何标准化处理线上用户反馈的问题【热度: 631】【web应用场景】

    • 800.如何做好前端监控方案【热度: 672】【web应用场景】

    • 811.日志监控:如何还原用户操作流程【热度: 450】【web应用场景】【出题公司: TOP100互联网】

    • 812.[React] scheduler 调度机制原理【热度: 660】【web框架】【出题公司: TOP100互联网】

    • 813.[React] useRef 是如何实现的【热度: 299】【web框架】【出题公司: TOP100互联网】

初级开发者相关问题【共计 1 道题】

814.盒模型【热度: 753】【CSS】

关键词:盒模型

盒模型

CSS3 中的盒模型有以下两种:标准盒子模型、IE 盒子模型

盒模型都是由四个部分组成的,分别是 margin、border、padding 和 content。

在标准盒模型性中

盒子在网页中实际占用:

宽 = width + padding2 + border2 + margin2

高 = height + padding2 + border2 + margin2

盒模型实际大小:

宽 = width + padding2 + border2

高 = height + padding2 + border2

在 IE 盒模型性中

盒子在网页中实际占用:

宽 = width + margin2

高 = height + margin2

盒模型实际大小:

宽 = width

高 = height

可以通过修改元素的 box-sizing 属性来改变元素的盒模型:

  • box-sizeing: content-box表示标准盒模型

  • box-sizeing: border-box表示 IE 盒模型

中级开发者相关问题【共计 10 道题】

795.axios 是否可以取消请求【热度: 532】【网络、web应用场景】【出题公司: TOP100互联网】

关键词:取消请求

Axios 可以取消请求。官方文档指出有两种方法可以取消请求,分别是cancelTokenAbortController,示例代码如下:

  • 使用cancelToken的方法一:
javascript 复制代码
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.post("/user/12345", { name: "new name" }, { cancelToken: source.token });
source.cancel("Operation canceled by the user.");
  • 使用 cancelToken的方法二:
javascript 复制代码
const CancelToken = axios.CancelToken;
let cancel;
axios.get("/user/12345", {
  cancelToken: new CancelToken(function executor(c) {
    cancel = c;
  }),
});
cancel();
  • 使用AbortController
javascript 复制代码
const controller = new AbortController();
axios.get("/foo/bar", { signal: controller.signal }).then(function (response) {
  //...
});
controller.abort();

通过文档描述和示例代码,可以总结出以下功能点:

  • 支持cancelToken取消请求,cancelToken可以通过工厂函数产生,也可以通过构造函数生成;

  • 支持 Fetch API 的AbortController取消请求;

  • 一个token/signal可以取消多个请求,一个请求也可同时使用token/signal

  • 如果在开始axios request之前执行了取消请求,则并不会发出真实的请求。

796.cookie 可以实现不同域共享吗【热度: 533】【网络】【出题公司: TOP100互联网】

关键词:cookie 共享

默认情况下,Cookie 不能在不同的顶级域名之间共享数据。

但是,如果两个域名属于同一主域名下的子域名,并且您设置了正确的 Domain 属性,那么在这些子域名之间是可以共享 Cookie 的。

例如,对于 sub1.example.comsub2.example.com 这样的子域名,如果设置 CookieDomain 属性为 .example.com ,那么在这两个子域名之间,这个 Cookie 是可以共享和访问的。

然而,如果是完全不同的顶级域名,如 example.comanotherdomain.com 之间,Cookie 是不能直接共享的。

此外,还需要注意 CookiePath 属性、安全属性(Secure)、HttpOnly 属性等,这些属性也会影响 Cookie 的使用范围和方式。

798.px 如何转为 rem【热度: 545】【CSS】

关键词:移动端适配

px(像素)转换为 rem(根元素字体大小的相对单位)需要先确定一个基准的根元素字体大小。

通常,我们将根元素(<html>)的字体大小设置为一个特定的值,比如 16px(这是常见的默认值,但您可以根据设计需求进行修改)。

假设根元素的字体大小为 16px,那么转换公式为:rem 值 = px 值 / 16

例如,如果有一个元素的宽度为 100px,转换为 rem 就是:100 / 16 = 6.25rem

在实际开发中,可以使用预处理器(如 Sass、Less)或者 JavaScript 来实现自动转换。

追问:可有什么办法让 px 自动转为 rem, 在开发中就直接使用 px

在前端开发中,要实现输入 px 但自动转换为 rem ,可以通过以下几种方式:

  1. 使用 CSS 预处理器(如 Sass、Less)
  • Sass:
scss 复制代码
@function pxToRem($pxValue) {
  @return $pxValue / 16 + rem;
}

.element {
  width: pxToRem(100);
}
  • Less:
less 复制代码
.pxToRem(@pxValue) {
  @remValue: @pxValue / 16;
  @return @remValue + rem;
}

.element {
  width: pxToRem(100);
}
  1. 使用构建工具(如 Webpack)的插件

    • 例如 postcss-pxtorem 插件,它可以在构建过程中自动将 px 转换为 rem 。您需要在配置中设置根元素的字体大小等相关参数。
  2. 自己编写脚本进行转换

    • 可以在开发过程中使用 JavaScript 脚本来处理样式表中的 px 值,并将其转换为 rem 。但这种方式相对复杂,并且可能会影响开发效率。

801.富文本里面, 是如何做到划词的(鼠标滑动选择一组字符, 对组字符进行操作)?【热度: 100】【web应用场景】【出题公司: TOP100互联网】

关键词:DOM getSelection 方法

主要考察 dom 方法, getSelection 属于很冷门知识, 只会在做过富文本的同��面试过程中可能会问得到。

在富文本环境中实现划词(鼠标滑动选择一组字符并对其进行操作)通常涉及以下几个关键步骤和技术:

  1. 事件监听

    • 监听鼠标按下、鼠标移动和鼠标松开这三个主要的鼠标事件。当鼠标按下时,标记选择的开始;在鼠标移动过程中,根据鼠标的位置更新选择范围;鼠标松开时,确定最终的选择。
  2. 选择范围计算

    • 使用浏览器提供的 Selection 对象来获取和管理选择的范围。在鼠标移动过程中,不断更新 Selection 对象的范围。
  3. 操作处理

    • 一旦选择完成,可以根据具体的需求对选中的字符进行操作。例如,修改样式(如加粗、变色)、获取选中的文本内容、执行复制粘贴等操作。

以下是一个简单的 JavaScript 示例,展示了如何获取选中的文本:

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <body>
    <p>这是一段示例文本,您可以尝试选中一部分。</p>

    <script>
      document.addEventListener("mouseup", function () {
        const selection = window.getSelection();
        if (selection) {
          const selectedText = selection.toString();
          console.log("选中的文本: ", selectedText);
        }
      });
    </script>
  </body>
</html>

802.如何在划词选择的文本上添加右键菜单(划词:鼠标滑动选择一组字符, 对组字符进行操作)【热度: 100】【web应用场景】【出题公司: TOP100互联网】

关键词:DOM getSelection 方法 应用场景

主要考察 dom 方法, getSelection 属于很冷门知识, 只会在做过富文本的同学面试过程中可能会问得到。

要在划词选择的文本上添加右键菜单,可以按照以下步骤进行操作:

  1. 监听鼠标右键事件 在文档或富文本区域上添加 contextmenu 事件的监听。
javascript 复制代码
document.addEventListener("contextmenu", function (event) {
  // 阻止默认的浏览器右键菜单
  event.preventDefault();

  // 在此处显示自定义右键菜单
  showCustomMenu(event);
});
  1. 显示自定义右键菜单 创建一个自定义的菜单元素,并根据选择的文本设置菜单选项。
javascript 复制代码
function showCustomMenu(event) {
  const customMenu = document.createElement("div");
  customMenu.style.position = "absolute";
  customMenu.style.left = event.clientX + "px";
  customMenu.style.top = event.clientY + "px";

  // 添加菜单选项
  const menuItem1 = document.createElement("div");
  menuItem1.textContent = "复制";
  menuItem1.addEventListener("click", function () {
    // 处理复制操作
    copySelectedText();
  });
  customMenu.appendChild(menuItem1);

  // 可以添加更多的菜单选项

  document.body.appendChild(customMenu);
}
  1. 处理菜单选项的操作 例如,实现复制选中文本的功能。
javascript 复制代码
function copySelectedText() {
  const selection = window.getSelection();
  if (selection) {
    const range = selection.getRangeAt(0);
    const clipboardData = new ClipboardEvent("copy", {
      clipboardData: { text: range.toString() },
      bubbles: true,
    }).clipboardData;
    document.execCommand("copy", false, clipboardData);
  }
}
  1. 隐藏右键菜单 当用户点击菜单之外的区域时,隐藏自定义右键菜单。
javascript 复制代码
document.addEventListener("click", function (event) {
  const customMenu = document.querySelector(".custom-menu");
  if (customMenu && !customMenu.contains(event.target)) {
    customMenu.remove();
  }
});

803.如何实现预览 PDF 文件【热度: 173】【web应用场景】

关键词:预览 PDF 文件

在前端实现 PDF 文件预览功能,主要有以下几种常用方法:

1. 使用浏览器内置的 PDF 查看器

浏览器像 Chrome 和 Firefox 等内置了 PDF 查看器,可以直接在浏览器中打开和预览 PDF 文件。实现方式非常简单,只需将 PDF 文件的 URL 设置为<a>标签的href属性,或者使用window.open方法在新标签页中打开 PDF 文件。

html 复制代码
<!-- 方法1: 使用超链接 -->
<a href="/path/to/your/document.pdf" target="_blank">预览PDF</a>

<!-- 方法2: 使用JavaScript -->
<button onclick="window.open('/path/to/your/document.pdf', '_blank')">预览PDF</button>

2. 使用 PDF.js

PDF.js是一个由 Mozilla 开发的开源库,它使用 HTML5 Canvas 来渲染 PDF 文件。PDF.js 提供了广泛的 API 来实现 PDF 的加载、渲染、缩放、打印等功能。

如何使用:

  1. 引入 PDF.js 首先,你需要在你的项目中包含 PDF.js。可以从其GitHub 仓库中直接下载或使用 CDN。
html 复制代码
<!-- 引入pdf.js和pdf.worker.js -->
<script src="/path/to/pdf.js"></script>
<script src="/path/to/pdf.worker.js"></script>
  1. 渲染 PDF 文件 使用 PDF.js 提供的 API 来加载和渲染 PDF 文件。
html 复制代码
<!-- PDF容器 -->
<div id="pdf-container"></div>

<script>
  // 初始化PDF.js
  pdfjsLib.getDocument("/path/to/your/document.pdf").promise.then(function (pdfDoc) {
    // 获取第一页
    pdfDoc.getPage(1).then(function (page) {
      // 设置视口和比例
      var scale = 1.5;
      var viewport = page.getViewport({ scale: scale });

      // 准备用于渲染的Canvas
      var canvas = document.createElement("canvas");
      var ctx = canvas.getContext("2d");
      canvas.height = viewport.height;
      canvas.width = viewport.width;

      // 将Canvas添加到DOM中
      document.getElementById("pdf-container").appendChild(canvas);

      // 通过Canvas渲染PDF页面
      var renderContext = {
        canvasContext: ctx,
        viewport: viewport,
      };
      page.render(renderContext);
    });
  });
</script>

3. 使用第三方服务

也可以使用第三方服务如 Google Docs Viewer 来预览 PDF。这种方法的优点是容易实现,但依赖于外部服务。

html 复制代码
<iframe
  src="http://docs.google.com/gview?url=http://path.to/your/document.pdf&embedded=true"
  style="width:600px; height:500px;"
  frameborder="0"
></iframe>

其中,将http://path.to/your/document.pdf替换为你的 PDF 文件的真实 URL。

选择适合的方法

  • 简单预览:如果只需要一个简单的 PDF 文件预览,使用浏览器的内置功能是最快的方法。

  • 复杂的 PDF 交互:对于需要复杂交互(如注释、填写表单)的 PDF 文件,PDF.js 提供了更多控制和定制选项。

  • 简易集成但依赖第三方:使用第三方服务是最容易实现的,但您的数据可能会通过第三方服务器传递,需要考虑隐私和安全性。

806.如何减少项目里面 if-else【热度: 310】【web应用场景】【出题公司: 美团】

关键词:减少 if-else

当项目中存在大量的 if-else 语句时,可以考虑以下几种优化方法:

  1. 策略模式

    • 创建一组策略对象,每个对象对应一种条件和处理逻辑。根据不同的条件选择相应的策略对象来执行操作。
  2. 表驱动法

    • 建立一个数据结构(如对象或数组),将条件与对应的处理函数或值关联起来,通过查找表来获取相应的处理方式。
  3. 多态

    • 如果条件判断基于不同的对象类型,可以使用多态性,让每个对象类型实现自己的处理方法。
  4. 提取函数

    • 将每个 if-else 分支中的复杂逻辑提取为独立的函数,以提高代码的可读性和可维护性。
  5. 状态模式

    • 当条件判断反映的是对象的不同状态时,可以使用状态模式来处理。

例如,使用表驱动法的示例代码如下:

javascript 复制代码
const handlers = {
  condition1: () => {
    // 处理条件 1 的逻辑
  },
  condition2: () => {
    // 处理条件 2 的逻辑
  },
  // 更多条件和处理函数
};

const condition = "condition1"; // 实际的条件

if (handlers[condition]) {
  handlers[condition]();
}

通过这些方法,可以使代码更加简洁、灵活和易于维护,减少大量 if-else 带来的复杂性和混乱。

参考文档

807.[React] hooks 调用是可以写在 if 语句里面吗【热度: 337】【web框架】【出题公司: 腾讯】

关键词:hooks 调用问题

hooks 写在 if 语句里面, 也是可以执行的, 但是会带来很多不可预期的异常

在 React 中,Hooks 的调用不应该直接写在 if 语句里面。

Hooks 必须在函数组件的顶层(不在循环、条件判断或嵌套函数中)按顺序调用。这是因为 React 需要在每次渲染时以相同的顺序调用 Hooks,以正确管理组件的状态和副作用。

如果在 if 语句中调用 Hooks,可能会导致以下错误:

  1. 状态不一致:由于渲染顺序的不确定性,可能会导致状态的更新和获取出现不一致的情况。

  2. 难以预测的行为:React 依赖于 Hooks 的调用顺序来正确管理组件的内部逻辑,如果在条件语句中调用,可能会导致难以理解和调试的问题。

例如,下面的代码是错误的:

jsx 复制代码
function MyComponent() {
  if (someCondition) {
    const [count, setCount] = useState(0); // 错误:不允许在条件语句中调用 useState
  }

  // 后续代码
}

为了遵循规则,应该将 Hooks 的调用始终保持在函数组件的最顶层。

809.ajax 和 xhr 是什么关系?【热度: 332】【网络】【出题公司: TOP100互联网】

关键词:ajax 和 xhr

Ajax

全称为 Asynchronous JavaScript and XML(异步 JavaScript 和 XML),是一种在不重新加载整个网页的情况下,与服务器进行数据交换并更新部分网页内容的技术方法。

Ajax 主要基于以下几个关键概念和技术:

  1. 异步通信:允许网页在发送请求后继续执行其他操作,无需等待服务器响应。

  2. JavaScript:用于处理请求的发送、响应的接收和页面的动态更新。

  3. XML 或其他数据格式:虽然名称中包含 XML,但实际上服务器返回的数据可以是 XML、JSON、HTML 等各种格式。

关系

Ajax(Asynchronous JavaScript and XML)是一种使用多种技术(包括 XMLHttpRequest(XHR)对象)在后台与服务器进行异步数据交换,而无需重新加载整个网页的 Web 开发技术。

XMLHttpRequest 是实现 Ajax 技术的关键对象之一。通过创建 XMLHttpRequest 对象,我们可以使用 JavaScript 向服务器发送请求,并处理服务器返回的响应。

简单来说,XMLHttpRequest 是实现 Ajax 的一种底层机制或工具。Ajax 是一个更广泛的概念,涵盖了使用包括 XMLHttpRequest 在内的技术来实现异步数据交互的方法和模式。

例如,以下是一个使用 XMLHttpRequest 实现简单 Ajax 请求的示例:

javascript 复制代码
let xhr = new XMLHttpRequest();

xhr.open("GET", "https://example.com/data");

xhr.onreadystatechange = function () {
  if (xhr.readyState === 4 && xhr.status === 200) {
    let data = xhr.responseText;

    console.log(data);
  }
};

xhr.send();

在这个示例中,我们通过操作 XMLHttpRequest 对象来完成了一个异步获取数据的过程,这就是 Ajax 技术的一种应用。

其他实现方式

除了使用 XMLHttpRequest 实现 Ajax 之外,还有以下几种常见的实现方式:

  1. fetch API:这是现代浏览器中提供的一种更简洁的异步请求方式,基于 Promise
javascript 复制代码
fetch("https://example.com/data")
  .then((response) => response.json())

  .then((data) => console.log(data))

  .catch((error) => console.error(error));
  1. Axios 库:一个流行的第三方 Ajax 库,提供了丰富的功能和简洁的接口。
javascript 复制代码
axios
  .get("https://example.com/data")

  .then((response) => console.log(response.data))

  .catch((error) => console.error(error));
  1. jQuery$.ajax() 方法:如果项目中使用了 jQuery 库,可以使用其提供的 ajax 方法。
javascript 复制代码
$.ajax({
  url: "https://example.com/data",

  method: "GET",

  success: function (data) {
    console.log(data);
  },

  error: function (error) {
    console.error(error);
  },
});

这些方式各有特点,可以根据项目的需求和技术架构选择合适的 Ajax 实现方式。

810.axios 请求的底层依赖是什么?【热度: 266】【网络】【出题公司: TOP100互联网】

关键词:axios 请求依赖

Axios 的底层依赖会根据运行环境而有所不同:

在浏览器环境中,Axios 通常会优先使用 XMLHttpRequest 对象来发送请求。但它也可以使用 fetch API (如果浏览器支持)。

在 Node.js 环境中,Axios 依赖于 Node.js 的 httphttps 模块来发送请求。

高级开发者相关问题【共计 4 道题】

797.浏览器有同源策略, 但是为何 cdn 请求资源的时候不会有跨域限制【热度: 579】【网络】【出题公司: TOP100互联网】

关键词:同源策略、跨域限制

同源策略是啥

浏览器的同源策略(Same-origin policy)是一种重要的安全机制,用于限制不同源的文档或脚本之间的交互操作。

"源"(origin)由三部分组成:协议(protocol)、域名(domain)和端口(port)。如果两个 URL 的协议、域名和端口都完全相同,那么它们就是同源的;否则,就是不同源的。

同源策略的主要作用和规则如下:

  1. 阻止文档或脚本读取来自不同源的文档内容

    • 比如,在 https://example.com/page1.html 页面中的 JavaScript 脚本,不能读取 https://anotherdomain.com/page2.html 的文档内容。
  2. 限制不同源的脚本之间的交互

    • 不同源的脚本不能相互调用方法、访问对象属性或修改对方的 DOM(文档对象模型)。
  3. 限制跨源的网络请求

    • 例如,使用 XMLHttpRequestFetch API 发起的网络请求,如果目标地址与当前页面的源不同,会受到同源策略的限制。不过,一些跨源请求可以通过 CORS(跨源资源共享,Cross-Origin Resource Sharing)机制来实现合法的跨源访问。

同源策略的目的是防止恶意网站窃取用户在其他网站上的敏感信息或进行未经授权的操作,保护用户数据的安全性和隐私性。

举个例子,如果没有同源策略,恶意网站 malicious-site.com 可能会在其页面中嵌入脚本,尝试读取用户正在访问的银行网站 bank-site.com 的页面内容,获取用户的账户信息、交易记录等敏感数据,这将给用户带来极大的安全风险。

浏览器有同源策略, 但是为何 cdn 请求资源的时候不跨域

一些 CDN 资源不受同源策略限制,是因为同源策略主要是浏览器的一种安全机制,用于限制不同源的文档或脚本之间的交互操作,但对于某些特定类型的资源访问,浏览器会有一些例外情况。 在 HTML 中,<script>、<img>、<iframe>、<link>等标签的 src 属性所指向的资源(如 JavaScript 文件、图片、CSS 文件等)通常是可以跨域访问的。 例如,可以在自己的网站中通过<script src="https://cdn.example.com/vue.min.js"></script>加载来自 CDN 的 Vue.js 库。

这样做的主要原因是为了保证 Web 的开放性和可扩展性。如果这些资源也严格受到同源策略的限制,那么将所有相关资源都部署在同一个服务器下会违背 Web 开放的初衷,并且不利于资源的分发和缓存。 然而,虽然浏览器允许这些资源的跨域加载,但在加载 JavaScript 时,会限制对返回内容的读写权限,以防止恶意脚本获取或修改其他域的信息。 另外,CDN 服务提供商通常也会采取一些措施来确保资源的安全性和合法性。他们会对资源进行管理和配置,只允许合法的请求访问资源,并防止恶意使用或滥用 CDN 资源。 需要注意的是,同源策略仍然是非常重要的安全机制,它能有效防止恶意网站窃取用户在其他网站上的敏感信息或进行未经授权的操作。在涉及到敏感数据的交互或需要更严格安全控制的情况下,仍然需要遵循同源策略或采用适当的跨域解决方案,如 CORS(跨域资源共享)等。CORS 通过在服务器端设置响应头,明确允许哪些源可以访问资源,从而在保证安全的前提下实现跨域数据交互。

img src 指向的任何资源都是可以跨域访问吗

一般情况下,<img> 元素的 src 属性指向的资源是可以进行跨域访问的。

当您在网页中使用 <img> 标签加载图片资源时,浏览器会向指定的 URL 发送请求获取图片数据,并将其显示在页面上,即使该资源的源与当前页面的源不同。

然而,也存在一些特殊情况和限制:

  1. 如果图片资源所在的服务器设置了严格的访问控制策略(例如通过服务器端的配置限制某些来源的访问),那么可能会导致您的请求被拒绝。

  2. 对于一些受版权保护或有特殊访问权限要求的图片资源,如果您没有相应的授权或访问权限,即使浏览器本身允许跨域访问,您也无法获取和显示这些图片。

总的来说,在大多数常规情况下,<img> 元素的 src 属性指向的图片资源能够实现跨域访问,但需要考虑服务器端的配置和资源本身的权限要求等因素。

804.[React] 生态有哪些【热度: 442】【web框架】【出题公司: 腾讯】

关键词:React 生态

直接抄作业即可,参考文档如下

juejin.cn/post/729790...

805.babel-runtime 作用是啥【热度: 200】【工程化】【出题公司: 腾讯】

关键词:babel-runtime 作用

babel-runtime 是一个包含 babel 模块化运行时助手的库。

在使用 babel 进行代码转换时,有时会注入一些在多个文件中相同且可能被重复使用的代码。例如,使用类转换(无松散模式)时,每个包含类的文件都会重复出现类似 _classcallcheck 这样的函数。

babel-runtime 的主要作用就是将这些可能被重用的代码抽取成单独的模块,以避免在每个文件中重复出现相同的代码。它通过模块导入的方式引入这些功能,从而避免了对全局作用域的修改或污染。

具体来说,babel-runtime 包含了诸如 core-js(提供 JavaScript 内置库的垫片,如 arrayjsonmathpromisesymbol 等)、regenerator-runtime(实现了 generator/yieldasync/await)以及一些语法转换的辅助函数(如 es5es6 的继承转换等)。

使用 babel-runtime 通常需要配合 babel-plugin-transform-runtime 插件一起使用。babel-plugin-transform-runtime 插件会进行一些处理,例如自动导入 babel-runtime/core-js,并将全局静态方法、全局内置对象映射到对应的模块;将内联的工具函数移除,改成通过 babel-runtime/helpers 模块进行导入;如果使用了 async/generator 函数,则自动导入 babel-runtime/regenerator 模块等。

这样,在代码中如果需要使用特定的功能,只需从 babel-runtime 相应的模块中导入即可,而不是直接使用全局的对象或函数。

例如,如果代码中使用了 promise,可以这样导入:

javascript 复制代码
import promise from "babel-runtime/core-js/promise";

总的来说,babel-runtime 更像是一种按需加载的实现方式,适用于开发库、工具等场景,可避免对全局作用域的污染,同时减少重复代码。

808.日志监控问题:可有办法将请求的调用源码地址包括代码行数也上报上去?【热度: 814】【web应用场景】【出题公司: 阿里巴巴】

关键词:日志监控问题

在使用了代码混淆(例如 Webpack 的 mina-hash、chunkhash 或 contenthash)的前端代码中,即使执行了混淆,依然可以通过以下方法在日志监控时提供足够的上下文信息,主要包括被请求的源代码地址以及代码行数:

源码映射(Source Maps)

  1. 生成 Source Maps: 在构建过程中生成功能强大的源码映射(Source Maps)文件是标准做法。Source Maps 主要用于将混淆、压缩后的 JavaScript 代码映射回到其原始版本,允许在浏览器调试工具中查看原始代码和追踪错误。

    • 保存映射文件: 在生产版本中生成如.map的 Source Map 文件,并确保它们正常处理(通常是将它们放置在服务器上的一个公开但安全的位置)。
    • 反映在 Source Maps 中的映射: Source Maps 文件应将原始的源文件路径和行号映射到构建后的代码中对应的位置。
  2. 错误跟踪系统集成: 使用错误跟踪工具(也常被称为 Error Monitoring 平台, 如 Sentry、LogRocket、Bugsnag 等),这些工具通常兼容并支持 Source Maps:

    • 自动和源码追踪: 漏洞和崩溃报告将自动包含被未混淆的源码引用,您只需确保生产版本的 Source Maps 配置正确。

    • 代码行号报告: 用户报告的堆栈跟踪信息将包括对应底层源文件,而非混淆后的行号。

自定义错误日志逻辑

  1. 覆盖全局的错误处理器: 对于更高级的错误追踪,你可能需要在前端代码中维护自定义的错误处理逻辑。

    • 使用.Window.onerrortry...catch:Window.onerror中捕捉到运行时错误时,或者在自定义函数内try...catch捕获的错误,你可以从错误的堆栈跟踪中提取当前运行代码的位置,并尝试将符号化的堆栈信息发送到后端服务器。
  2. 在后端查阅符号化堆栈: 为了安全和性能的考虑,源码映射通常不包括在客户端的部署中。因此固体堆栈信息需要在服务器端符号化,这是针对转换后的堆栈轨迹进行处理,将反向转换为源代码行。

注意:

  • 确保 Source Maps 不公开到客户端以避免潜在的安全风险。应该将它们存放于受控的服务器环境,以避免源码泄露或不当使用。

  • 以上方案更适合于开发或测试环境提供详细调试信息,确保在最终部署产品之前只公开给授权的人员。

资深开发者相关问题【共计 5 道题】

799.如何标准化处理线上用户反馈的问题【热度: 631】【web应用场景】

关键词:处理线上用户反馈

作者之所以要将这个问题定义为 【master】级别, 是因为这个问题, 说简单又简单, 说难又是有不小难度的。

作者认为:在一个团队里面, 能够快速解决用户的线上反馈问题, 这个是 中级、高级开发的能力要求。 但是,在一个团队里面, 提供一个完整的线上问题反馈的解决方案, 是一个资深研发工程师的能力要求模型。

还有这个是一个开放型的问题,各位小伙伴可以根据各自的情况, 自由发挥吧

修复 bug 研发往往需要先复现,而复现需要依赖一些关键信息,比如用户操作路径,日志信息等等;但站在组织架构角度,研发同学一般不会直接跟客户打交道,所以在客户提出问题的同时尝试搜集必要的 bug 信息对于整个 bug 修复流程很有重要。

当然在很多公司, 用户问题是会先反馈给销售团队或者技术支持团队。 我们这里讨论的情况是, 问题就已经反馈到了研发同学的情况。

客户沟通原则

原则很简单, 就是尝试自己复现, 如果自己无法复现, 再去尝试跟客户沟通。

前期通用排查手段

1. 是否受缓存影响?

浏览器缓存:包裹 cookies、本地缓存、indexDB 等等,这些缓存一般存储用户数据,账号信息,关键逻辑缓存等等。验证是否受浏览器缓存影响最直接的是让用户新开一个无痕浏览器测试功能是否正常即可,如果无痕正常但非无痕有问题,那就可以确定是这个问题了。

2. 是否受浏览器插件影响?

也是直接使用无痕浏览器验证功能是否正常

3. 浏览器版本问题

尝试升级浏览器即可, 或者换一个浏览器

4. 网络网关问题

遇到这个问题, 应该该用户整个网内都有该问题。

可以通过心跳检测, 资源加载检测等手段, 确认是否是网络问题。

信息收集

这部分主要收集用户的一些操作信息, 例如用户操作路径、报错信息、运行日志等。

这里就直接整理一下需要收集的一些信息。

  • 用户复现问题路径
  • 用户信息
  • 客户出现问题使用的操作系统和版本
  • 客户使用的浏览器类型与具体版本
  • 报错信息
  • 客户遇到问题时的截图或录屏
  • 此问题是否是近期突然出现还是一直存在
  • 对于公司群体用户是否只有特定用户遇到了这个问题
  • 性能问题的 performance 文件

这里只是列举了一些常用的信息,建议信息收集的时候, 直接介入一个完整的日志报警平台。 通过上报日志与监控报警的方式来收集这部分信息。

这里如果公司没有自检报警监控的框架, 我这里直接就推荐开源日志框架的 Sentry

Sentry:一个功能强大的错误监控和日志收集工具。支持多种前端框架和语言,能够实时捕获和报告前端应用中的错误和异常,并提供详细的错误上下文信息。

参考文档

800.如何做好前端监控方案【热度: 672】【web应用场景】

关键词:前端监控

作者推荐可以直接参考下面这个文章就好了, 写的挺不错的。 juejin.cn/post/728560...

作者在这里, 对上面的文章进行一下简单的总结

全文总结: Web 前端监控的方案,包括前端监控的意义、内容、形式、总体方案设计、监控指标、前端埋点方案、上报逻辑、监控数据存储、管理平台展示、报警通知、优化整改等方面。

重要:

  • 前端监控的意义:如同城市探头,实时监测保证系统稳定高效,为业务赋能获取更多用户。能够快速解决用户线上问题、用户性能问题;给予产品决策提供数据支撑。

  • 2-5-8 原则:阐述不同响应时间用户的感受和可能的行为。

  • 监控的内容:包括用户行为程序异常、运行性能。

  • 监控的形式:分为主动和被动监控。

  • 总体方案设计:涵盖页面埋点、数据上报、后台存储、汇总统计、报警展示、优化整改等环节。

  • 监控指标:性能指标如 FP、FCP、FMP 等以及 Google Web Vitals 中的 LCP、FID、CLS 等,还有用户指标如 UV、PV 等。

  • 前端埋点方案:介绍了写死在业务代码、全量埋点、动态埋点三种方式,推荐动态埋点。

  • 上报逻辑:ajax、fetch 上报、image 上报、jsonp 上报、sendBeacon 上报,推荐 sendBeacon 上报。

  • 监控数据的存储:可存于 Hadoop 大数据平台、MySQL 关系数据库、NoSQL 存储。

  • 管理平台展示:包括注册和管理业务项目、查看监控数据、配置监控规则和阈值。

  • 报警通知:通过定时任务读取配置表,根据规则查询数据,有多种通知形式。

  • 优化整改:针对性能不达标和用户留存低提出多种措施。

811.日志监控:如何还原用户操作流程【热度: 450】【web应用场景】【出题公司: TOP100互联网】

关键词:日志监控 - 还原现场、日志监控 - 前端录制用户行为技术方案

需求

一种手段来获取用户某一时段连续的操作行为,也就是录制用户行为,包括整个会话中的每一个点击、滑动、输入等行为,同时支持回放录制的操作行为,完整且真实地重现用户行为以帮助我们回溯或分析某些使用场景。

实现方式

方案对比

对比内容 视频录制 页面截图 Dom 快照录制
开源库 WebRTC 原生支持 html2canvas rrweb
用户感知 录制有感 录制无感 录制无感
产物大小 相对较小
兼容性 详见相关 API 兼容性 部分场景内容截图无法显示 兼容性相对较好
信息安全 无法脱敏 无法脱敏 可以脱敏
可操作性 强(支持数据脱敏/加密等)
回放清晰度 录制时决定,有损录制 录制时决定,有损录制 高保真

实操

视频录制

录制用户行为最容易想到的就是将屏幕操作通过视频的方式录制下来,目前浏览器本身已经提供了一套基于音视轨的实时数据流传输方案 WebRTC(Web Real-Time Communications),在我们的录屏使用场景主要关注以下几个 API:

  • getDisplayMedia() - 提示用户给予使用媒体输入的许可从而获取屏幕的流;
  • MediaRecorder() - 生成对指定的媒体流进行录制的 MediaRecorder 对象;
  • ondataavailable - 当 MediaRecorder 将媒体数据传递到应用程序以供使用时将触发该事件;

整体录制流程如下:

  1. 调用mediaDevices.getDisplayMedia()由用户授权选择屏幕进行录制,获取到数据流;
  2. 生成一个new MediaRecorder()对象录制获取的屏幕的数据流;
  3. 在 MediaRecorder 对象上设置ondataavailable监听事件用于获取录制的 Blob 数据。
html 复制代码
代码解读<template>
  <video ref="playerRef"></video>
  <button @click="handleStart">开启录制</button>
  <button @click="handlePause">暂停录制</button>
  <button @click="handleResume">继续录制</button>
  <button @click="handleStop">结束录制</button>
  <button @click="handleReplay">播放录制</button>
  <button @click="handleReset">重置内容</button>
</template>

<script lang="ts" setup>
  import { ref, reactive } from "vue";

  const playerRef = ref();
  const state = reactive({
    mediaRecorder: null as null | MediaRecorder,
    blobs: [] as Blob[],
  });

  // 开始录制
  const handleStart = async () => {
    const stream = await navigator.mediaDevices.getDisplayMedia();
    state.mediaRecorder = new MediaRecorder(stream, {
      mimeType: "video/webm",
    });
    state.mediaRecorder.addEventListener("dataavailable", (e: BlobEvent) => {
      state.blobs.push(e.data);
    });
    state.mediaRecorder?.start();
  };
  // canvas录制(特殊处理)
  const handleCanvasRecord = () => {
    const stream = canvas.captureStream(60); // 60 FPS recording
    const recorder = new MediaRecorder(stream, {
      mimeType: "video/webm;codecs=vp9",
    });
    recorder.ondataavailable = (e) => {
      state.blobs.push(e.data);
    };
  };
  // 暂停录制
  const handlePause = () => {
    state.mediaRecorder?.pause();
  };
  // 继续录制
  const handleResume = () => {
    state.mediaRecorder?.resume();
  };
  // 停止录制
  const handleStop = () => {
    state.mediaRecorder?.stop();
  };
  // 播放录制
  const handleReplay = () => {
    if (state.blobs.length === 0 || !playerRef.value) return;
    const blob = new Blob(state.blobs, { type: "video/webm" });
    playerRef.value.src = URL.createObjectURL(blob);
    playerRef.value.play();
  };

  const handleReset = () => {
    state.blobs = [];
    state.mediaRecorder = null;
    playerRef.value.src = null;
  };
  const handleDownload = () => {
    if (state.blobs.length === 0) return;
    const blob = new Blob(state.blobs, { type: "video/webm" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.style.display = "none";
    a.download = "record.webm";
    a.click();
  };
</script>

页面截图

众所周知,视频是由一帧帧的画面组合而成的,因此我们可以按照一定时间间隔来截图的方式保存当前页面快照,然后将快照按照相同的截取速度播放形成视频就能实现用户行为录制了。最常用的截图方法就是以 html2canvas 库为代表的 canvas 截图,我们在使用过程中也发现了较多问题:

  1. canvas 截图有较多局限之处,例如无法绘制动画、样式错位、不支持部分 CSS 样式等;
  2. 截图性能开销较大,可能会导致掉帧,例如我们在尝试中 css 动画有非常明显的卡顿等;
  3. 截图资源体积大,我们尝试中截图时单张图片体积为 200k 左右,以 24 帧来算一分钟录制的图片体积将近 300MB,对带宽和资源存储都是浪费;
  4. 在需要忽略的元素上增加 data-html2canvas-ignore 属性或者设置 ignoreElements 属性删除特定元素可以对某些特定数据或内容进行脱敏,但会直接删除元素无法做到"有占位但无内容"效果,影响页面布局。
html 复制代码
代码解读<template>
  <el-button @click="handleStart">开启录制</el-button>
  <el-button @click="handleStop">停止录制</el-button>
  <el-button @click="handleReplay">播放录制</el-button>
  <img :src="state.imgs[state.num ?? 0]" />
</template>

<script lang="ts" setup>
  import { reactive } from "vue";
  import html2canvas from "html2canvas";

  const state = reactive({
    visible: false,
    imgs: [] as string[],
    num: 0,
    recordInterval: null as any,
    replayInterval: null as any,
  });

  const FPS = 30;
  const interval = 1000 / FPS;
  const handleStart = async () => {
    handleReset();
    state.recordInterval = setInterval(() => {
      if (state.imgs.length > 100) {
        handleStop();
        return;
      }
      html2canvas(document.body).then((canvas: any) => {
        const img = canvas.toDataURL();
        state.imgs.push(img);
      });
    }, interval);
  };

  const handleStop = () => {
    state.recordInterval && clearInterval(state.recordInterval);
  };

  const handleReplay = async () => {
    state.recordInterval && clearInterval(state.recordInterval);
    state.num = 0;
    state.visible = true;
    state.replayInterval = setInterval(() => {
      if (state.num >= state.imgs.length - 1) {
        clearInterval(state.replayInterval);
        return;
      }
      state.num++;
    }, interval);
  };

  const handleReset = () => {
    state.imgs = [];
    state.recordInterval = null;
    state.replayInterval = null;
    state.num = 0;
  };
</script>

Dom 快照录制

💡 Dom 快照录制 - rrweb 库 是目前最为流行的解决方案,一些商业化平台解决方案也都主要基于 rrweb 库来进行录制与回放的功能开发。

rrweb 主要由 3 部分组成:

  1. rrweb-snapshot,包含 snapshot 和 rebuild 两部分,snapshot 用于将 DOM 及其状态转化为可序列化的数据结构并添加唯一标识,rebuild 是将 snapshot 记录的数据结构重建为对应 DOM。
  2. rrweb,包含 record 和 replay 两个功能,record 用于记录 DOM 中的所有变更,replay 则是将记录的变更按照对应的时间一一重放。
  3. rrweb-player,为 rrweb 提供一套 UI 控件,提供基于 GUI 的暂停、快进、拖拽至任意时间点播放等功能。

分别设计到了【录制】和【回访】两个场景

细节可以参考官网文档即可

参考文档

juejin.cn/post/728042...

812.[React] scheduler 调度机制原理【热度: 660】【web框架】【出题公司: TOP100互联网】

关键词:scheduler 调度机制原理

细节过于复杂, 可以参考一下文档:

后续是题库作者对上述文档的一些重点信息总结:

  1. scheduler 概念
  2. 时间片与优先级 概念
  3. 优先级切分
  4. 任务队列
  5. scheduleCallback
  6. requestHostCallback
  7. MessageChannel
  8. performWorkUntilDeadline
    • 任务的中断和恢复

    • 判断任务的完成状态

    • 取消任务

813.[React] useRef 是如何实现的【热度: 299】【web框架】【出题公司: TOP100互联网】

关键词:useRef 实现

该问题也是非常复杂, 需要深入源码, 可以看下面文章解析:

juejin.cn/post/734175...

以下是题库作者对上面文档的一些提炼总结

  • 什么是数据共享层
  • hooks
    • 如何确定 fiber 对应的 hook 上下文?
    • hook 是如何存在的?保存在什么地方?
    • 多个 hook 如何处理?
  • useRef
    • 实现原理
    • 标记 Ref
    • 执行 Ref 操作
  • mount 该如何操作
  • update 的时候该如何操作
  • 整体执行流程
    • 标记

    • 执行

相关推荐
姚*鸿的博客1 分钟前
pinia在vue3中的使用
前端·javascript·vue.js
宇文仲竹20 分钟前
edge 插件 iframe 读取
前端·edge
Kika写代码23 分钟前
【基于轻量型架构的WEB开发】【章节作业】
前端·oracle·架构
天下无贼!2 小时前
2024年最新版Vue3学习笔记
前端·vue.js·笔记·学习·vue
Jiaberrr2 小时前
JS实现树形结构数据中特定节点及其子节点显示属性设置的技巧(可用于树形节点过滤筛选)
前端·javascript·tree·树形·过滤筛选
赵啸林2 小时前
npm发布插件超级简单版
前端·npm·node.js
我码玄黄2 小时前
THREE.js:网页上的3D世界构建者
开发语言·javascript·3d
罔闻_spider2 小时前
爬虫----webpack
前端·爬虫·webpack
吱吱鼠叔2 小时前
MATLAB数据文件读写:1.格式化读写文件
前端·数据库·matlab
爱喝水的小鼠2 小时前
Vue3(一) Vite创建Vue3工程,选项式API与组合式API;setup的使用;Vue中的响应式ref,reactive
前端·javascript·vue.js