前端面试题详解整理60|. useCallback和useMemo的区别,session cookie token的区别, Wepack和Vite构建区别,

231 阅读13分钟

Cider一面前端日常实习

1. 自我介绍
2. 项目使用技术
以下不太记得顺序了

3. useCallback和useMemo的区别和应用场景

useCallbackuseMemo都是React Hooks中用于优化性能的钩子函数,它们的作用和应用场景有所不同:

  1. useCallback:

    • useCallback用于缓存函数引用,当依赖不变时,返回的是缓存的函数引用,避免了函数的重复创建。
    • 语法:const memoizedCallback = useCallback(callback, dependencies);
    • 参数:
      • callback:需要缓存的函数。
      • dependencies(可选):依赖数组,当依赖数组中的值发生变化时,会重新创建并返回新的函数;若依赖数组为空,则表示该函数永远不会变化。
    • 应用场景:
      • 将回调函数作为props传递给子组件时,可以使用useCallback缓存函数,避免在每次渲染时创建新的函数引用,提高性能。
      • 优化useEffect钩子函数中的依赖项列表,避免不必要的重复触发副作用函数。
  2. useMemo:

    • useMemo用于缓存计算结果,当依赖不变时,返回的是缓存的值,避免了重复的计算过程。
    • 语法:const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
    • 参数:
      • create:一个函数,用于计算需要缓存的值。
      • dependencies(可选):依赖数组,当依赖数组中的值发生变化时,会重新计算并返回新的值;若依赖数组为空,则表示该值永远不会变化。
    • 应用场景:
      • 优化组件渲染性能,避免在每次渲染时重复计算的昂贵操作,例如复杂的数据处理、数组排序等。
      • 缓存具有稳定输入但计算开销较大的函数结果,避免重复计算。

总的来说,useCallback适用于缓存函数引用,主要用于优化回调函数;而useMemo适用于缓存计算结果,主要用于优化计算开销较大的值。在使用时,需要根据具体情况选择合适的钩子函数来优化性能。

5. Wepack和Vite构建区别,为什么vite快❌

Webpack和Vite都是常见的前端构建工具,它们在构建过程、性能和开发体验上有一些区别,其中Vite相对于Webpack的速度更快的主要原因在于其采用了基于ESM(ES Module)的开发模式。下面是它们之间的一些区别和Vite快速的原因:

  1. 构建过程:

    • Webpack:Webpack是一个基于任务的构建工具,它通过配置文件定义了一系列的任务(如加载器、插件等),然后执行这些任务来打包、转换和优化项目中的资源文件。
    • Vite:Vite是一个基于原生ESM的构建工具,它利用ESM的特性,以及浏览器原生支持ESM的能力,在开发时将源代码直接以ESM的形式传递给浏览器,而不需要像Webpack那样先将代码打包成一个或多个bundle。
  2. 性能表现:

    • Webpack:Webpack在打包大型项目时可能会面临性能瓶颈,尤其是在增量构建、热更新等方面的速度可能较慢。
    • Vite:Vite采用了基于ESM的开发模式,能够利用现代浏览器对ESM的原生支持,因此在启动和开发时的速度较快。Vite还支持基于服务端渲染(SSR)的开发模式,可以进一步提高开发效率。
  3. 开发体验:

    • Webpack:Webpack的配置相对复杂,需要花费一定的时间和精力来学习和配置。开发过程中需要等待Webpack重新打包并且刷新页面才能看到更新效果。
    • Vite:Vite采用了开箱即用的方式,减少了配置的复杂性。同时,由于其快速的开发模式,可以实现热更新和快速刷新,使开发体验更加流畅。
  4. Vite快速的原因:

    • 基于ESM:Vite利用了ESM在浏览器中的原生支持,将源代码直接传递给浏览器,避免了打包过程中的性能损耗和额外的文件转换。
    • 按需编译:Vite采用了按需编译的方式,只编译当前修改的文件,而不是重新编译整个项目,因此能够更快地响应变化。
    • 服务端渲染:Vite支持服务端渲染(SSR)模式,可以在开发过程中进行服务器端的渲染,提高了开发效率和性能。

综上所述,Vite相对于Webpack的主要优势在于其基于ESM的开发模式和按需编译的特性,使得开发过程更加快速和流畅。

6. session cookie token的区别

Session、Cookie和Token是用于在Web应用中进行用户身份认证和管理的常见方式,它们之间的区别如下:

  1. Session(会话):

    • Session是一种服务器端的状态管理机制,用于跟踪用户的会话信息。在用户首次访问服务器时,服务器会为该用户创建一个唯一的会话标识(Session ID),并将该标识存储在服务器端,同时将Session ID发送给客户端(通常是通过Cookie)。
    • 在后续的请求中,客户端会将Session ID带回给服务器,服务器通过Session ID来识别用户的会话信息,从而实现状态的保持和管理。Session通常用于存储用户的登录状态、购物车内容等敏感信息。
  2. Cookie(HTTP Cookie):

    • Cookie是一种客户端的状态管理机制,通过在客户端存储少量的数据来实现状态的保持和传递。服务器通过在HTTP响应头中设置Set-Cookie字段来向客户端发送Cookie,客户端会将Cookie保存在本地,并在后续的HTTP请求中自动携带Cookie信息。
    • Cookie通常用于实现用户的身份认证、记住用户的登录状态、记录用户的偏好设置等功能。但由于Cookie是存储在客户端的,因此可能会存在被篡改或者窃取的风险。
  3. Token(令牌):

    • Token是一种基于令牌的身份验证机制,通过在客户端和服务器之间交换令牌来进行身份验证和授权。常见的Token包括JWT(JSON Web Token)、OAuth Token等。
    • 在Web应用中,用户通常会在登录成功后获取到一个令牌(Token),并将其保存在客户端(通常是LocalStorage或SessionStorage)中。后续的请求中,客户端会携带该令牌作为身份验证凭证发送给服务器,服务器通过验证令牌的有效性来识别用户身份。
    • 与Session不同的是,Token的验证是无状态的,服务器不需要在服务器端保存任何状态信息,因此适用于分布式系统和无状态服务。

综上所述,Session、Cookie和Token都是用于管理用户身份和状态的机制,它们在实现上有所不同,但都能够实现用户身份认证和状态管理的功能。选择使用哪种机制取决于具体的业务需求和安全考虑。

7. Mobx和Redux应用区别❌

MobX和Redux都是流行的状态管理库,用于管理React应用中的状态。它们之间的主要区别如下:

  1. 响应式设计:

    • MobX采用了响应式设计,即数据的变化会自动触发相关的更新,从而使状态管理更加简单和直观。
    • Redux则是基于纯函数的不可变数据,更新状态需要通过派发action,由reducer函数处理,并返回一个新的状态,相对而言比较繁琐。
  2. 代码复杂度:

    • MobX的使用相对于Redux来说更加简单和直观,因为它不需要编写大量的模板代码,而是直接在需要观察的对象上添加装饰器或者使用observable函数来定义可观察的状态。
    • Redux需要编写大量的action和reducer代码,并且需要手动管理状态的更新和订阅,相对而言代码复杂度更高一些。
  3. 性能:

    • 由于MobX采用了响应式设计,可以实现精确的状态更新,并且只会更新被观察到的相关组件,因此在一些场景下性能更好。
    • Redux的更新是基于纯函数的不可变数据,可能会导致一些不必要的更新,需要借助一些优化手段(如使用shouldComponentUpdate或者使用connectmapStateToProps函数)来提升性能。
  4. 社区生态和工具支持:

    • Redux有着庞大的社区和丰富的生态系统,拥有大量的相关工具和插件(如Redux DevTools)来辅助开发。
    • MobX的生态相对较小,但也有一些相关工具和插件,同时由于其简单易用的特点,吸引了越来越多的开发者使用。

综上所述,MobX和Redux都是用于状态管理的优秀工具,选择使用哪一个取决于项目的具体需求、团队的偏好以及开发者的经验水平。

8. 懒加载和按需加载的区别

懒加载(Lazy Loading)和按需加载(On-Demand Loading)是两种优化前端性能和资源加载的方法,它们之间存在一些区别:

  1. 懒加载(Lazy Loading):

    • 指的是延迟加载页面或组件的内容,直到用户需要访问或者请求该内容时才进行加载。
    • 通常用于图片、视频、音频等大型资源的加载,或者在单页面应用中延迟加载其他页面的内容。
    • 可以通过将资源的加载时机延迟到用户实际需要访问时,来减少初始页面加载时间和带宽占用,提高页面加载速度和性能。
  2. 按需加载(On-Demand Loading):

    • 指的是根据用户的操作或者需要,动态地加载或者渲染页面中的部分内容或组件。
    • 通常用于单页面应用中,根据用户的路由切换或者交互操作,动态地加载相应的页面或者组件,以提升页面的响应速度和用户体验。
    • 可以通过按需加载,只加载当前页面或者视图所需的内容,而不是一次性加载整个应用的所有内容,从而减少页面加载时间和资源占用。

总的来说,懒加载和按需加载都是通过延迟加载或者动态加载来提升页面性能和用户体验的方法,但懒加载更侧重于延迟加载资源内容,而按需加载更侧重于动态加载页面组件或者内容。

9. React Native跨端中和原生app的bridge通信❌

React Native 中实现跨端通信,即与原生应用进行桥接(bridge communication),可以通过以下几种方式实现:

  1. React Native 原生模块:

    • 可以编写原生模块(Native Modules),以原生代码的形式在原生平台(如 iOS、Android)中实现一些功能。
    • 通过 React Native 提供的桥接机制,将原生模块导出到 JavaScript 环境中,从而在 JavaScript 代码中调用原生模块提供的方法。
  2. React Native 调用原生代码:

    • 使用 NativeModules API,可以在 JavaScript 中调用原生模块提供的方法或属性。
    • 在 JavaScript 中引入 NativeModules 模块,并通过该模块访问原生模块提供的接口。
  3. React Native 模块通信:

    • 使用 React Native 提供的 DeviceEventEmitterNativeEventEmitter 类,实现 JavaScript 和原生代码之间的事件通信。
    • 通过在 JavaScript 中发出事件,然后在原生代码中监听并处理这些事件,实现跨端通信。
  4. 使用第三方库:

    • React Native 社区中有许多第三方库提供了更加方便的方法来实现 JavaScript 和原生代码之间的通信,如 React Native Bridge 等。

以上方法可以让 React Native 应用与原生应用进行有效的通信,实现更加丰富和复杂的功能。选择合适的方式取决于具体的项目需求和开发团队的技术栈。

10. React Router中history和hash的区别

在 React Router 中,historyhash 是两种不同的路由模式,它们在处理路由的方式上有一些区别:

  1. Hash 模式:

    • 在 URL 中使用哈希部分(#)来管理路由状态。
    • 哈希部分的改变不会导致浏览器向服务器发送请求,因此页面不会重新加载。
    • Hash 模式可以实现无刷新页面的路由切换,对于不支持 HTML5 History API 的浏览器是一个有效的解决方案。
    • 缺点是 URL 中包含了哈希符号,不够美观,且不利于 SEO。
  2. History 模式:

    • 使用 HTML5 History API 来管理路由状态,例如 pushState()replaceState() 方法。
    • 可以更加自然地显示 URL,不需要哈希符号。
    • 改变 URL 时不会添加哈希符号,页面也不会因此重新加载,因此用户体验更好。
    • 需要后端服务器的支持,以处理在浏览器地址栏中输入 URL 时的路由匹配。

总的来说,Hash 模式更加简单且兼容性更好,适用于简单的单页应用,而 History 模式在用户体验和 SEO 优化方面更有优势,适用于需要更加专业化的应用场景。在选择使用哪种模式时,需要考虑项目的实际需求和兼容性要求。

11.用户退出重定向到登录如何规划逻辑❌

用户退出后重定向到登录页面是一个常见的需求,可以通过以下逻辑来规划实现:

  1. 清除用户认证信息: 当用户点击退出按钮时,首先要清除用户的认证信息,例如清除存储在本地的token、清除session、或者在后端清除相应的认证信息等,确保用户的身份认证信息被正确注销。

  2. 重定向到登录页面: 客户端在清除用户认证信息后,应该将用户重定向到登录页面。这可以通过设置浏览器的跳转方式来实现,例如使用JavaScript的window.location进行页面跳转。

下面是一个基本的示例,演示了如何在用户退出时执行上述逻辑:

// 用户点击退出按钮时执行的函数
function logout() {
    // 清除用户认证信息
    clearAuthenticationInfo();

    // 重定向到登录页面
    redirectToLogin();
}

// 清除用户认证信息的函数示例
function clearAuthenticationInfo() {
    // 清除本地存储中的token等信息
    localStorage.removeItem('token');
    // 或者清除cookie中的token
    document.cookie = "token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
    // 或者在后端执行注销操作
    // sendLogoutRequest();
}

// 重定向到登录页面的函数示例
function redirectToLogin() {
    // 重定向到登录页面
    window.location.href = '/login'; // 这里的/login是你的登录页面的URL
}

这样,当用户点击退出按钮时,会先清除用户的认证信息,然后将用户重定向到登录页面,实现了用户退出后重定向到登录的逻辑。

11. 代码题
都是按照简历上的场景出题,纯八股不是很难。面试官情绪价值给的很到位,没有任何不适,就是我太菜了

作者:菜就多练_
链接:www.nowcoder.com/feed/main/d…
来源:牛客网