面试能不能不这么费口水🤣😶‍🌫️:面题【1】

388 阅读9分钟

面试题:

# 刚面试的小白来面试啦😮‍💨,整理面题【2】

# 2025前端高频面试题--CSS篇问点

开始是自我介绍和项目相关讲解。以下帮整理的面试题内容,主要针对个人·(排版比较随意)当然如果你愿意看,我也很乐意分享出来一起学习进步~~

第5题:Promise 的几种状态分别是怎么变化的?

Promise 有三种状态:pending(进行中)、fulfilled(已解决)和 rejected(已拒绝)。当一个 Promise 被创建时,它的初始状态是 pending。然后它会根据执行器函数中的逻辑变为 fulfilled 或 rejected 状态。

当执行器函数中的代码成功执行并调用 resolve() 方法时,Promise 变为 fulfilled 状态。 当执行器函数中的代码抛出错误或调用 reject() 方法时,Promise 变为 rejected 状态。 一旦 Promise 进入了 fulfilled 或 rejected 状态,这个状态就不会再改变。

第6题:

问题: 有一段 promise 代码块,逻辑是 new 一个 promise,function 有两个参数 resolved 和 rejected,执行这个 function 的时候,还没有执行到 resolved 或者 rejected 回调之前,我们的代码发生了报错,下面链式调用了.then.catch.then.catch,会怎么执行?

简单回答: 如果在 Promise 执行过程中发生错误,并且在调用 resolve() 或 reject() 之前,那么该错误会被捕获并在 catch() 中处理。因此,在这种情况下,第一个 .catch() 将被触发,而后续的 .then() 和 .catch() 不会被执行。

怎么理解这个回答?

当一个 Promise 的执行器函数(executor function)在执行过程中抛出了一个错误,但在此之前没有调用 resolve() 或 reject() 方法时,这个错误会被 Promise 自动捕获,并将 Promise 的状态变为 rejected。这意味着,即使错误发生在 resolve() 或 reject() 被调用之前,该 Promise 也会被视为失败,并且链式调用中的第一个 .catch 方法会被触发。

考虑以下代码片段:

new Promise((resolve, reject) => {
    console.log('Promise 执行');
    throw new Error('执行器中抛出的错误'); // 抛出一个错误
    // resolve('成功'); // 这一行永远不会被执行
    // reject('失败'); // 这一行也永远不会被执行
})
.then(result => {
    console.log('第一个 then: ' + result);
})
.catch(error => {
    console.log('第一个 catch: ' + error.message); // 捕获错误
})
.then(result => {
    console.log('第二个 then: ' + result);
})
.catch(error => {
    console.log('第二个 catch: ' + error.message);
});

输出结果

Promise 执行
第一个 catch: 执行器中抛出的错误
第二个 then: undefined

执行流程解析

  1. Promise 创建与执行:当 new Promise 被调用时,执行器函数立即执行。在这个过程中,console.log('Promise 执行') 会被执行,随后抛出一个错误。
  2. 错误捕获:由于抛出了一个错误,Promise 自动将状态从 pending 更改为 rejected,并将错误传递给最近的 .catch 方法。
  3. 第一个 .catch 被触发:因为 Promise 已经处于 rejected 状态,所以第一个 .catch 方法会被调用,输出 '第一个 catch: 执行器中抛出的错误'
  4. 第二个 .then 的执行.catch 方法本质上也是 .then 的一种形式,它返回一个新的 Promise,这个 Promise 默认是 resolved 的,除非 .catch 的回调函数抛出错误或返回一个 rejected 的 Promise。因此,在第一个 .catch 成功处理了错误之后,链式调用中的下一个 .then 会被执行,但是它不会接收到任何特别的值,因为它接收到的是 .catch 方法返回的默认 resolved 状态的 Promise。
  5. 后续 .catch 不会被触发:由于第二个 .then 没有抛出错误,后续的 .catch 方法不会被调用。

总结

  • 当 Promise 的执行器函数抛出错误时,Promise 会自动变为 rejected 状态。

  • 链式调用中的第一个 .catch 会捕获这个错误,并处理它。

  • 如果 .catch 成功处理了错误,那么后续的 .then 方法会继续执行。

  • 如果 .then 或 .catch 中再次抛出错误,它会跳过后续的 .then 方法,直接寻找下一个 .catch 方法来处理错误。

第7题:事件循环机制(去看看 w3c 的最新标准)

事件循环是 JavaScript 引擎的核心概念之一,用于管理异步任务的执行顺序。JavaScript 是单线程语言,这意味着在同一时间只能执行一个任务。为了支持异步操作,如网络请求、定时器等,JavaScript 使用事件循环来调度这些任务。

从下面图片进行讲解: image.png 事件循环的基本流程如下:

  1. 在一个大的宏任务宿主环境下,JavaScript 引擎首先执行同步代码,直到遇到异步任务(如 setTimeout、Promise 等)。
  2. 异步任务被添加到相应的队列中(例如,setTimeout 添加到计时器队列,Promise 添加到微任务队列)。
  3. 当当前栈清空后,事件循环从队列中取出下一个任务并执行。
  4. 如果任务执行完成后还有其他任务等待执行,则重复步骤 3 直至所有任务完成。

推荐相关面试pink视频

第8题:说出代码执行的顺序

console.log(1)

setTimeout(() => {
    console.log(2)
}, 0)

new Promise((resolve, reject) => {
    console.log(3)
    resolve()
}).then(() => {
    console.log(4)
})

document.appendChild(p); // p 标签在前面已经定义好了的

最终输出顺序为: 1 3 4 2 (因为 setTimeout 在微任务之后执行)

简单解释一下:

  1. console.log(1) - 输出 "1"
  2. setTimeout - 设置一个延迟时间为 0 毫秒的回调函数,但不会立即执行。
  3. 创建一个新的 Promise 并立即执行其执行器函数:
  4. console.log(3) - 输出 "3"
  5. resolve() - 解决 Promise,将其状态设置为 fulfilled
  6. Promise 的 .then() 处理程序将被添加到微任务队列中。
  7. document.appendChild(p) - 将元素插入 DOM
  8. 由于 setTimeout 的延迟时间为 0 毫秒,所以它会在当前宏任务结束后立即执行。但是,由于 Promise 的 .then() 处理程序是在微任务队列中,它将在 setTimeout 完成后立即执行。

第9题:输入URL后发生了什么?

当你在浏览器地址栏输入一个URL并按下回车键后,会发生一系列复杂的操作,这些操作大致可以分为以下几个步骤:

image.png

  1. URL解析:浏览器首先解析输入的URL,提取出协议(如HTTP或HTTPS)、域名、端口号(如果指定)、路径以及查询参数等信息。

  2. DNS域名解析:浏览器会尝试从本地缓存中查找域名对应的IP地址。如果找不到,它会查询操作系统的DNS缓存,如果还是找不到,会向本地DNS服务器发送查询请求。本地DNS服务器会通过递归或迭代查询的方式,最终找到目标域名的IP地址并返回给浏览器

  3. 建立TCP连接:浏览器使用获取到的IP地址,通过三次握手与服务器建立TCP连接。这个过程确保了数据传输的可靠性。

  4. 发送HTTP请求:一旦TCP连接建立,浏览器会发送一个HTTP请求到服务器。请求中包含请求方法(如GET或POST)、请求头(包括User-Agent、Accept等信息)以及请求体(如果适用)。

  5. 服务器处理请求并返回响应:服务器接收到请求后,会解析请求头和请求体,根据请求的内容进行处理。处理完成后,服务器会生成一个HTTP响应,包含状态码、响应头和响应体(如HTML文档、图片等),并通过已建立的TCP连接返回给浏览器

  6. 浏览器接收响应并解析渲染页面:浏览器接收到服务器的响应后,会根据响应头的信息判断响应类型,并解析响应体。对于HTML文档,浏览器会构建DOM树和CSSOM树,然后结合这两个树构建渲染树,计算布局并绘制页面。在这个过程中,浏览器可能会发现需要加载更多的资源(如CSS文件、JavaScript文件、图片等),会发起新的请求来加载这些资源。

  7. 断开TCP连接:当所有的资源加载完成并且页面渲染完毕后,浏览器会根据HTTP响应头中的Connection字段决定是否断开TCP连接。如果Connection字段设置为keep-alive,则连接会保持打开状态以供后续请求使用;否则,连接会被断开。

推荐相关视频

第10题:简述浏览器内核的作用

浏览器内核是浏览器的核心组件,负责渲染网页内容并处理网页上的交互。浏览器内核的主要职责包括:

  1. 解析HTML、CSS和JavaScript:将这些代码转换为浏览器可以理解和显示的内容。
  2. 构建DOM树和CSSOM树:解析HTML生成DOM树,解析CSS生成CSSOM树。
  3. 布局计算:根据渲染树计算每个节点的位置和大小,确定页面的布局。
  4. 绘制页面:将计算好的布局信息转换为屏幕上的像素,显示在用户的浏览器窗口中。
  5. 网络通信:管理与服务器之间的通信,包括发起请求、接收响应、处理重定向等。

不同的浏览器可能使用不同的内核,例如Chrome和Edge使用Blink(基于WebKit),Firefox使用Gecko,而Safari则使用WebKit。每个内核都有自己的特点和优化策略。

浏览器内核 对比 JS引擎

JavaScript引擎是浏览器内核的一部分,专门负责解析和执行JavaScript代码。具体职责包括:

  1. 解析JavaScript代码:将JavaScript代码转换为可执行的字节码或机器码。
  2. 执行JavaScript代码:运行解析后的代码,实现网页的动态效果和交互功能。
  3. 内存管理:管理JavaScript代码中使用的内存,包括垃圾回收等。

浏览器内核 :网络通信功能

  1. 发起请求:当用户输入URL或点击链接时,浏览器内核会解析URL并发起HTTP或HTTPS请求,请求特定的资源。
  2. 接收响应:浏览器内核接收服务器返回的HTTP响应,解析响应头和响应体,处理返回的数据。
  3. 处理重定向:如果服务器返回的响应中包含重定向信息(如HTTP状态码301或302),浏览器内核会自动处理这些重定向,发起新的请求。
  4. 管理连接:浏览器内核管理与服务器之间的TCP连接,包括建立、维护和断开连接。

期待下一篇吧!

image.png