前端面试第 68 期 - 2024.10.07 更新前端面试问题总结(21道题)

2024.09.28 - 2024.10.07 更新前端面试问题总结(21道题)

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

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

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

目录:

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

      1. 完整域名的构成部分【网络】
  • 中级开发者相关问题【共计 8 道题】

      1. try...catch 是否能捕获异步异常【热度: 701】【web应用场景】
      1. 浏览器中如何实现剪切板复制内容的功能【热度: 95】【web应用场景】【出题公司: 美团】
      1. http ETag 值改变了,是否意味着文件内容一定已经更改【热度: 138】【网络、web应用场景】【出题公司: 阿里巴巴】
      1. 站点是如何保持登录状态【热度: 210】【网络、web应用场景】【出题公司: 腾讯】
      1. http 向 https 做重定向应该使用哪个状态码【热度: 336】【网络、web应用场景】【出题公司: 网易】
      1. http 缓存中 no-cache 与 no-store 的区别是什么【热度: 564】【网络、web应用场景】【出题公司: 小米】
      1. 对于已经 import 但未实际使用的模块使用 webpack 还会对它打包吗【热度: 108】【工程化】【出题公司: 阿里巴巴】
      1. http2 中的首部压缩是什么【网络】
  • 高级开发者相关问题【共计 11 道题】

      1. 前端部署应该要考虑哪些问题【热度: 310】【工程化】【出题公司: 腾讯】
      1. 前端需要加载一个大体积的文件时, 一般有哪些优化思路【热度: 594】【工程化】【出题公司: 腾讯】
      1. 分片上传文件,如何校验文件完整性【热度: 220】【web应用场景】
      1. http 响应头中的 ETag 值是如何生成的【热度: 37】【web应用场景】【出题公司: 阿里巴巴】
      1. http 静态文件缓存 Last-Modified 是根据什么生成的【热度: 85】【网络、web应用场景】【出题公司: 阿里巴巴】
      1. http header content-type 为 application/octet-stream,则代表什么意思【热度: 136】【网络、web应用场景】
      1. http 缓存 header 中的 Date 与 Last-Modified 有什么不同【热度: 276】【网络、web应用场景】【出题公司: Shopee】
      1. https 中如何保证证书是可信任的【热度: 210】【网络】【出题公司: 阿里巴巴】
      1. 如果 cookie 没有设置 maxage, 那么这一条 cookie 失效时间改怎么算【热度: 42】【网络】【出题公司: 小红书】
      1. css 中属性选择器及类选择器的权重哪个高【热度: 642】【CSS、web应用场景】
      1. commonjs 模块化中 module.exports 与 exports 有什么区别, 该如何选择【热度: 194】【工程化、web应用场景】
  • 资深开发者相关问题【共计 1 道题】

      1. 如何进行代码质量检测【热度: 497】【web应用场景】【出题公司: 小米】

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

971. 完整域名的构成部分【网络】

完整域名由多个部分组成,主要包括以下几个部分:

一、顶级域名(Top-Level Domain,TLD)

  1. 含义

    • 顶级域名是域名中最右边的部分,它表示域名的类型或所属的国家或地区。例如,在"example.com"中,".com"就是顶级域名。
    • 顶级域名分为通用顶级域名(gTLD)和国家代码顶级域名(ccTLD)。通用顶级域名如".com"(商业机构)、".org"(非营利组织)、".net"(网络服务机构)等;国家代码顶级域名如".cn"(中国)、".uk"(英国)、".jp"(日本)等。
  2. 作用

    • 顶级域名帮助用户快速识别域名的类型或所属地区,同时也在互联网的命名体系中起到分类和标识的作用。

二、二级域名(Second-Level Domain,SLD)

  1. 含义

    • 二级域名位于顶级域名的左边,是域名中的主要标识部分。例如,在"example.com"中,"example"就是二级域名。
    • 二级域名通常由网站所有者或组织自行定义,可以是任何符合域名命名规则的字符串。
  2. 作用

    • 二级域名用于区分不同的网站、组织或服务。它是网站的主要标识,用户通过二级域名来识别和访问特定的网站。

三、子域名(Subdomain)

  1. 含义

    • 子域名是位于二级域名前面的部分,它可以进一步细分域名的层次结构。例如,在"blog.example.com"中,"blog"就是子域名。
    • 子域名可以有多个层次,例如"sub1.sub2.example.com"。
  2. 作用

    • 子域名可以用于划分不同的业务模块、部门或功能区域。例如,一个公司可以使用"blog"子域名来表示其博客站点,使用"shop"子域名来表示其电子商务站点。

四、协议部分(如 http:// 或 https://)

  1. 含义

    • 协议部分位于域名的前面,用于指定访问网站所使用的通信协议。常见的协议有"http://"(超文本传输协议)和"https://"(安全超文本传输协议)。
  2. 作用

    • 协议部分决定了浏览器与服务器之间的通信方式和安全性。"https://"协议提供了加密和安全的通信,保护用户数据的安全。

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

958. try...catch 是否能捕获异步异常【热度: 701】【web应用场景】

关键词:异常处理

题目是:以下代码有错吗?如果有错,应该如何改正?

js 复制代码
try {
  setTimeout(() => {
    throw new Error("err");
  }, 200);
} catch (err) {
  console.log(err);
}

try {
  Promise.resolve().then(() => {
    throw new Error("err");
  });
} catch (err) {
  console.log(err);
}

解答

才知道 try...catch 不能异步捕获代码错误。在 JavaScript 中,setTimeout 是一个异步函数,它的回调函数会在指定的延时后被放入事件队列,等待当前执行栈清空后才执行。因此,当 setTimeout 的回调函数执行并抛出错误时,try...catch 已经执行完毕,无法捕捉到异步回调中的错误。 正确的做法是在异步操作中直接处理错误,例如使用回调函数、Promises 或者 async/await 结合 try...catch

js 复制代码
new Promise((resolve, reject) => {
  setTimeout(() => {
    try {
      throw new Error("err");
    } catch (err) {
      reject(err);
    }
  }, 200);
})
  .then(() => {
    // 正常执行时的处理逻辑
  })
  .catch((err) => {
    console.log(err); // 这里会捕捉到错误
  });

至于第二个例子,尝试使用 try...catch 来捕捉一个在 Promise 链中抛出的错误。这种方式同样是无效的,因为 try...catch 不能捕捉到在 Promise 链中的异步错误。

在 Promise 中抛出一个错误(例如通过 throw 语句)会导致 Promise 被拒绝(或失败)。要正确处理这个错误,需要在 Promise 链中使用.catch 方法或者在一个 async 函数中使用 try...catch。

js 复制代码
// 方法一
Promise.resolve()
  .then(() => {
    throw new Error("err");
  })
  .catch((err) => {
    console.log(err); // 这里会捕捉到错误
  });

// 方法二
async function handleError() {
  try {
    await Promise.resolve().then(() => {
      throw new Error("err");
    });
  } catch (err) {
    console.log(err); // 这里会捕捉到错误
  }
}

handleError();

补充

960. 浏览器中如何实现剪切板复制内容的功能【热度: 95】【web应用场景】【出题公司: 美团】

关键词:document.execCommand('copy')、navigator.clipboard API

在浏览器中,可以通过以下几种方式实现剪切板复制内容的功能:

一、使用document.execCommand('copy')

  1. 基本用法

    • 在 JavaScript 中,可以使用document.execCommand('copy')方法来执行复制操作。但这个方法需要先选中页面上的一部分内容或者将内容放入一个可编辑的元素中。
    • 例如:
    html 复制代码
    <button onclick="copyToClipboard()">复制</button>
    <div id="contentToCopy">这是要复制的内容</div>
    javascript 复制代码
    function copyToClipboard() {
      const content = document.getElementById("contentToCopy").textContent;
      const tempInput = document.createElement("input");
      tempInput.value = content;
      document.body.appendChild(tempInput);
      tempInput.select();
      document.execCommand("copy");
      document.body.removeChild(tempInput);
    }
    • 在这个例子中,当用户点击按钮时,将获取要复制的内容,创建一个临时的<input>元素,将内容放入其中,选中该元素的内容,然后执行复制操作,最后移除临时元素。
  2. 限制和兼容性

    • 这种方法在一些浏览器中可能存在兼容性问题,并且需要用户交互(如点击按钮)才能触发复制操作。
    • 此外,现代浏览器对于使用document.execCommand的限制越来越多,因为它可能存在安全风险。

二、使用navigator.clipboard API

  1. 异步方法

    • 现代浏览器提供了navigator.clipboard API,它提供了更安全和可靠的方式来访问剪切板。这个 API 主要使用异步方法来进行复制操作。
    • 例如:
    javascript 复制代码
    async function copyToClipboard() {
      const content = "这是要复制的内容";
      try {
        await navigator.clipboard.writeText(content);
        console.log("内容已复制到剪切板");
      } catch (err) {
        console.error("无法复制内容到剪切板:", err);
      }
    }
    • 在这个例子中,使用navigator.clipboard.writeText()方法将指定的内容复制到剪切板。如果操作成功,控制台将打印"内容已复制到剪切板";如果出现错误,将打印错误信息。
  2. 权限要求

    • 使用navigator.clipboard API 可能需要用户的明确许可,特别是在一些注重隐私的浏览器中。如果用户没有授予权限,复制操作可能会失败。
    • 可以通过在页面加载时请求用户的权限来提高复制操作的成功率。

三、结合事件处理

  1. 响应用户交互

    • 可以结合用户的交互事件,如点击按钮、按下快捷键等,来触发复制操作。这样可以提供更好的用户体验。
    • 例如,可以使用addEventListener方法来监听按钮的点击事件:
    html 复制代码
    <button id="copyButton">复制</button>
    javascript 复制代码
    document.getElementById("copyButton").addEventListener("click", copyToClipboard);
  2. 快捷键支持

    • 还可以监听键盘快捷键事件,例如Ctrl+C(在 Windows 和 Linux 系统中)或Command+C(在 macOS 系统中),来模拟系统的复制操作。
    • 这需要使用keydownkeyup事件,并检查按下的键是否是复制快捷键。但这种方法可能会受到浏览器的安全限制,并且不同浏览器对快捷键的处理方式可能不同。

通过以上方法,可以在浏览器中实现剪切板复制内容的功能。根据具体的需求和浏览器的兼容性,可以选择合适的方法来实现复制操作。同时,需要注意用户的隐私和安全问题,确保复制操作是在用户许可的情况下进行的。

962. http ETag 值改变了,是否意味着文件内容一定已经更改【热度: 138】【网络、web应用场景】【出题公司: 阿里巴巴】

关键词:ETag 值

如果 HTTP 响应头中的 ETag 值改变了,通常意味着资源(文件或其他内容)很可能发生了变化,但并不绝对意味着文件内容一定已经更改。

一、可能导致 ETag 变化但文件内容未更改的情况

  1. 生成方式的变化:

    • 如果服务器更改了生成 ETag 的方式,即使文件内容没有变化,ETag 也可能不同。例如,服务器原本使用文件的最后修改时间戳作为 ETag,后来改为使用文件内容的哈希值,那么即使文件内容未变,ETag 也会改变。
  2. 服务器配置或逻辑变化:

    • 服务器的某些配置更改或业务逻辑变化可能导致 ETag 的生成与之前不同,而与文件内容本身的变化无关。
    • 比如,服务器在不同的环境中可能有不同的 ETag 生成策略,从开发环境切换到生产环境时,ETag 可能会改变,即使文件内容相同。
  3. 动态资源的非内容相关变化:

    • 对于动态生成的资源,如由服务器端脚本生成的网页,ETag 可能受到一些与内容无关的因素影响。例如,服务器的负载、请求的时间等因素可能导致动态资源的 ETag 变化,而实际生成的内容可能并没有改变。

二、ETag 的作用和可靠性

  1. 缓存验证:

    • ETag 主要用于缓存验证,客户端在后续请求中通过 If-None-Match 请求头将上次接收到的 ETag 发送给服务器,服务器比较 ETag 来判断资源是否发生了变化。如果 ETag 相同,服务器返回 304 Not Modified,客户端可以使用缓存中的资源,节省带宽和提高响应速度。
  2. 相对可靠性:

    • 虽然 ETag 的变化不能绝对确定文件内容的更改,但在大多数情况下,它是一个比较可靠的指示。如果 ETag 发生了变化,客户端应该重新获取资源以确保得到最新的内容。

综上所述,ETag 值的改变不能确凿地证明文件内容一定更改,但它是一个重要的线索,提示客户端可能需要重新获取资源以验证其是否发生了变化。

963. 站点是如何保持登录状态【热度: 210】【网络、web应用场景】【出题公司: 腾讯】

关键词:http 保持登录态

虽然 HTTP 是无状态协议,但可以通过以下几种方式来保持登录状态:

一、Cookie

  1. 工作原理:

    • 当用户成功登录后,服务器在响应中设置一个 Cookie,通常包含用户的身份标识、会话信息等。
    • 客户端(浏览器)会存储这个 Cookie,并在后续的请求中自动将其发送给服务器。
    • 服务器通过检查 Cookie 中的信息来识别用户并确定其登录状态。
  2. 示例:

    • 用户登录时,服务器生成一个唯一的会话 ID,并将其存储在数据库中,同时在响应中设置一个名为"session_id"的 Cookie,值为该会话 ID。
    • 后续请求中,浏览器自动发送包含"session_id"的 Cookie,服务器根据这个会话 ID 查找对应的用户信息,从而确定用户已登录。

二、Session

  1. 结合 Cookie 使用:

    • 服务器端创建一个会话(Session)对象来存储用户的登录状态和其他相关信息。
    • 与 Cookie 类似,服务器在用户登录成功后设置一个包含会话 ID 的 Cookie,客户端在后续请求中携带这个 Cookie。
    • 服务器根据会话 ID 查找对应的 Session 对象,以确定用户的登录状态。
  2. 优点:

    • 相比直接使用 Cookie 存储用户信息,Session 更加安全,因为敏感信息存储在服务器端,而不是在客户端的 Cookie 中。

三、Token(令牌)

  1. JWT(JSON Web Token):

    • 用户登录成功后,服务器生成一个包含用户信息和签名的 JWT 令牌,并将其返回给客户端。
    • 客户端在后续请求中,将 JWT 令牌作为请求头或参数发送给服务器。
    • 服务器通过验证令牌的签名和有效性来确定用户的登录状态。
  2. 优点:

    • 无状态:服务器不需要存储会话信息,只需要验证令牌的有效性,因此可以轻松地进行水平扩展。
    • 跨域支持:JWT 令牌可以在不同的域之间传递,适用于前后端分离的架构。

四、HTTP 基本认证和摘要认证

  1. 基本认证:

    • 客户端在请求中包含用户名和密码,经过 Base64 编码后作为请求头的一部分发送给服务器。
    • 服务器验证用户名和密码的正确性,如果正确则认为用户已登录。
    • 缺点是密码以明文形式传输(虽然经过 Base64 编码,但仍然可以被轻易解码),不安全。
  2. 摘要认证:

    • 是对基本认证的改进,通过使用哈希函数对密码进行加密,提高了安全性。

    • 但仍然存在一些安全风险,并且在每次请求中都需要发送用户名和密码的哈希值,不够便捷。

966. http 向 https 做重定向应该使用哪个状态码【热度: 336】【网络、web应用场景】【出题公司: 网易】

关键词:重定向

从 HTTP 向 HTTPS 做重定向,既可以使用 301 永久重定向状态码,也可以使用 302 临时重定向状态码。以下是对这两种状态码的具体介绍及使用场景分析:

  1. 301 永久重定向
    • 含义:表示请求的资源已被永久地移动到了新的 URL,搜索引擎等客户端会更新其索引,将旧的 URL 替换为新的 URL。未来所有对旧 URL 的访问都应该被定向到新 URL。
    • 优点:一旦设置好 301 重定向,搜索引擎会将权重和排名等信息从旧 URL 转移到新 URL,有利于网站的 SEO。并且用户浏览器会缓存这个重定向信息,下次访问时可以直接跳转到新的 HTTPS 地址,减少了服务器的请求处理。
    • 缺点:如果后续需要更改重定向设置,由于浏览器已经缓存了重定向信息,可能会导致一些用户在一段时间内仍然被重定向到旧的设置,直到缓存过期。
    • 适用场景:如果您的网站已经确定永久地从 HTTP 迁移到 HTTPS,并且希望搜索引擎尽快更新索引,那么使用 301 永久重定向是比较合适的。例如,一个已经完成全站 HTTPS 改造,并且不再使用 HTTP 访问的网站,可以使用 301 重定向来引导用户和搜索引擎。
  2. 302 临时重定向
    • 含义:表示请求的资源暂时被移动到了新的 URL,客户端在后续的请求中应该继续使用旧的 URL 进行访问,直到资源的位置被永久更改。

    • 优点:302 重定向比较灵活,适用于一些临时的情况,比如网站正在进行 HTTPS 的部署或测试,还不确定是否会长期使用 HTTPS,或者在某些特殊情况下需要暂时将用户从 HTTP 引导到 HTTPS。

    • 缺点:由于是临时重定向,搜索引擎可能不会将权重和排名等信息立即转移到新的 URL,并且用户浏览器也可能不会像对待 301 重定向那样缓存重定向信息,这可能会导致每次访问都需要进行重定向操作,增加了服务器的负担。

    • 适用场景:对于一些短期的、过渡性的 HTTP 到 HTTPS 的重定向需求,或者在不确定是否要长期使用 HTTPS 的情况下,可以使用 302 临时重定向。比如,一个新上线的网站,正在测试 HTTPS 的性能和稳定性,此时可以使用 302 重定向来引导用户访问 HTTPS 版本,以便在测试过程中随时切换回 HTTP。

969. http 缓存中 no-cache 与 no-store 的区别是什么【热度: 564】【网络、web应用场景】【出题公司: 小米】

关键词:http 缓存

在 HTTP 缓存中,no-cacheno-store是两种不同的缓存指令,它们的区别如下:

一、no-cache

  1. 含义

    • 当设置了no-cache指令时,这并不意味着不使用缓存。相反,它表示在使用缓存之前,必须先与服务器进行验证,以确定缓存的资源是否仍然有效。
    • 这意味着浏览器在使用缓存的资源之前,会向服务器发送一个条件请求(通常是使用If-Modified-SinceIf-None-Match头部),询问服务器该资源是否有更新。如果服务器返回 304 Not Modified 状态码,表示资源没有更新,浏览器可以使用缓存的资源;如果服务器返回新的资源内容,表示资源有更新,浏览器需要使用新的资源。
  2. 使用场景

    • 适用于需要确保获取到最新资源,但又不想每次都从服务器获取完整资源的情况。例如,对于一些经常更新但更新频率不高的资源,可以使用no-cache指令,以便在资源没有更新时可以快速使用缓存,而在资源有更新时可以获取到最新的资源。
    • 对于一些需要根据用户的特定请求参数来生成资源的情况,也可以使用no-cache指令,以便在每次请求时都让服务器根据请求参数来确定是否返回缓存的资源还是生成新的资源。

二、no-store

  1. 含义

    • no-store指令表示绝对不允许缓存资源。这意味着浏览器在接收到带有no-store指令的响应后,不会将资源存储在任何缓存中,包括浏览器缓存、代理服务器缓存等。每次请求都必须从服务器获取最新的资源。
  2. 使用场景

    • 适用于对安全性要求非常高的资源,例如包含敏感信息的页面或需要严格保证每次都获取到最新数据的资源。
    • 对于一些动态生成的资源,其内容可能会根据不同的请求而变化,并且不希望这些资源被缓存,可以使用no-store指令。例如,一些在线银行页面、交易系统等可能会使用no-store指令来确保用户每次看到的都是最新的信息。

总之,no-cache表示在使用缓存之前需要与服务器进行验证,而no-store表示绝对不允许缓存资源。根据不同的需求,可以选择合适的缓存指令来控制资源的缓存行为。

970. 对于已经 import 但未实际使用的模块使用 webpack 还会对它打包吗【热度: 108】【工程化】【出题公司: 阿里巴巴】

关键词:tree-shaking 使用

在使用 Webpack 进行打包时,对于已经导入(import)但未实际使用的模块,通常情况下不会被打包进去,但这也取决于具体的配置和使用场景。

一、默认行为

在默认情况下,Webpack 会进行"树摇"(tree shaking)操作。树摇是一种优化技术,它可以检测和移除未被使用的代码。如果一个模块被导入但在代码中没有被实际使用,Webpack 会尝试识别并排除这个模块,以减小最终打包文件的大小。

例如:

javascript 复制代码
import { someFunction } from "moduleA";
// 如果 someFunction 在后续代码中没有被调用,Webpack 可能会在打包时排除 moduleA 中未被使用的部分。

二、特殊情况

然而,在某些情况下,即使模块未被直接使用,也可能会被打包进去:

  1. 副作用:如果导入的模块有副作用(例如修改全局状态、注册事件监听器等),即使模块中的具体函数或变量没有被直接使用,Webpack 也可能不会将其排除。因为这些副作用可能对应用的运行产生影响。

    • 例如:
    javascript 复制代码
    import "moduleB"; // moduleB 可能会在导入时执行一些初始化操作,有副作用。
  2. 动态导入:如果使用动态导入(例如通过 import()函数),Webpack 可能无法在打包时确定哪些模块会被实际使用,因此可能会保留一些未被直接使用的模块,以确保在运行时能够正确加载所需的模块。

    • 例如:
    javascript 复制代码
    const moduleName = "moduleC";
    import(moduleName).then((module) => {
      // 使用动态导入的模块。
    });
  3. 第三方库的依赖:如果导入的模块被其他模块间接依赖,即使在当前模块中没有直接使用,也可能会被打包进去。例如,一个第三方库可能依赖于某个特定的模块,而你的代码只导入了这个第三方库,Webpack 可能会将这个被依赖的模块也打包进来。

972. http2 中的首部压缩是什么【网络】

作者备注

作者看到有问题是:「请说说 http2 瘦不压缩原理」, 然后才有了这个问题。 但是作者觉得, 没有事实意义,当做科普即可。

在 HTTP/2 中,首部压缩是一项重要的特性,它主要是为了减少在网络传输中重复的首部信息所占用的带宽,从而提高网络传输效率。

一、为什么需要首部压缩

在 HTTP/1.1 中,每次请求和响应都包含大量的首部信息,这些首部信息可能会重复出现,并且占用不少的网络带宽。例如,每次请求都可能包含的 User-Agent、Accept 等首部字段,在多个请求之间可能是相同的。随着现代网页应用的复杂性增加,请求的数量也越来越多,首部信息的重复传输问题就变得更加突出。

二、HTTP/2 首部压缩的原理

HTTP/2 使用了 HPACK(Header Compression for HTTP/2)算法进行首部压缩。HPACK 主要基于以下两个关键概念:

  1. 静态表和动态表:

    • 静态表是一个预定义的首部名称和值的映射表,其中包含了一些常见的首部字段,如":method: GET"":status: 200"等。当在请求或响应中出现这些常见的首部字段时,可以通过索引值来引用静态表中的条目,而不是传输完整的首部名称和值,从而减少传输的数据量。
    • 动态表是在通信过程中动态构建的。当出现新的首部字段组合时,可以将其添加到动态表中。后续的请求或响应如果包含相同的首部字段组合,可以通过索引值来引用动态表中的条目。
  2. 整数编码和霍夫曼编码:

    • 整数编码用于对首部字段的索引值和长度进行编码,减少表示这些值所需的位数。
    • 霍夫曼编码是一种可变长度编码技术,它根据字符的出现频率为不同的字符分配不同长度的编码。在 HTTP/2 中,霍夫曼编码用于对首部字段的值进行编码,进一步减少数据量。

三、首部压缩的效果

通过首部压缩,HTTP/2 可以显著减少网络传输中的首部信息大小。在实际应用中,首部压缩可以将首部信息的大小减少到原来的几分之一甚至更小,从而提高网络传输效率,降低延迟。特别是对于频繁重复的首部字段,压缩效果更加明显。

例如,在一个包含多个请求和响应的网页应用中,如果每个请求和响应都包含相同的 User-Agent 首部字段,在 HTTP/1.1 中,这个首部字段会在每次请求和响应中重复传输。而在 HTTP/2 中,只需要在第一次出现时传输完整的首部字段,后续可以通过索引值引用动态表中的条目,大大减少了传输的数据量。

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

956. 前端部署应该要考虑哪些问题【热度: 310】【工程化】【出题公司: 腾讯】

关键词:前端部署

在前端部署到生产环境时,有多个关键问题需要解决:

一、高可用性与故障应对

生产环境中,单点故障是必须考虑的问题。若一台物理机突然崩溃,应用需依然能够正常运行。这时可以了解 Kubernetes(k8s)的 Deployment,它能够有效地应对单点故障,确保应用的高可用性。

二、热更新与用户体验

热更新也是重要环节。当需要更新应用时,要做到让用户无感知。同样,k8s 的 Deployment 提供了热更新的功能,能够在不影响用户使用的情况下完成应用的更新。

三、版本回退机制

如果上线的新版本出现问题,需要有时光回溯的能力,能够快速回退到之前的稳定版本。

四、负载均衡

负载均衡能够确保流量均匀分配到各个服务器上,提高系统的性能和稳定性。使用 Nginx 等工具可以实现负载均衡,满足生产环境的需求。

五、自动扩缩容

当流量突然增大时,系统需要能够自动扩容以应对压力。反之,流量减少时也应能自动缩容以节省资源。

六、数据库部署与运维

数据库部署不建议在 k8s 上进行,可选择本地部署 MySQL 集群或直接上云。同时,还需要具备基本的数据运维能力,如日志收集(ELK 或 EFK)和性能监控等。

总结 要将前端应用成功部署到生产环境,需要解决上述多个问题。自动化 pipeline 也是关键,包括 Jenkins、GitLab、k8s 等工具的组合使用。将这一套组合拳运用好,即使不是非常厉害的高手,达到中级水平,也能在中小型公司中轻松应对各种部署需求,实现高效的生产环境部署和运维。

957. 前端需要加载一个大体积的文件时, 一般有哪些优化思路【热度: 594】【工程化】【出题公司: 腾讯】

关键词:前端加载文件过大

当前端需要加载大体积文件时,可以从以下几个方面进行优化:

一、文件压缩

  1. 服务器端压缩

    • 在服务器上配置文件压缩功能,如使用 Gzip 或 Brotli 压缩算法对文件进行压缩后再传输。这样可以显著减少文件的大小,降低传输时间。
    • 例如,在 Nginx 服务器中,可以通过配置开启 Gzip 压缩:
    nginx 复制代码
    gzip on;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/javascript application/json image/svg+xml;
  2. 客户端解压缩

    • 现代浏览器通常支持对 Gzip 和 Brotli 压缩的文件进行自动解压缩。当浏览器接收到压缩后的文件时,会自动解压缩并使用。
    • 无需额外的客户端代码,浏览器会自动处理压缩文件的解压缩过程,提高文件加载速度。

二、文件分割与懒加载

  1. 文件分割

    • 将大体积文件分割成多个较小的文件。例如,对于一个大型的 JavaScript 库,可以将其拆分成多个模块,根据需要逐步加载。
    • 这样可以避免一次性加载整个大文件,减少初始加载时间。
    • 例如,使用 Webpack 等构建工具可以将代码分割成多个 chunk,根据路由或特定条件进行加载。
  2. 懒加载

    • 对于不是立即需要的文件或资源,可以采用懒加载的方式。当用户实际需要使用该资源时,再进行加载。
    • 例如,对于图片、视频等资源,可以在用户滚动到可视区域时再进行加载,避免在页面初始加载时加载所有资源。
    • 对于 JavaScript 模块,可以使用动态导入(dynamic import)的方式实现懒加载:
    javascript 复制代码
    const loadModule = async () => {
      const module = await import("./largeModule.js");
      // 使用加载的模块
    };

三、缓存策略

  1. 浏览器缓存

    • 设置合理的缓存策略,让浏览器缓存已经加载过的文件。这样,当用户再次访问时,可以直接从缓存中读取文件,而无需再次从服务器下载。
    • 可以通过设置 HTTP 响应头来控制缓存,例如:
    nginx 复制代码
    location / {
      add_header Cache-Control "max-age=3600";
    }
    • 上述配置将设置文件的缓存时间为 1 小时。
  2. 缓存更新机制

    • 当文件内容发生变化时,需要确保浏览器能够获取到最新的版本。可以通过在文件名中添加版本号或哈希值来实现缓存更新。
    • 例如,将文件名改为largeFile_v1.2.jslargeFile_abc123.js,当文件内容变化时,更新版本号或哈希值,浏览器会认为这是一个新的文件并进行下载。

四、优化加载顺序

  1. 关键资源优先加载

    • 确定哪些资源是页面加载的关键资源,优先加载这些资源。对于大体积文件,如果不是关键资源,可以延迟加载。
    • 例如,对于一个图片库应用,先加载页面的基本结构和导航部分,图片可以在用户交互时再进行加载。
  2. 异步加载

    • 使用异步加载的方式加载大体积文件。例如,对于 JavaScript 文件,可以使用<script async>标签或动态创建<script>标签并插入到页面中进行异步加载。
    html 复制代码
    <script async src="largeScript.js"></script>
    • 这样可以避免阻塞页面的渲染,提高用户体验。

五、CDN 加速

  1. 使用内容分发网络(CDN)

    • 将大体积文件托管在 CDN 上,利用 CDN 的分布式节点,可以让用户从离自己最近的节点获取文件,减少网络延迟,提高加载速度。
    • 例如,将图片、视频、静态文件等托管在 CDN 上,通过 CDN 的 URL 进行访问。
  2. CDN 缓存

    • CDN 通常会对文件进行缓存,进一步提高文件的加载速度。当文件内容发生变化时,需要及时更新 CDN 上的缓存。

    • 可以通过设置 CDN 的缓存策略或使用版本号等方式来管理 CDN 缓存。

959. 分片上传文件,如何校验文件完整性【热度: 220】【web应用场景】

分片上传是一种将大文件分割成多个小片段进行上传的方法,在分片上传过程中校验文件完整性非常重要,可以确保上传的文件在服务器端能够正确地组合成完整的文件。以下是一些校验文件完整性的思路:

一、使用哈希算法

  1. 计算文件哈希值

    • 在客户端上传文件之前,先对整个文件计算哈希值。常用的哈希算法有 MD5、SHA-1、SHA-256 等。
    • 例如,使用 JavaScript 的crypto-js库计算文件的 MD5 哈希值:
    javascript 复制代码
    import CryptoJS from "crypto-js";
    
    const calculateFileHash = async (file) => {
      const fileReader = new FileReader();
      return new Promise((resolve, reject) => {
        fileReader.onload = (event) => {
          const hash = CryptoJS.MD5(event.target.result);
          resolve(hash.toString());
        };
        fileReader.onerror = reject;
        fileReader.readAsArrayBuffer(file);
      });
    };
  2. 上传过程中携带哈希值

    • 在进行分片上传时,将文件的哈希值作为一个参数一起上传给服务器。
    • 可以在每个分片的请求中携带哈希值,或者在上传开始时先将哈希值发送给服务器。
  3. 服务器端校验

    • 服务器在接收到所有分片并组合成完整文件后,再次计算文件的哈希值,并与客户端上传的哈希值进行比较。
    • 如果两个哈希值一致,则说明文件完整无误;如果不一致,则说明文件在上传过程中可能出现了问题。

二、校验和(Checksum)

  1. 计算校验和

    • 除了哈希算法,还可以使用校验和来校验文件完整性。校验和是通过对文件的每个字节进行特定的数学运算得到的一个值。
    • 例如,可以使用简单的累加校验和算法,将文件的每个字节的值相加得到一个总和作为校验和。
  2. 上传和校验

    • 在客户端计算文件的校验和,并在分片上传时将校验和发送给服务器。
    • 服务器在组合完文件后,计算文件的校验和并与客户端上传的校验和进行比较,以确定文件的完整性。

三、文件大小比较

  1. 记录文件大小

    • 在客户端上传文件之前,记录文件的大小。可以通过File对象的size属性获取文件的大小。
  2. 服务器端验证

    • 服务器在接收到所有分片并组合成完整文件后,检查文件的大小是否与客户端上传的文件大小一致。
    • 如果大小一致,则说明文件可能是完整的;如果不一致,则说明文件在上传过程中出现了问题。

四、上传状态跟踪

  1. 客户端跟踪上传状态

    • 在客户端,可以使用一个数据结构来跟踪每个分片的上传状态,例如使用一个数组记录每个分片是否成功上传。
    • 当所有分片都成功上传后,可以认为文件上传完整。
  2. 服务器端确认

    • 服务器在接收到每个分片时,可以回复一个确认消息给客户端。客户端根据服务器的确认消息来更新上传状态。

    • 当客户端收到服务器对所有分片的确认后,可以确定文件上传完整。

961. http 响应头中的 ETag 值是如何生成的【热度: 37】【web应用场景】【出题公司: 阿里巴巴】

关键词:ETag 值

作者备注

没有啥价值, 当做科普吧

HTTP 响应头中的 ETag(Entity Tag)是服务器生成的用于标识资源的一个字符串。ETag 的生成方式通常有以下几种:

一、基于资源内容生成

  1. 哈希算法:

    • 服务器可以计算资源内容的哈希值,例如使用 MD5、SHA-1 等哈希算法。将资源的内容作为输入,计算出一个固定长度的哈希值作为 ETag。
    • 这种方式可以确保只要资源内容发生变化,ETag 就会不同。
    • 例如,服务器读取文件内容,计算其 MD5 哈希值,将其作为 ETag 返回给客户端。
  2. 特征提取:

    • 对于某些资源,可能无法直接计算哈希值,或者计算哈希值的成本较高。在这种情况下,可以提取资源的一些特征来生成 ETag。
    • 例如,对于一个数据库记录,可以根据记录的主键、创建时间、更新时间等属性组合生成一个唯一的字符串作为 ETag。

二、基于资源属性生成

  1. 版本号或时间戳:

    • 服务器可以为资源分配一个版本号或使用资源的最后修改时间戳作为 ETag。
    • 当资源被修改时,版本号或时间戳会更新,从而导致 ETag 发生变化。
    • 例如,一个动态生成的网页可以在每次更新时增加一个版本号,并将版本号作为 ETag 返回。
  2. 资源标识符:

    • 如果资源有一个唯一的标识符,如数据库中的主键、文件系统中的路径等,可以将其作为 ETag 的一部分。
    • 这样,即使资源内容没有变化,只要资源的标识符不同,ETag 也会不同。

三、动态生成

  1. 服务器端逻辑:

    • 服务器可以根据特定的业务逻辑生成 ETag。例如,一个电商网站的商品页面可能根据商品的库存状态、价格变化等因素生成 ETag。
    • 这种方式可以让服务器更灵活地控制 ETag 的生成,以满足特定的需求。
  2. 缓存策略考虑:

    • 在生成 ETag 时,服务器可以考虑缓存策略。例如,如果服务器希望客户端在一定时间内不重新验证资源,可以生成一个较长时间内不会变化的 ETag。

无论使用哪种方式生成 ETag,其目的都是为了让客户端能够有效地判断资源是否发生了变化,从而决定是否需要重新获取资源。当客户端再次请求资源时,会将上次接收到的 ETag 通过 If-None-Match 请求头发送给服务器,服务器比较客户端发送的 ETag 和当前资源的 ETag,如果相同,则返回 304 Not Modified 状态码,表示资源未发生变化,客户端可以使用缓存中的资源。

964. http 静态文件缓存 Last-Modified 是根据什么生成的【热度: 85】【网络、web应用场景】【出题公司: 阿里巴巴】

关键词:静态文件缓存

作者备注

冷门, 当做只是了解即可

在 HTTP 服务中,静态文件的Last-Modified(最后修改时间)通常是根据以下几个因素生成的:

一、文件系统的修改时间

  1. 来源

    • 服务器在提供静态文件时,通常会读取文件所在文件系统中的最后修改时间作为Last-Modified的值。
    • 例如,在使用常见的 Web 服务器软件如 Nginx、Apache 等时,它们会在响应中自动包含文件的最后修改时间。
  2. 准确性

    • 这个时间是由操作系统维护的,通常是准确的,反映了文件内容最后一次被修改的时间。
    • 但是,如果文件是通过某些方式(如某些备份工具或文件同步工具)复制或移动的,文件系统的修改时间可能不会被正确地保留。

二、文件生成或更新的时间戳

  1. 自定义生成

    • 在一些特定的应用场景中,开发者可能会根据文件的生成或更新的时间戳来设置Last-Modified
    • 例如,在一个动态生成静态文件的应用中,开发者可以在生成文件时记录当前时间,并将其作为Last-Modified的值添加到 HTTP 响应头中。
  2. 数据库记录

    • 如果文件的生成或更新与数据库中的记录相关,开发者可以从数据库中获取相应的时间戳,并将其用于设置Last-Modified
    • 例如,一个内容管理系统可能会在数据库中记录每个文件的最后更新时间,当用户请求静态文件时,服务器可以从数据库中读取这个时间并设置为Last-Modified

三、构建工具或部署流程中的时间标记

  1. 构建工具生成

    • 在使用构建工具(如 Webpack、Gulp 等)进行项目构建时,构建工具可能会在生成静态文件时自动添加一些时间标记,这些标记可以用于设置Last-Modified
    • 例如,Webpack 可以通过插件在生成的文件中添加构建时间戳,服务器可以读取这个时间戳并将其作为Last-Modified的值。
  2. 部署流程中的时间记录

    • 在部署应用时,部署工具或脚本可以记录每个文件的部署时间,并将其作为Last-Modified的值。
    • 这样可以确保在每次部署后,用户能够获取到最新的文件修改时间信息。

总之,Last-Modified的值可以根据文件系统的修改时间、自定义的时间戳或构建工具和部署流程中的时间标记来生成。其目的是为了让客户端能够通过这个时间信息来判断文件是否有更新,从而决定是否需要重新下载文件,以提高网络效率和用户体验。

965. http header content-type 为 application/octet-stream,则代表什么意思【热度: 136】【网络、web应用场景】

关键词:header content-type

在 HTTP 响应头中,如果Content-Typeapplication/octet-stream,代表以下含义:

一、数据类型含义

  1. 通用二进制流

    • application/octet-stream表示这是一个通用的二进制流数据。它没有特定的格式或结构定义,只是表示数据是以二进制形式传输的。
    • 这意味着接收方不知道具体的数据格式,需要根据其他信息(如文件名扩展名、特定的协议约定等)来确定如何处理这个数据。
  2. 任意二进制数据

    • 可以用于传输各种类型的二进制文件,如图片、音频、视频、压缩文件、可执行文件等。
    • 例如,当下载一个未知类型的文件时,服务器可能会使用这个Content-Type来表示文件的内容是二进制数据,但不指定具体的文件类型。

二、使用场景

  1. 文件下载

    • 在文件下载场景中,服务器通常会将Content-Type设置为application/octet-stream,以便让客户端知道这是一个二进制文件,可以进行下载操作。
    • 客户端浏览器在接收到这种类型的响应时,通常会根据文件的扩展名或其他信息来决定如何处理这个文件,例如提示用户保存文件或使用特定的应用程序打开文件。
  2. 上传和下载未知类型的数据

    • 当通过 HTTP 上传或下载数据时,如果数据的类型未知或不确定,可以使用application/octet-stream来表示数据是二进制形式,而不指定具体的格式。
    • 例如,在一些文件上传接口中,如果允许用户上传任意类型的文件,服务器可能会将接收到的文件数据以application/octet-stream类型返回给客户端,以便客户端可以根据需要进行处理。
  3. 与特定协议或应用程序交互

    • 某些协议或应用程序可能会使用application/octet-stream来表示特定类型的二进制数据。
    • 例如,在一些自定义的网络协议中,或者与特定的服务器端应用程序交互时,可能会使用这个Content-Type来表示特定格式的二进制数据,但这种格式可能不是标准的 MIME 类型。

总之,Content-Typeapplication/octet-stream表示这是一个通用的二进制流数据,没有特定的格式定义,通常用于文件下载、上传未知类型的数据或与特定协议和应用程序交互的场景。

967. http 缓存 header 中的 Date 与 Last-Modified 有什么不同【热度: 276】【网络、web应用场景】【出题公司: Shopee】

关键词:http 缓存 header

在 HTTP 响应头中,DateLast-Modified有以下不同:

一、含义不同

  • Date:表示消息产生的时间。服务器用这个时间来标记响应报文的生成时间,它反映了服务器生成响应的时刻。例如,"Mon, 07 Oct 2024 12:34:56 GMT",这个时间是服务器根据其自身的时钟生成的。
  • Last-Modified:指示资源的最后修改时间。它表示服务器上该资源最后被修改的时间。比如,一个网页文件最后一次被编辑的时间就可以通过这个字段告知客户端。例如,"Mon, 01 Sep 2024 10:20:30 GMT"。

二、用途不同

  • Date
    • 客户端可以根据这个时间来判断响应的新鲜度。例如,如果客户端本地有缓存,它可以通过比较缓存的时间和响应中的Date来确定是否需要使用缓存。
    • 用于计算响应的年龄等缓存相关的参数。
  • Last-Modified
    • 主要用于缓存控制。客户端在后续的请求中可以通过If-Modified-Since请求头将这个时间发送给服务器,询问服务器资源是否在这个时间之后被修改过。如果没有被修改,服务器可以返回一个状态码为 304(Not Modified)的响应,告知客户端可以使用缓存中的资源,从而减少传输的数据量和提高响应速度。
    • 有助于客户端判断资源是否已经过期,以便决定是否需要重新获取资源。

综上所述,Date主要表示响应的生成时间,而Last-Modified表示资源的最后修改时间,它们在 HTTP 通信中起着不同的作用,共同为缓存控制和资源管理提供重要信息。

973. https 中如何保证证书是可信任的【热度: 210】【网络】【出题公司: 阿里巴巴】

关键词:https 证书可信保证

在 HTTPS 中,保证证书是可信任的主要通过以下几个方面实现:

一、证书颁发机构(CA)的信任体系

  1. 根证书的信任

    • 操作系统和浏览器内置了一些受信任的根证书颁发机构(Root CA)的证书。这些根证书是整个信任体系的基础。
    • 当浏览器接收到一个服务器的 SSL/TLS 证书时,它会沿着证书链向上追溯,直到找到一个受信任的根证书。如果证书链中的所有证书都有效,并且最终可以追溯到一个受信任的根证书,那么这个服务器证书就被认为是可信任的。
  2. 中间证书的验证

    • 通常,服务器证书不是由根证书颁发机构直接颁发的,而是由中间证书颁发机构(Intermediate CA)颁发的。中间证书颁发机构的证书又由根证书颁发机构颁发。
    • 浏览器在验证服务器证书时,会同时验证证书链中的中间证书。它会检查中间证书的有效性、签名是否正确以及是否在有效期内等。

二、证书的验证过程

  1. 证书的完整性检查

    • 浏览器会检查服务器证书的数字签名,以确保证书在传输过程中没有被篡改。证书的数字签名是使用证书颁发机构的私钥生成的,浏览器可以使用证书颁发机构的公钥来验证签名的有效性。
    • 如果签名验证失败,说明证书可能被篡改,浏览器会显示警告信息,并且可能拒绝建立安全连接。
  2. 证书的有效期检查

    • 浏览器会检查服务器证书的有效期,确保证书在当前时间是有效的。如果证书已过期或尚未生效,浏览器会显示警告信息,并且可能拒绝建立安全连接。
  3. 域名匹配检查

    • 浏览器会检查服务器证书中的域名与用户访问的域名是否匹配。如果证书中的域名与访问的域名不匹配,浏览器会显示警告信息,并且可能拒绝建立安全连接。
    • 例如,如果用户访问"example.com",但服务器证书是为"another-example.com"颁发的,那么浏览器会认为证书不可信。

三、证书吊销检查

  1. 证书吊销列表(CRL)

    • 证书颁发机构可以吊销已经颁发的证书,例如当证书的私钥被泄露或者证书的所有者发生变化时。为了检查证书是否被吊销,浏览器可以查询证书颁发机构发布的证书吊销列表(CRL)。
    • CRL 是一个包含已吊销证书序列号的列表,浏览器可以下载这个列表,并检查服务器证书的序列号是否在列表中。如果在列表中,说明证书已被吊销,浏览器会显示警告信息,并且可能拒绝建立安全连接。
  2. 在线证书状态协议(OCSP)

    • 除了 CRL,浏览器还可以使用在线证书状态协议(OCSP)来实时查询服务器证书的状态。OCSP 允许浏览器向证书颁发机构的服务器发送一个请求,询问服务器证书是否有效。

    • 证书颁发机构的服务器会返回一个响应,指示证书的状态(有效、吊销或未知)。浏览器可以根据这个响应来决定是否信任服务器证书。

关键词:cookie 失效时间

如果 Cookie 没有设置 max-age,它通常被视为会话 Cookie,其失效时间的计算方式如下:

一、会话 Cookie 的失效时间

  1. 浏览器关闭时:一般情况下,当用户关闭浏览器时,会话 Cookie 会被删除。这意味着只要浏览器处于打开状态,并且用户在与同一个网站进行交互,会话 Cookie 就会一直有效。

    • 例如,你在浏览一个在线购物网站时,登录后服务器设置了一个未设置 max-age 的 Cookie 用于标识你的登录状态。只要你不关闭浏览器,这个 Cookie 就会一直有效,让你在不同页面之间切换时保持登录状态。但是一旦你关闭浏览器,再次打开并访问该网站时,你可能需要重新登录,因为会话 Cookie 已经被删除。
  2. 特殊情况:有些浏览器可能会在一段时间内保留会话 Cookie,以便在用户重新打开浏览器时恢复会话状态。然而,这种行为并不是标准的,不同的浏览器可能有不同的处理方式。

    • 比如,某些浏览器可能会在用户关闭浏览器后几分钟或几小时内保留会话 Cookie。这可能是为了提供更好的用户体验,让用户在短时间内重新打开浏览器时不需要再次登录或重新执行某些操作。但这种保留时间是不确定的,并且可能因浏览器的设置、版本和用户的操作而有所不同。

二、需要注意的问题

  1. 安全性考虑:由于会话 Cookie 在浏览器关闭时会被删除,相对来说比较安全。但是,如果在公共计算机上使用会话 Cookie,仍然存在被他人获取敏感信息的风险。因此,在使用会话 Cookie 时,要注意保护用户的隐私和安全。

  2. 网站功能影响:对于依赖会话 Cookie 来保持用户状态或提供个性化体验的网站,用户关闭浏览器后可能会导致一些功能失效。例如,在线购物车中的商品可能会在浏览器关闭后丢失,或者用户需要重新设置一些个性化的偏好。在设计网站时,需要考虑到会话 Cookie 的特性,以便在用户关闭浏览器后提供适当的提示或恢复机制。

975. css 中属性选择器及类选择器的权重哪个高【热度: 642】【CSS、web应用场景】

关键词:选择器权重

作者备注

这个是一个非常贼的问题, 可能很多都只是知道, 【类选择器、属性选择器和伪类选择器】 都为为一样的, 但是并不知道 【类选择器、属性选择器】之间还有优先级关系

在 CSS 中,类选择器的权重高于属性选择器。

一、权重计算规则

CSS 的权重是一个用于确定当多个选择器应用于同一元素时,哪个样式规则将被应用的概念。权重是通过一个四位数字表示的,分别对应不同类型的选择器:

  1. 内联样式:权重为 1000。例如,通过 HTML 元素的style属性设置的样式。
  2. ID 选择器:权重为 0100。
  3. 类选择器、属性选择器和伪类选择器:权重为 0010。
  4. 元素选择器和伪元素选择器:权重为 0001。

通配符选择器(*)的权重为 0000。

二、类选择器与属性选择器的比较

  1. 类选择器:使用点号(.)后跟类名来选择元素。例如,.my-class选择所有具有class="my-class"的元素。

    • 类选择器在 CSS 中非常常用,因为它们可以方便地对一组具有相同特征的元素应用相同的样式。
    • 由于类选择器的权重为 0010,相对较高,所以在与权重较低的选择器发生冲突时,类选择器的样式通常会被应用。
  2. 属性选择器:根据元素的属性来选择元素。例如,input[type="text"]选择所有type属性为text<input>元素。

    • 属性选择器可以提供更具体的选择方式,但相对来说使用频率可能不如类选择器高。
    • 属性选择器的权重也为 0010,与类选择器相同。然而,在实际应用中,如果同时存在类选择器和属性选择器,并且它们的特异性相同,通常类选择器会优先被应用。

三、示例说明

以下是一个示例代码,展示了类选择器和属性选择器的权重比较:

html 复制代码
<!DOCTYPE html>
<html>
  <head>
    <style>
      /* 属性选择器 */
      input[type="text"] {
        background-color: yellow;
      }

      /* 类选择器 */
      .text-input {
        background-color: blue;
      }
    </style>
  </head>

  <body>
    <input type="text" class="text-input" />
  </body>
</html>

在这个例子中,<input>元素同时匹配属性选择器input[type="text"]和类选择器.text-input。由于类选择器的权重更高,所以最终这个输入框的背景颜色将是蓝色,而不是黄色。

综上所述,在 CSS 中,类选择器的权重高于属性选择器。但在实际应用中,还需要考虑选择器的特异性和其他因素,以确保正确的样式被应用到元素上。

976. commonjs 模块化中 module.exports 与 exports 有什么区别, 该如何选择【热度: 194】【工程化、web应用场景】

关键词:模块化 导出

在 CommonJS 模块化规范中,module.exportsexports有以下区别:

一、module.exports

  1. 本质

    • module.exports是一个对象,它代表当前模块要导出的内容。可以将任意类型的值(如函数、对象、字符串等)赋值给module.exports来决定模块导出的内容。
  2. 作用范围和灵活性

    • 可以完全覆盖模块的导出内容。例如,可以直接将一个全新的对象赋值给module.exports,从而完全替换模块原本可能通过exports添加的属性。
    • 适合需要导出复杂数据结构或多个不同类型的值的情况。例如,可以导出一个包含多个函数和变量的对象。

二、exports

  1. 本质

    • exports最初是一个对module.exports的引用。这意味着通过exports添加的属性实际上是添加到了module.exports所代表的对象上。
  2. 局限性

    • 如果直接将一个值赋值给exports,它将不再是对module.exports的引用,而是变成一个独立的变量。此时,模块的导出内容将变为这个新的值,而不是原本期望的通过添加属性到exports来构建的导出对象。
    • 例如:
    javascript 复制代码
    exports = function () {
      console.log("This is a new function.");
    };
    • 在这种情况下,模块将不再导出之前可能通过exports.xxx = yyy添加的属性,而是只导出这个新的函数。

三、选择建议**

  1. 简单模块导出单个值

    • 如果模块只需要导出一个简单的值,如一个函数或一个字符串,可以使用module.exports直接赋值的方式。例如:
    javascript 复制代码
    module.exports = function add(a, b) {
      return a + b;
    };
  2. 复杂模块构建导出对象

    • 当模块需要导出多个相关的值或功能时,可以先使用exports添加属性,最后确保module.exports指向一个包含所有需要导出内容的对象。例如:
    javascript 复制代码
    exports.foo = function () {
      console.log("foo function.");
    };
    exports.bar = "bar value";
    module.exports = exports; // 确保 module.exports 和 exports 指向同一个对象
  3. 避免混淆和错误

    • 理解module.exportsexports的区别非常重要,以避免在导出模块内容时出现意外的结果。尽量明确使用module.exports或遵循使用exports的正确方式,避免直接赋值给exports而导致错误的导出行为。

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

968. 如何进行代码质量检测【热度: 497】【web应用场景】【出题公司: 小米】

关键词:代码质量检查

作者备注

开发性质的话题, 没有统一答复, 也没有最好答复, 这边给几个思考的方向

进行代码质量检测可以从以下几个方面入手:

一、静态代码分析

  1. 使用静态代码分析工具

    • 例如 SonarQube、Checkstyle、PMD 等。这些工具可以检查代码中的潜在问题,如代码风格不符合规范、未使用的变量、复杂度过高的方法等。
    • SonarQube 可以对多种编程语言进行分析,提供全面的代码质量报告,包括代码重复率、代码复杂度、潜在的漏洞等。
    • Checkstyle 主要用于检查 Java 代码是否符合编码规范,如缩进、命名规范、注释等。
    • PMD 可以检测 Java 代码中的各种问题,如空指针引用、资源未释放等。
  2. 遵循编码规范

    • 制定统一的编码规范,包括命名规范、缩进风格、注释规范等。确保团队成员都遵循这些规范,以提高代码的可读性和可维护性。
    • 例如,在 Java 中,变量名通常采用驼峰命名法,方法名采用动词+名词的形式。

二、单元测试

  1. 编写单元测试用例

    • 针对代码中的每个函数、方法或类编写单元测试用例,确保代码的正确性。单元测试应该覆盖各种输入情况,包括正常情况和边界情况。
    • 例如,对于一个加法函数,可以编写测试用例来测试两个正数相加、一个正数和一个负数相加、两个负数相加等情况。
  2. 使用测试框架

    • 如 JUnit(Java)、pytest(Python)等。这些测试框架提供了方便的断言方法和测试运行环境,使单元测试的编写和执行更加容易。
    • JUnit 提供了注解和断言方法,方便编写和组织单元测试。可以使用@Test 注解标记测试方法,使用断言方法如 assertEquals、assertTrue 等来验证测试结果。

三、代码审查

  1. 团队成员之间进行代码审查

    • 定期进行代码审查,让其他团队成员对代码进行审查。这可以发现代码中的潜在问题、提高代码质量,并促进团队成员之间的知识共享。
    • 在代码审查中,可以关注代码的可读性、可维护性、性能、安全性等方面。
  2. 自动化代码审查工具

    • 如 Gerrit、Phabricator 等。这些工具可以帮助管理代码审查流程,记录审查意见和修改历史,确保代码审查的有效性和可追溯性。
    • Gerrit 可以与版本控制系统集成,提供代码审查、合并请求管理等功能。审查者可以在网页上对代码进行审查,提出意见和建议,开发者可以根据审查意见进行修改。

四、持续集成和持续部署(CI/CD)

  1. 建立 CI/CD 流程

    • 使用工具如 Jenkins、GitLab CI/CD 等建立持续集成和持续部署流程。每次代码提交后,自动触发构建、测试和部署流程,确保代码的质量和稳定性。
    • 在 CI/CD 流程中,可以集成静态代码分析、单元测试、代码审查等环节,及时发现和修复代码中的问题。
  2. 监控和反馈

    • 建立监控系统,实时监测应用的性能和可用性。如果出现问题,及时反馈给开发团队,以便进行修复。
    • 可以使用监控工具如 Prometheus、Grafana 等,设置报警规则,当指标超过阈值时及时通知开发团队。

五、性能测试

  1. 进行性能测试

    • 使用性能测试工具如 JMeter、LoadRunner 等对应用进行性能测试。模拟多用户并发访问,测试应用的响应时间、吞吐量、资源利用率等指标。
    • 根据性能测试结果,优化代码的性能,如优化数据库查询、减少网络请求、提高算法效率等。
  2. 压力测试

    • 进行压力测试,模拟高负载情况下应用的表现。这可以帮助发现应用在极端情况下的性能问题和潜在的瓶颈。

    • 压力测试可以逐渐增加负载,观察应用的性能变化,直到达到系统的极限。

相关推荐
码农超哥同学18 分钟前
Python知识点:在Python编程中,如何使用Gensim进行主题建模
开发语言·python·面试·编程
风清扬_jd43 分钟前
Chromium 硬件加速开关c++
java·前端·c++
weixin_545032311 小时前
JavaScript代码如何测试?
开发语言·javascript·ecmascript
谢尔登2 小时前
【React】事件机制
前端·javascript·react.js
2401_857622662 小时前
SpringBoot精华:打造高效美容院管理系统
java·前端·spring boot
etsuyou2 小时前
Koa学习
服务器·前端·学习
Easonmax3 小时前
【CSS3】css开篇基础(1)
前端·css
粥里有勺糖3 小时前
视野修炼-技术周刊第104期 | 下一代 JavaScript 工具链
前端·javascript·github
大鱼前端3 小时前
未来前端发展方向:深度探索与技术前瞻
前端
昨天;明天。今天。3 小时前
案例-博客页面简单实现
前端·javascript·css