前端面经真题解析5-字节/抖音/支付前端/超详细记录

自我介绍

当在前端面试中进行自我介绍时,你可以按照以下结构进行组织:

  • 介绍自己:

开始时,简要介绍自己的姓名和背景。你可以提及自己的学历、专业背景以及工作经验。

  • 技术专长:

提及你在前端领域的技术专长和经验。列举你熟悉的编程语言、前端框架、库和工具等。可以着重强调你在哪些方面特别擅长,例如前端开发、响应式设计、用户界面设计、性能优化等。

  • 项目经验:

介绍你在过去的项目中所承担的角色和贡献。可以选择其中几个有代表性的项目来详细介绍,包括项目的规模、技术栈、解决的问题以及你在项目中的具体工作。

  • 学习与成长:

提及你的学习态度和成长经历。你可以分享你如何持续学习新技术、参与开发社区、阅读技术文章和书籍等。强调你对于前端领域的持续关注和追求,以及你在学习过程中遇到的挑战和如何克服它们。

  • 团队合作与沟通能力:

强调你在团队合作中的角色和能力。你可以提及你在过去的团队合作中的贡献,以及你如何与其他团队成员协作、解决问题和有效沟通的能力。

  • 总结与展望:

总结你的自我介绍,并表达你对前端领域的热情和对未来的展望。你可以提及你对前端技术的热爱和对新技术的追求,以及你希望在未来的工作中继续学习和成长。

自我介绍需要简明扼要地表达你的关键信息,同时展现你的技术实力、学习能力和团队合作能力。在介绍过程中,注意保持清晰的表达、自信的姿态和积极的态度。记得准备并练习自我介绍,以确保你能在面试中自信地展现自己。

1.介绍一下自己最熟悉的项目

当在计算机面试中介绍自己最熟悉的项目时,你可以按照以下结构展开:

1.项目背景和目标:

  • 介绍项目的背景,包括项目的起因、背景信息和目标。

  • 解释项目的关键问题或挑战,以及为什么这个项目对你来说很重要。

2.角色和职责:

  • 解释你在项目中扮演的角色和职责。

  • 提及你在项目中的主要职责和贡献。

3.技术栈和架构:

  • 介绍项目所使用的技术栈和架构。

  • 列举你在项目中使用的主要技术和工具。

4.功能和模块:

  • 列举项目的主要功能和模块。

  • 对每个功能或模块进行简要说明,包括其目的和实现方式。

5.解决方案和挑战:

  • 详细说明你在项目中遇到的挑战。

  • 描述你所采取的解决方案,并解释为什么选择了这些方案。

6.成果和影响:

  • 概述项目的成果和影响。

  • 提及项目对业务或团队的影响,例如提升了用户体验、优化了性能或提高了效率。

7.学习和成长:

  • 分享你在项目中学到的知识和技能。

  • 强调项目对你个人成长的重要性,以及你如何通过项目取得了进步。

8.总结:

  • 简要总结你在这个项目中的经验和收获。

  • 强调你如何将这些经验应用到未来的项目中。

在介绍项目时,要确保清晰明了地表达你的思路,并使用简洁的语言描述关键信息。重点突出你的角色和贡献,以及在项目中遇到的挑战和解决方案。展示你在项目中的技术能力和成果,并突出强调你在项目中的学习和成长。

2.nginx的配置

Nginx是一个开源的高性能Web服务器和反向代理服务器,常用于构建可扩展的、高性能的网站和应用。下面是Nginx的基本配置介绍、作用以及实现代理转发解决跨域问题的方法:

1.Nginx的基本配置介绍:

  • Nginx的配置文件是nginx.conf,其中包含了Nginx的全局配置和针对特定虚拟主机的配置。

  • 配置文件可以包含多个server块,每个server块定义了一个虚拟主机。

  • 每个server块中可以定义多个location块,用于匹配和处理特定的URL路径。

2.Nginx的作用:

  • 作为Web服务器,Nginx可以处理客户端的HTTP请求,并返回相应的静态或动态内容。

  • 作为反向代理服务器,Nginx可以接收客户端的请求,并将其转发给后端的应用服务器,然后将应用服务器的响应返回给客户端。

  • Nginx还可以进行负载均衡、缓存、SSL/TLS加密、URL重写等功能。

3.如何实现Nginx的基本配置:

  • 安装Nginx并启动服务。

  • 编辑nginx.conf文件,根据需求进行全局配置,如监听端口、工作进程数等。

  • 在server块中配置虚拟主机,设置域名、根目录、日志等。

  • 在location块中配置URL路径匹配规则,并指定处理方式,如代理转发、静态文件返回等。

4.如何实现代理转发解决跨域问题:

  • 在Nginx的配置文件中的location块中添加以下配置:
location /api {
  proxy_pass http://backend_server/api;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
}
  • 上述配置将所有以/api开头的请求转发到http://backend_server/api的后端服务器。

  • 这样可以绕过浏览器的同源策略限制,实现跨域访问后端接口。

需要注意的是,在实际部署中,还需要配置Nginx的其他相关项,如安全性设置、SSL证书配置等,以满足具体需求和保障系统的安全性和性能。

3.React是用什么版本写的,hook了解吗

react18

0.react不同版本介绍

以下是React 16、17和18版本之间的一些主要改进和区别:

1.React 16:

  • Fiber 架构:引入了新的协调算法 Fiber,使得 React 能够更好地处理大型和复杂的应用,提高了渲染性能和用户体验。

  • 错误边界:通过引入 ErrorBoundary 组件,能够捕获并处理组件树中的 JavaScript 错误,以防止整个应用崩溃。

  • Portals:提供了 createPortal API,允许开发者将子节点渲染到 DOM 结构中的不同位置,跨越组件层级。

2.React 17:

  • 无新特性:React 17主要是一个稳定版本,没有引入新特性。

  • 向后兼容性改进:更改了底层的事件处理机制,提高了向后兼容性,允许逐步迁移应用程序到新版本的 React,而无需一次性进行全面的更改。

  • React 17还引入了新的 JSX 转换器 @babel/preset-react,用于替代之前的 react-scripts。

3.React 18:

  • Concurrent Mode:引入了 Concurrent Mode,使得 React 能够更好地处理并发渲染,提高了渲染性能和用户体验。并发模式下,应用程序可以更好地响应用户输入,并在渲染过程中保持流畅的用户界面。

  • 基于时间的渲染:引入了新的渲染调度器,它基于时间来调度渲染任务,可以根据浏览器的空闲时间来优化渲染性能。

  • 自动批量更新:React 18 通过自动批量更新机制,减少了对开发者的手动批量更新代码的依赖,提高了开发效率。

需要注意的是,上述只是React 16、17和18版本中的一些主要改进和区别,具体的变化和改进还涉及到更多细节和特性。建议在具体的项目中参考官方文档和迁移指南,以了解更全面的变化和更新。

1.React Hooks介绍:

React Hooks 是在 React 16.8 版本中引入的一项重要特性,它改变了组件编写的方式。它允许你在函数组件中使用状态(state)、副作用和其他 React 特性,而无需编写类组件。

使用react hooks 的好处包括:

1.简化组件:

使用 Hooks 可以将逻辑相关的代码组织在一起,使组件更加简洁和易于理解。

2.复用逻辑:

通过自定义 Hooks,可以将组件之间共享的逻辑提取出来,实现逻辑的复用。

3.状态管理:

使用 useState Hook 可以在函数组件中定义和管理状态。

4.副作用管理:

使用 useEffect Hook 可以处理副作用,如数据获取、订阅和事件处理等。

5.上下文管理:

使用 useContext Hook 可以方便地在组件之间共享数据。

2.常用的 Hooks 包括:

1.useState:

用于定义和管理组件的状态。

2.useEffect:

用于处理副作用,如数据获取、订阅和事件处理等。

3.useContext:

用于在组件之间共享数据。

4.useReducer:

用于复杂的状态管理,类似于 Redux 的 reducer。

5.useCallback:

用于缓存回调函数,以便在依赖不变时避免不必要的重新创建。

6.useMemo:

用于缓存计算结果,以便在依赖不变时避免不必要的重新计算。

React Hooks 的引入使得函数组件具备了更多的能力和灵活性,使组件的编写更加简洁、可维护和可测试。使用 8.Hooks 可以摆脱类组件中繁琐的生命周期方法,提高代码的可读性和可维护性。

需要注意的是,使用 Hooks 需要在 React 版本 16.8 或更高版本中。如果使用较旧的 React 版本,需要升级到 React 16.8 或更高版本才能使用 Hooks。

4.router的原理

1.router的实现步骤

前端中的路由(Router)是指通过 URL 的变化来实现不同页面之间的切换和导航。路由的原理可以简单描述为以下几个步骤:

1.URL 解析:

当用户在浏览器地址栏中输入或点击链接时,浏览器会解析 URL,获取其中的路径和查询参数。

2.路由匹配:

在前端路由中,通常使用一种路由库(如React Router、Vue Router等)来定义路由规则。这些路由库会将特定的 URL 路径与组件或处理函数进行匹配。

3.组件渲染:

当 URL 路径与路由规则匹配成功后,对应的组件会被加载和渲染到页面上。这可以是一个单独的组件,也可以是一个组件树。

4.URL 更新:

在页面加载完成后,路由库会通过 JavaScript 来更新 URL,以保持与当前页面的状态同步。这样,用户刷新页面或直接访问特定 URL 时,可以保持正确的页面状态。

5.导航操作:

用户在页面上进行导航操作(如点击链接、点击返回按钮等),路由库会拦截这些操作并进行相应的处理。例如,路由库可以通过 JavaScript 来切换页面并更新 URL,而不会触发完整的页面刷新。

路由库通常提供了一些特性和API来处理路由的实现细节,例如:

  • 嵌套路由:支持在页面中嵌套不同层级的子路由。

  • 路由参数:允许通过 URL 中的参数来传递数据给组件。

  • 跳转导航:提供编程式的导航方法,允许在组件中执行跳转操作。

  • 导航守卫:提供在导航发生前、发生时或发生后执行额外逻辑的机制,例如身份验证、权限控制等。

总之,前端路由通过解析 URL、匹配路由规则、渲染组件和更新 URL,实现了在单页面应用中切换和导航的功能。它使得用户可以在不刷新整个页面的情况下,以更快速和流畅的方式访问不同的页面内容。

2.路由的底层实现原理

在前端中,路由的底层实现可以基于以下几种方式:

1.History API:

浏览器提供的 History API 允许 JavaScript 与浏览器历史记录进行交互。通过使用 pushState() 和 replaceState() 方法,可以向浏览器历史记录中添加或替换条目,并且不会导致页面的刷新。路由库可以使用 History API 来监听 URL 的变化,并根据需要更新页面组件。

2.Hash(哈希)模式:

在旧版本的浏览器中,History API 可能不被完全支持。为了兼容这些浏览器,路由库可以使用 URL 中的哈希部分(#)来模拟路由。当 URL 的哈希部分发生变化时,可以触发对应的路由匹配和组件渲染。

3.HTML5<a>标签的默认行为:

当用户点击页面上的链接时,浏览器会默认发起一个 HTTP 请求并加载新的页面。然而,通过监听<a>标签的点击事件,并阻止默认行为,可以在前端实现路由的切换和导航,而不需要进行完整的页面刷新。

4.浏览器端的 JavaScript 路由库:许多前端框架和库,如React Router、Vue Router等,提供了自己的路由实现。这些库通过监听浏览器的 URL 变化,使用上述的底层机制(如 History API、哈希模式或默认行为阻止)来实现路由的功能,并提供了更高级的特性和API,以简化开发过程。

需要注意的是,不同的路由库和实现方式可能在底层机制上有所差异,但它们的目标都是在单页面应用中实现路由功能。具体选择使用哪种方式取决于项目需求、浏览器兼容性要求和开发团队的偏好。

5.Redux的原理

1.redux实现原理

Redux 是一个用于管理应用状态的 JavaScript 库,它的实现原理可以概括为以下几个核心概念:

1.Store(存储):

Redux 使用一个单一的存储对象来保存整个应用的状态。Store 是通过调用 Redux 的 createStore() 方法创建的,它包含了应用的状态和一些用于操作状态的方法。

2.Action(动作):

Action 是一个简单的 JavaScript 对象,用于描述发生了什么事件。它必须包含一个 type 字段,表示动作的类型,可以携带一些额外的数据。通过调用 Redux 的 dispatch() 方法,我们可以向 Store 发送一个 Action,触发状态的更新。

3.Reducer(归纳器):

Reducer 是一个纯函数,用于根据当前的状态和接收到的 Action 来计算新的状态。Reducer 接收当前状态和 Action 作为参数,并返回一个新的状态对象。Redux 中的状态更新是通过调用 Reducer 来完成的。

4.Middleware(中间件):

中间件是 Redux 提供的一种扩展机制,用于处理异步操作、日志记录、数据转换等功能。中间件可以拦截 Action,在它到达 Reducer 之前执行一些额外的逻辑。常见的 Redux 中间件有 Redux Thunk、Redux Saga 等。

Redux 的工作流程如下:

1.初始化 Store:

通过调用 createStore() 方法创建一个 Store,并传入 Reducer 函数和可选的初始状态。

2.分发 Action:

通过调用 store.dispatch(action) 方法分发一个 Action。Action 包含了对应的动作类型和需要更新的数据。

3.调用 Reducer:

Store 接收到 Action 后,会调用传入的 Reducer 函数。Reducer 根据当前的状态和接收到的 Action 计算新的状态,并返回新的状态对象。

4.更新状态:

Redux 中的状态是不可变的,每次 Reducer 返回新的状态对象后,Store 会将其更新为最新的状态。

5.触发订阅:

每当状态更新时,Store 会触发已注册的订阅函数。订阅函数可以是 UI 组件,用于获取最新的状态并更新视图。

通过这个过程,Redux 实现了应用状态的集中管理和单向数据流动。Redux 的设计思想是可预测性和可维护性,使得应用的状态变化易于理解和调试。它在大型应用或需要共享状态的组件间提供了一种可靠的状态管理机制。

2.redux的底层原理与依赖

Redux 的底层原理相对简单,它并不依赖于任何特定的库或框架。Redux 的核心是一个独立的状态管理库,它可以在任何 JavaScript 应用中使用。

Redux 的实现依赖于以下几个关键概念:

1.纯函数:

Redux 中的 Reducer 和中间件都必须是纯函数。纯函数是指函数的输出只依赖于输入参数,并且没有副作用。这确保了 Redux 的状态更新是可预测且可控的。

2.单一数据源:

Redux 通过一个单一的存储对象(Store)来管理应用的状态。这个存储对象包含了整个应用的状态树,所有的状态变化都在这个对象中进行。

3.状态不可变性:

Redux 的状态是不可变的,即状态对象不能被直接修改,而是通过创建新的状态对象来实现状态的更新。这样可以确保状态的变化可追溯和可预测,方便进行状态的比较和调试。

4.单向数据流:

Redux 的数据流是单向的,即从组件中的 Action 分发到 Reducer,再到 Store 的状态更新,最后到组件的重新渲染。这种单向数据流简化了状态管理的复杂性,并使状态变化可追溯。

Redux 并不依赖于任何特定的框架或库, 但在实际开发中常与 React 结合使用,以便更好地管理 React 组件的状态。Redux 提供了一些与 React 配合使用的库,如 react-redux,它提供了用于连接 Redux 和 React 组件的工具。

需要注意的是,虽然 Redux 是一个独立的状态管理库,但它可以与其他库或框架结合使用。开发人员可以根据项目需求,选择合适的中间件、工具或插件来增强 Redux 的功能,例如 Redux Thunk、Redux Saga 等。这些扩展可以帮助处理异步操作、副作用管理等特定的需求。

6.setstate是同步还是异步的

在 React 中,setState 方法既可以是同步的,也可以是异步的,具体取决于情况。但通常情况下,都是异步的。

1.异步更新:

React 会对连续的 setState 调用进行合并,并进行批量异步更新。这意味着在一个事件循环周期内,多次调用 setState 会被合并为一次更新操作,只触发一次重新渲染。这样可以提高性能和优化渲染过程。

this.setState({ count: this.state.count + 1 });
this.setState({ count: this.state.count + 1 });
// 上述两次 setState 调用会被合并为一次更新操作

在异步更新模式下,React 会根据当前的状态进行批量更新,然后触发重新渲染。

2.同步更新:

在某些情况下,setState 方法可能会以同步方式立即更新状态。例如,在 React 的生命周期函数、合成事件、原生事件处理函数中调用 setState,React 会立即更新状态并触发重新渲染。

1.在 React 生命周期钩子函数中调用 setState:

在组件的生命周期方法(如 componentDidMount、componentDidUpdate、componentWillUnmount 等)中调用 setState 会立即更新状态,并触发重新渲染。

componentDidMount() {
  this.setState({ count: 1 }); // 同步更新
}

2.在合成事件(Synthetic Event)中调用 setState:

在 React 的事件处理函数中调用 setState 会立即更新状态,并触发重新渲染。

handleClick() {
  this.setState({ count: this.state.count + 1 }); // 同步更新
}

render() {
  return <button onClick={this.handleClick}>Click Me</button>;
}

3.在原生事件处理函数中调用 setState:

在使用 addEventListener 绑定的原生事件处理函数中调用 setState 会立即更新状态,并触发重新渲染。

componentDidMount() {
  document.addEventListener('click', this.handleClick);
}

handleClick() {
  this.setState({ count: this.state.count + 1 }); // 同步更新
}

componentWillUnmount() {
  document.removeEventListener('click', this.handleClick);
}

需要注意的是,无论是异步更新还是同步更新,React 会保证在组件生命周期中的 render 方法执行之前,所有的状态更新都已经完成。这意味着在 render 方法中访问状态时,可以获取到最新的状态值。

如果需要在 setState 更新状态后执行一些操作,可以使用回调函数作为 setState 的第二个参数。回调函数会在状态更新完成并重新渲染后被调用。


this.setState({ count: this.state.count + 1 }, () => {
  // 在状态更新完成后执行一些操作
});

总结起来,setState 方法在 React 中既可以是异步的,也可以是同步的,具体取决于调用的时机和场景。在一般情况下,我们可以将其视为异步更新,以提高性能和优化渲染过程。同时,为了确保在状态更新完成后执行一些操作,可以使用回调函数作为第二个参数传递给 setState。

7.手写垂直水平居中

在 CSS 中实现垂直居中、水平居中和垂直水平居中可以采用不同的方法。以下是常用的几种实现方式:

1.垂直居中:

  • 单行文本垂直居中:可以使用行高(line-height)和高度(height)相等,并将文本的 vertical-align 设置为 middle。

  • 多行文本/块元素,垂直居中:可以使用 flex 布局,将容器的 align-items 属性设置为 center,或者使用表格布局,将单元格的 vertical-align 设置为 middle。

  • 绝对定位元素垂直居中:将父容器的 position 设置为 relative,子元素的 position 设置为 absolute,并将 top 和 bottom 值都设置为 50%,再通过负的 margin-top 和 margin-bottom 将子元素居中。

2.水平居中:

  • 块级元素水平居中:可以使用 margin 属性将左右外边距设置为 auto。

  • 行内元素水平居中:可以使用 text-align 属性将父容器的文本对齐设置为 center。

3.垂直水平居中:

  • 使用 flex 布局:将容器的 display 属性设置为 flex,然后使用 justify-content 和 align-items 属性将内容在垂直和水平方向上都居中。

  • 使用绝对定位和 transform:将父容器的 position 设置为 relative,子元素的 position 设置为 absolute,并将 top、bottom、left、right 都设置为 0,并使用 transform 属性的 translate 方法将子元素居中。

需要注意的是,margin和padding的百分比值,它们是相对于包含块(containing block)的宽度计算的。包含块是指元素的直接父元素或者是根据特定规则生成的。例如,如果一个元素的 margin-left 属性设置为 10%,表示该元素的左外边距为包含块的宽度的十分之一。

而绝对定位absolute中的top、bottom是针对已定位父元素的高度,left和right是针对已定位父元素的宽度计算的。这一点和margin和padding不同。

下面是代码示例:

1.垂直居中:

/* 单行文本垂直居中 */
.container {
  height: 100px;
  line-height: 100px;
}

.text {
  vertical-align: middle;
}

/* 多行文本/块元素垂直居中 */
.container {
  display: flex;
  align-items: center;
}

/* 绝对定位元素垂直居中 */
.container {
  position: relative;
}

.absolute-element {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

2.水平居中:

/* 块级元素水平居中 */
.container {
  margin: 0 auto;
}

/* 行内元素水平居中 */
.container {
  text-align: center;
}

3.垂直水平居中:

/* 使用 flex 布局 */
.container {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* 使用绝对定位和 transform */
.container {
  position: relative;
}

.absolute-element {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
}

这些是常见的实现方式,具体使用哪种方式取决于具体的布局需求和场景。

8.实现物体或图片一直旋转

方法一:使用animation 和 keyframes:

要在 CSS 中实现元素或图片的持续旋转,你可以使用 CSS 的 animation 属性结合 @keyframes 规则来实现。

首先,定义一个 @keyframes 规则,指定旋转动画的关键帧。在这个规则中,你可以设置不同的旋转角度和时间点,从而实现旋转效果。

接下来,将 animation 属性应用于你想要旋转的元素,指定动画名称、持续时间、动画类型等。

以下是一个简单的示例,演示如何在 CSS 中实现元素的持续旋转:

@keyframes rotate {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.rotating-element {
  animation-name: rotate; /* 使用定义的 @keyframes 规则 */
  animation-duration: 4s; /* 动画持续时间为 4 秒 */
  animation-timing-function: linear; /* 线性动画过渡 */
  animation-iteration-count: infinite; /* 无限循环 */
}

在上面的示例中,我们定义了一个@keyframes规则,名为 rotate,它指定了从0% 到 100%的旋转动画效果。然后,我们将 rotate 动画应用于一个名为 rotating-element 的元素。动画的持续时间为 4 秒,使用线性的动画过渡,并无限循环。

你可以根据需要调整 @keyframes 规则中的旋转角度、持续时间和动画效果,以实现不同的旋转效果。

通过使用类似的方法,你也可以将持续旋转应用于图片,只需将动画应用于包含图片的元素即可。

请注意,这只是一种基本的示例,实际应用中可能需要更多的样式和调整来达到所需的效果。

方法二:js实现

当需要实现元素或图片的持续旋转时,除了使用 CSS 动画 @keyframes 和 animation 属性之外,还可以使用 CSS3 的 transform 属性结合 JavaScript 来实现。

首先,在 CSS 中为要旋转的元素创建一个类,例如 .rotate-element,并为其设置初始样式。

然后,在 JavaScript 中获取该元素的引用,并使用 setInterval 函数或其他适当的方式来触发一个函数,该函数将应用 transform 属性来实现旋转效果。

以下是一个示例代码,展示了使用 transform 和 JavaScript 实现元素的持续旋转:

<!DOCTYPE html>
<html>
<head>
  <style>
    .rotate-element {
      width: 100px;
      height: 100px;
      background-color: red;
      /* 设置初始样式 */
    }
  </style>
</head>
<body>
  <div class="rotate-element"></div>

  <script>
    const element = document.querySelector('.rotate-element');
    let rotation = 0;

    function rotateElement() {
      rotation += 1;
      element.style.transform = `rotate(${rotation}deg)`;
    }

    setInterval(rotateElement, 10); // 每 10 毫秒调用一次函数,实现持续旋转
  </script>
</body>
</html>

在上面的示例中,我们定义了一个类名为.rotate-element的元素,并设置其初始样式。然后,在 JavaScript 中获取该元素的引用,并创建一个变量 rotation 来跟踪旋转角度。

接下来,我们定义了一个函数 rotateElement(),在每次调用时增加 rotation 变量的值,并将其应用于元素的 transform 属性,以实现旋转效果

最后,我们使用 setInterval 函数来每 10 毫秒调用一次rotateElement()函数,从而实现持续旋转

这种方法使用了 JavaScript 来控制旋转过程,可以更灵活地控制旋转角度和速度,适用于需要动态控制旋转的场景。

9.Token是怎样配置使用的

在前端开发中,Token(令牌)通常用于身份验证和授权,用于验证用户的身份并授予其访问权限。下面是一般情况下前端中配置和使用 Token 的步骤:

**1.生成 Token:**通常是在后端服务器上生成 Token,并在身份验证成功后返回给前端。后端可以使用各种身份验证机制(如 JWT、OAuth 等)来生成 Token。

2.存储 Token:
前端通常将 Token 存储在客户端的某个地方,以便后续的请求中使用。常见的存储方式有:

  • 在浏览器的 Cookie 中存储 Token(需要注意安全性和跨域问题)。

  • 使用 Web Storage(如 localStorage 或 sessionStorage)存储 Token。

  • 将 Token 存储在内存中(如 JavaScript 变量)。

3.发送 Token:

  • 在每个需要进行身份验证的请求中,前端通常需要在请求的头部或参数中发送 Token。具体的方式取决于后端的身份验证机制和要求。常见的方式有:

  • 在请求头部的 Authorization 字段中发送 Token。例如:Authorization: Bearer

  • 将 Token 添加到请求参数中。例如:http://example.com/api?token=

4.验证 Token:
后端服务器接收到带有 Token 的请求后,会进行相应的身份验证和授权操作。这通常包括对 Token 的解析、验证签名、检查权限等步骤,以确保请求的合法性和有效性。

在前端中,可以使用各种库和工具来简化 Token 的配置和使用过程,例如 Axios、Fetch 等 HTTP 请求库通常提供了拦截器(interceptors)功能,可以在请求中自动添加 Token。此外,一些前端框架和库(如 Vue、React)也提供了相应的插件和中间件,用于处理身份验证和 Token 的配置。

需要注意的是,Token 的安全性至关重要。在设计和使用 Token 时,要确保采取适当的安全措施,如使用 HTTPS 进行传输、设置 Token 的过期时间、避免在不安全的环境中存储敏感信息等。此外,还要注意保护 Token 的机密性,避免被恶意攻击者获取和滥用。

10.什么是CSRF攻击和XSS攻击

1.CSRF攻击介绍

CSRF(Cross-Site Request Forgery)攻击是一种利用用户的身份验证凭证来发送未经授权的请求的安全漏洞。攻击者通过诱导受害者在已经登录了一个网站的情况下,访问包含恶意请求的网页,从而在用户的浏览器中执行未经授权的操作。

下面是 CSRF 攻击的详细介绍:

1.攻击流程:

(1)用户登录网站A并获得身份验证凭证(例如Cookie)。

(2)用户在同一浏览器中访问攻击者控制的网站B。

(3)网站B中包含针对网站A的恶意请求(例如修改用户密码)。

(4)用户的浏览器向网站A发送了恶意请求,携带了用户的身份验证凭证。

(5)网站A验证请求中的身份验证凭证有效,并执行了未经授权的操作。

2.攻击原理:

CSRF 攻击利用了网站对用户的身份验证凭证的信任。当用户在一个网站中进行身份验证后,该网站会将身份验证凭证(通常是 Cookie)发送给浏览器,并在后续的请求中自动附加该凭证。攻击者通过构造恶意请求,并欺骗用户在另一个网站中触发该请求,从而利用了浏览器自动发送身份验证凭证的特性。

3.攻击目标:

CSRF 攻击可以导致各种安全问题,包括但不限于以下几点:
(1)未经授权的操作:攻击者可以通过欺骗用户执行未经授权的操作,如更改密码、发起资金转账等。

(2)数据篡改:攻击者可以通过欺骗用户修改用户信息、发布垃圾内容等。

(3)账号劫持:攻击者可以通过修改用户密码、邮箱等信息劫持用户账号。

4.预防措施:

(1)使用 CSRF Token:网站在用户会话中生成一个随机的 Token,并将其嵌入到表单或请求头中。服务器在收到请求时验证 Token 的有效性,只
接受带有效 Token 的请求,拒绝未经授权的请求。

(2)同源检测:网站可以在请求中检查 Referer 头或 Origin 头,确保请求来源于合法的同源网站。

(3)使用验证码:对于执行敏感操作的请求,要求用户输入验证码,增加身份验证的安全性。

(4)安全的 Cookie 设置:设置 Cookie 的 SameSite 属性为 Strict 或 Lax,限制跨站点访问,减少 CSRF 攻击的风险。

通过采取这些预防措施,可以有效减少和防止 CSRF 攻击的发生,确保用户的安全和数据的完整性。

2.XSS攻击

XSS(Cross-Site Scripting)攻击是一种利用网页应用程序对用户的信任,向用户的浏览器注入恶意脚本的攻击方式。攻击者通过在受害者的浏览器上执行恶意脚本,可以窃取用户的敏感信息、劫持会话、修改页面内容等。

下面是 XSS 攻击的详细介绍:

1.攻击流程:

(1)攻击者找到一个存在漏洞的网站,并在其中注入恶意脚本。

(2)受害者访问了被注入恶意脚本的网站。

(3)受害者的浏览器执行了恶意脚本,攻击者获取了受害者的信息或执行了其他恶意操作。

2.攻击原理:

XSS 攻击利用了网页应用程序对用户输入的信任。攻击者通过在网页中插入恶意脚本,使得该脚本在用户浏览网页时被执行。脚本可以通过修改 DOM 结构、获取用户输入的敏感信息、发起网络请求等方式实现攻击目的。

3.攻击类型:

(1)存储型 XSS:攻击者将恶意脚本存储在服务器上,当其他用户访问包含该脚本的页面时,恶意脚本会从服务器加载并执行。

(2)反射型 XSS:攻击者将恶意脚本作为参数注入到目标网址中,服务器将参数反射到页面上,用户点击带有恶意脚本的链接时,脚本被执行。

(3)DOM 型 XSS:攻击者通过修改页面的 DOM 结构,使恶意脚本被执行。

4.危害:

(1)数据窃取:攻击者可以通过注入的恶意脚本获取用户的敏感信息,如用户名、密码、银行账号等。

(2)会话劫持:攻击者可以通过注入的恶意脚本劫持用户的会话,获取用户的权限和身份。

(3)恶意操作:攻击者可以通过修改页面内容、重定向用户到其他恶意网站等方式进行恶意操作。

5.预防措施:

(1)输入验证和过滤:对用户输入的数据进行验证和过滤,确保只接受合法的输入,可以通过对特殊字符进行转义或过滤来防止恶意脚本的注入。

(2)输出转义:在将用户输入输出到网页上时,对特殊字符进行转义,避免被解析为恶意脚本。

(3)使用 Content Security Policy(CSP):通过设置合适的 CSP 策略,限制页面可以加载的资源和执行的脚本,防止恶意脚本的注入和执行。

(4)HttpOnly 和 Secure Cookie:将敏感信息存储在 HttpOnly 和 Secure 标记的 Cookie 中,限制脚本的访问。

(5)定期更新和修补漏洞:及时更新和修补网页应用程序中的漏洞,以防止攻击者利用已知的漏洞进行 XSS 攻击。
通过采取这些预防措施,可以有效减少和防止 XSS 攻击的发生,保护用户的安全和隐私。

11.justify-content是控制水平方向吗(direction-row)

在CSS中,justify-content属性用于控制项目在其容器内的水平方向上的对齐方式。而flex-direction属性则用于控制项目的排列方向。

当你将flex-direction设置为row时,项目将按照水平方向(从左到右)排列。默认情况下,项目将从容器的起始位置开始排列。

下面是一个示例,展示了如何使用justify-content和flex-direction: row一起控制水平方向上的对齐方式:

.container {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
}

在这个例子中,.container是包含项目的父容器。通过设置display: flex,我们将其转换为弹性容器。然后,使用flex-direction: row将项目按照水平方向排列。

justify-content属性被设置为flex-start,这意味着项目将从容器的起始位置开始排列。其他可能的值包括:

  • flex-end:项目在容器的末尾位置对齐。
  • center:项目在容器的水平中心位置对齐。
  • space-between:项目均匀分布在容器内,首个项目位于容器的起始位置,末尾项目位于容器的末尾位置。
  • space-around:项目均匀分布在容器内,项目之间有相等的空间,容器的起始位置和末尾位置也有空间。

你可以根据需要选择适合的justify-content值,以控制项目在水平方向上的对齐方式。

12.get/post的区别

get与post介绍

get请求:从指定的资源请求数据,用于获取数据,一般用于搜索排序和筛选之类的操作。

post请求:向指定的资源提交要被处理的数据,用于将数据发送给服务器,一般用于修改和写入数据。

get请求和post请求本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。


post请求和get请求的区别

(1)post请求更安全(不会作为url的一部分,不会被缓存、保存在服务器日志、以及浏览器浏览记录中,get请求的是静态资源,则会缓存,如果是数据,则不会缓存)

(2)post请求发送的数据更大(get请求有url长度限制,http协议本身不限制,请求长度限制是由浏览器和web服务器决定和设置)

(3)post请求能发送更多的数据类型(get请求只能发送ASCII字符)

(4)传参方式不同(get请求参数通过url传递,post请求放在request body中传递)

(5)get请求产生一个TCP数据包;post请求产生两个TCP数据包(get请求,浏览器会把http header和data一并发送出去,服务器响应200返回数据;post请求,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 返回数据)

注意:在发送 POST 的时候都没有带 Expect 头,server 也自然不会发 100 continue。


post请求的过程:

(1)浏览器请求tcp连接(第一次握手)

(2)服务器答应进行tcp连接(第二次握手)

(3)浏览器确认,并发送post请求头(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送)

(4)服务器返回100 Continue响应

(5)浏览器发送数据

(6)服务器返回200 OK响应


get请求的过程:

(1)浏览器请求tcp连接(第一次握手)

(2)服务器答应进行tcp连接(第二次握手)

(3)浏览器确认,并发送get请求头和数据(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送)

(4)服务器返回200 OK响应

网络环境好的情况下,发一次包和发两次包的时间差别基本可以忽略。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。


总结

除了 GET 和 POST 之外,HTTP 协议中还有许多其他请求方法,如HEAD、 PUT、DELETE、PATCH 等。这些请求方法都有不同的用途和特点,需要根据具体的情况选择合适的请求方法。
3.HEAD:和Get请求相一致,只不过不会返回响应体,这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。(用于获取报头)

  • OPTIONS: 询问支持的请求方法。请求成功后,http头中包含一个名为“Allow”的头,值是支持的方法,如get,post,put等

  • HEAD: 类似于get,通常用来测试某个资源是否存在。

  • PUT:向指定资源位置上传最新的内容。和post很类似,但是put通常指定来资源存放的位置,而post则没有。

  • DELETE:请求服务器删除Request-URI所标识的资源

  • TRACE:(极少使用)回显服务器收到的请求,主要用于测试或诊断

  • CONNECT:(极少使用)HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

13.TCP/UDP的区别

TCP(传输控制协议) 和 UDP(用户数据报协议) 是两种网络传输协议,它们在网络通信中扮演不同的角色和提供不同的服务。以下是它们的主要区别和应用场景:

  • 连接性和可靠性:TCP 是面向连接的协议,而 UDP 是无连接的协议。TCP 通过三次握手建立连接,并提供可靠的数据传输机制,确保数据的完整性和正确性,即使在数据传输过程中发生错误,TCP 也会自动重传数据,保证数据的完整性。UDP 则没有这些特性,它传输的数据不受连接影响,也不提供可靠的数据传输机制。

  • 流量控制:TCP 提供流量控制机制,可以防止过多的数据注入到网络中,使网络拥塞。而 UDP 没有提供流量控制机制。


  • 应用场景:TCP 适用于对数据完整性要求较高的应用场景,如文件传输、电子邮件等。UDP 适用于实时传输的应用场景,如语音、视频等。

  • 数据包大小:TCP 和 UDP 的数据包大小是没有限制的,但是过大的数据包容易导致网络拥塞,而过小的数据包又可能导致传输效率低下。

  • 网络拓扑:TCP 支持任何类型的网络拓扑,包括总线型、环型、星型、树型和网状型网络。而 UDP 仅支持总线型网络拓扑。


总的来说,TCP 适用于对数据完整性和可靠性要求较高的应用场景,而 UDP 适用于实时传输的应用场景。在选择使用哪种协议时,需要根据具体的应用场景和需求进行综合考虑。

14.webpack loader和plugin的区别

在Webpack中,Loader和Plugin是两个不同的概念,它们分别用于不同的目的和功能。

Loader(加载器):

Loader是Webpack的核心概念之一,用于将非JavaScript模块转换为Webpack可以处理的模块。它允许你在打包过程中对不同类型的文件进行处理和转换。Loader可以处理各种文件类型,例如JavaScript、CSS、图片、字体等。当Webpack遇到特定类型的文件时,它会使用相应的Loader对文件进行处理,然后将其转换为模块,使其可以被打包和使用。

Loader的工作方式是通过配置Webpack的module.rules选项来实现。每个规则指定了一个文件类型和应用于该文件类型的Loader。例如,使用babel-loader可以将ES6+的JavaScript代码转换为ES5以在旧版本的浏览器中运行。

Loader的作用是在Webpack打包过程中,对模块进行转换和处理,以适应特定的需求和场景。

Plugin(插件):

Plugin是Webpack的另一个核心概念,它用于扩展Webpack的功能。Plugin可以在整个构建过程中介入,并执行广泛的任务,例如打包优化、资源管理、环境变量注入、代码生成等。Plugin可以通过干预Webpack的不同阶段来实现各种功能,例如在打包开始前或结束后执行特定的操作。

与Loader不同,Plugin不是直接处理模块的转换,而是基于Webpack的事件钩子机制来执行额外的任务。你可以编写自己的Plugin或使用现有的插件,以满足项目的特定需求。常见的Webpack插件包括HtmlWebpackPlugin用于生成HTML文件,MiniCssExtractPlugin用于提取CSS文件等。

总结起来,Loader用于处理模块的转换和加载,而Plugin用于扩展Webpack的功能和执行额外的任务。它们在Webpack中发挥着不同的作用,相互协作来实现更高级的构建和优化需求。

15.算法1:剑指 Offer 42. 连续子数组的最大和

输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。

要求时间复杂度为O(n)。

示例1:

输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

1.动态规划

var maxSubArray = function(nums) {
    let pre = 0, max = nums[0];
    for (i of nums) {
        pre = i + (pre > 0? pre: 0);
        max = Math.max(pre, max);
    }
    return max;
};

2.前缀和思想

var maxSubArray = function(nums) {
    let min = 0, max = nums[0], sum = 0;
    for ( i of nums) {
        sum += i;
        max = Math.max(max, sum - min);
        if (min > sum) {
            min = sum;
        }
    }
    return max;
};

16.算法2:求两个数的最大公约数

辗转相除法

const nums = [num1, num2];
var findGCD = function(nums) {
    const max = Math.max(...nums);
    const min = Math.min(...nums);
    function gcd(a,b) {
        let r = a % b;
        if (r === 0) {
            return b;
        } else {
            return gcd(b,r)
        }
    }
    const k = gcd (max, min);
    return k;
};

如何学习前端的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值