居然之家二,详细面试题解析

  1. 深浅拷贝有哪些方法
  2. 深浅拷贝有哪些方法
  3. JSON.parse(JSON.stringify(object)) 有什么缺点
  4. 前端浏览器的存储方式有哪些
  5. 防抖节流,应用场景,手写一个防抖节流
  6. Promise是干什么的?Promise.all()接受三个promise,如果第二个失败了还会执行第三个吗?
  7. async/await 怎么捕获异常
  8. React,哪一个版本有hooks,怎么进行数据通信
  9. React生命周期
  10. webpack,它的插件loader,plugin,拆包
  11. 事件循环
  12. 代码执行顺序, 那些是宏任务和微任务,区别?
  13. new()方法会执行什么?
  14. 单点登录?怎么判断是否登录?
  15. 微前端,低代码有了解吗?
  16. 平时怎么学习前端的
  17. 最近在看那些技术?
  18. attribute 和 property 的区别
  19. webpack构建流程

深浅拷贝有哪些方法

  • 浅拷贝:Object.assign()、...扩展运算符、数组的slice()和concat()
  • 深拷贝:JSON.parse(JSON.stringify())、手动编写递归函数复制对象、使用第三方库如Lodash的_.cloneDeep()方法。

JSON.parse(JSON.stringify(object)) 有什么缺点

使用 JSON.parse(JSON.stringify()) 深拷贝时需要注意不能拷贝循环引用属性和函数属性。

  • 该方式无法拷贝对象的函数属性和基于原型继承的属性;
  • 该方式无法处理循环引用的情况,即当一个对象内部出现循环引用时,该方式会报错或拷贝出一个不完整的对象;
  • 该方式也无法处理特殊的对象类型,如 Date、RegExp 等。

手写一个深浅拷贝

浅拷贝:只是将数据中所有的数据引用下来,依旧指向同一个存放地址,拷贝之后的数据修改之后,也会影响到原数据的中的对象数据

function shallowCopy(obj){
    var data = {};
    for (var i in obj){
        if(obj.hasOwnProperty(i)){  // for in  循环,也会循环原型链上的属性,所以这里需要判断一下
        //hasOwnProperty的相关知识点,查看下面的:相关知识点补充
            data[i] = obj[i]
        }
    }
    return data
}

深拷贝:将数据中所有的数据拷贝下来,对拷贝之后的数据进行修改不会影响到原数据

function deepCopy(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj; // 非对象类型直接返回
  }
  let copy = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      copy[key] = deepCopy(obj[key]); // 递归拷贝对象的每个属性值
    }
  }
  return copy;
}

前端浏览器的存储方式有哪些

  1. Cookies:一种小型文本文件,用于从网站发送到用户设备上。浏览器会自动在后续请求中包含这些数据。Cookies一般被用来记录用户的登录状态、购物车信息等。
  2. localStorage:可以将数据永久性保存在客户端,即便关闭浏览器或重新启动电脑,数据也不会被清除。localStorage 数据存储容量较大,一般为 5MB 或以上,可以保存大量数据
  3. sessionStorage:sessionStorage 只能保存在当前会话中,当用户关闭当前窗口或标签页时,数据将会被清除。同时,不同的窗口和标签页之间也无法共享 sessionStorage。
  4. IndexedDB:IndexedDB 是一款本地数据库,类似于前端版的 SQL 数据库。它支持更复杂的数据类型和更强的查询功能,适合存储大数据量的结构化数据。

防抖节流,应用场景,手写一个防抖节流

防抖:n 秒后再执行回调,若在 n 秒内被重复触发,则重新计时;防抖的基本思想是在函数被连续调用时,只执行最后一次调用,并在指定的时间间隔内没有新的调用才执行函数。如果在时间间隔内有新的调用,则重新计时。

  • 输入框搜索:当用户在输入框中连续输入字符时,使用防抖可以避免每次输入都触发搜索请求,而是在用户停止输入一段时间后才触发搜索请求,减少不必要的请求。
  • 窗口调整:当窗口大小调整时,使用防抖可以确保调整完成后才执行相应的操作,避免频繁触发操作。
  • 按钮点击:当用户频繁点击按钮时,使用防抖可以确保只有最后一次点击有效,避免误操作或重复操作。
function debounce(func, delay) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, args);
    }, delay);
  };
}

节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效;节流的基本思想是限制函数在一定时间间隔内的执行次数,例如每隔一段时间执行一次,并在该时间间隔内忽略其他的函数调用。

  • 页面滚动:当用户滚动页面时,使用节流可以控制触发事件的频率,减少滚动事件的处理次数,提高页面的流畅度。
  • 鼠标移动:当用户在页面上移动鼠标时,使用节流可以限制触发事件的频率,避免触发过多的事件处理逻辑。
function throttle(func, delay) {
  let timer;
  return function (...args) {
    if (!timer) {
      timer = setTimeout(() => {
        func.apply(this, args);
        timer = null;
      }, delay);
    }
  };
}

Promise是干什么的?Promise.all()接受三个promise,如果第二个失败了还会执行第三个吗?

Promise是异步编程的一种解决方案,可以解决传统的回调地狱问题,使得异步代码更加扁平化、可读性更高,避免了多层嵌套的回调函数。

如果第二个Promise执行失败,Promise.all()返回的Promise会立即失败,并把第二个Promise的拒绝原因作为参数传递给失败的回调函数,同时第三个Promise不会被执行。

async/await 怎么捕获异常

在 async 函数内部,可以使用 try 关键字来包裹可能抛出异常的代码块。在 await 表达式之后,如果异步操作抛出异常,它将被捕获并传递给 catch 块,然后执行相应的错误处理逻辑。在 catch 块中,可以访问到抛出的异常对象,并进行相应的处理,例如打印错误信息或执行其他错误处理操作。

注意,使用 try/catch 只能捕获到 await 表达式所在的异步函数内部抛出的异常。如果在异步函数之外发生异常,或者在异步函数内部的同步代码中发生异常,try/catch 是无法捕获到的。在这种情况下,可以使用 .catch() 方法来捕获异常,或者在调用异步函数的地方使用 try/catch 来处理异常。

React,哪一个版本有hooks,怎么进行数据通信

React Hooks 是从 React 16.8 版本引入的。在此版本之前,React 的组件主要是基于类的,使用类组件来管理状态和生命周期方法

使用 Hooks 进行数据通信有多种方式,以下是一些常见的方法:

  • Props:父组件通过 Props 将数据传递给子组件。子组件可以通过 props 对象获取传递过来的数据,并在组件内部使用。

  • Context:Context 提供了一种在组件之间共享数据的方法,避免了通过 Props 层层传递数据。通过创建一个 Context 对象,在父组件中将需要共享的数据包裹在 Provider 组件中,子组件可以通过 useContext Hook 或 Consumer 组件来获取共享数据。

  • useState Hook:useState Hook 可以在函数组件中声明和管理状态。通过调用 useState 返回的状态和更新函数,组件可以在函数组件中维护自己的状态数据。

  • useReducer Hook:useReducer Hook 是另一种用于状态管理的 Hook。它接受一个 reducer 函数和初始状态作为参数,并返回当前状态和 dispatch 函数。通过 dispatch 函数可以触发 reducer 来更新状态。

  • Redux 或其他状态管理库:如果需要更复杂的状态管理和数据通信方案,可以使用像 Redux 这样的状态管理库。Redux 提供了统一的状态管理和数据流控制机制,使得组件之间的数据通信更加可预测和可维护。

React生命周期

组件从 被创建 到 被销毁 的过程称为组件的生命周期。

组件的生命周期可分成三个状态:

  • Mounting(挂载时)
  • Updating(更新时)
  • Unmounting(卸载时)

组件的生命周期可分为三个阶段:

  • Render: 用于计算当前的状态/更新信息,会根据产生的任务的优先级,安排任务的调度(schedule)
  • Pre-commit: commit 之前,可以获取当前 DOM 的快照(snap)
  • Commit: 把所有更新都 commit 到 DOM 树上

webpack,它的插件loader,plugin,拆包

Webpack是一个现代化的静态模块打包工具,它主要用于构建和打包前端项目

  • Loader是Webpack的核心概念之一,它用于处理非JavaScript文件。Webpack通过Loader可以将不同类型的文件(例如CSS、图片、字体等)转换为模块,并将其添加到依赖图中。常见的Loader有:
1. babel-loader:将ES6+的JavaScript代码转换为可以在旧版本浏览器中运行的JavaScript代码。
2. css-loader:处理CSS文件,使其能够被Webpack打包。
3. file-loader:处理文件,例如图片和字体文件,将其复制到输出目录,并返回文件路径。
4. style-loader:将CSS代码注入到页面的<style>标签中。

Loader可以通过在Webpack配置文件中的module.rules中进行配置。每个规则对象都包含了一个test属性,用于匹配需要处理的文件类型,以及一个use属性,用于指定使用的Loader。

  • Plugin是Webpack的另一个重要概念,它可以用于执行更广泛的任务,例如打包优化、资源管理、环境变量注入等。Plugin通过在Webpack构建过程的不同阶段注入钩子函数来实现其功能。常见的Plugin有:
1. HtmlWebpackPlugin:生成HTML文件,并将Webpack打包后的文件自动引入到HTML中。
2. MiniCssExtractPlugin:将CSS提取为单独的文件,而不是注入到页面的<style>标签中。
3. OptimizeCSSAssetsPlugin:优化CSS输出,例如压缩和去重。
4. CleanWebpackPlugin:在每次构建之前清理输出目录。
  • 拆包是一种优化技术,用于将大型的代码包拆分为更小的块。这样可以实现按需加载,减少初始加载的文件大小,提高网页的加载速度。Webpack提供了多种拆包的方式,例如:
1. 入口点拆包:将应用程序的不同部分拆分成多个入口点,每个入口点对应一个输出文件。
2. 动态导入:使用ES6的import()语法实现按需加载。
3. SplitChunks Plugin:通过配置optimization.splitChunks选项,
将公共模块拆分到单独的文件中。

事件循环

事件循环(Event Loop)是 JavaScript 运行时环境(如浏览器或 Node.js)用来处理异步操作的机制。它负责管理 JavaScript 代码的执行顺序,使得异步操作能够以非阻塞的方式进行。

事件循环的主要思想是将任务分为不同的队列,然后按照特定的规则来执行这些队列中的任务。在浏览器环境中,事件循环由浏览器的主线程控制,而在 Node.js 环境中,则由 Node.js 的事件驱动模型管理。

下面是事件循环的基本步骤:

  1. 执行同步任务:从调用栈(执行上下文栈)中取出位于栈顶的同步任务执行。

  2. 执行微任务(Microtask)队列:在执行同步任务过程中,如果遇到微任务(如 Promise 的回调函数、queueMicrotask 方法等),则将其添加到微任务队列中。

  3. 执行宏任务(Macrotask)队列:当同步任务和微任务队列都为空时,事件循环会从宏任务队列中取出一个任务执行。常见的宏任务包括 setTimeout、setInterval、requestAnimationFrame、I/O 操作等。

  4. 更新渲染:在浏览器环境中,如果当前任务完成后需要更新页面的渲染,会执行渲染操作。

  5. 重复上述步骤:事件循环会不断重复执行上述步骤,直到所有任务都被处理完毕。

代码执行顺序, 那些是宏任务和微任务,区别?

  • 执行完当前宏任务中的同步代码。
  • 执行当前宏任务产生的微任务队列中的所有微任务。微任务队列为空才会进入下一步。
  • 执行下一个宏任务。 微任务的执行优先级高于宏任务。也就是说,在一个宏任务执行完毕后,会先执行微任务队列中的所有微任务,然后再执行下一个宏任务。
  • 宏任务(Macrotask):setTimeout、setInterval、setImmediate(仅在 Node.js 中)、I/O 操作、渲染事件(在浏览器中)、UI 交互事件(在浏览器中)等
  • 微任务(Microtask):Promise 的回调、async/await、queueMicrotask 方法等。

new()方法会执行什么?

  • 创建一个空对象
  • 将空对象的原型指向构造函数的原型
  • 将构造函数的 this 指向新创建的对象
  • 返回新创建的对象:如果构造函数没有显式返回一个对象,则默认返回新创建的对象。如果构造函数返回的是一个非对象值(如基本类型),则返回新创建的对象实例。

单点登录?怎么判断是否登录?

单点登录(Single Sign-On,简称 SSO)是一种身份验证和授权机制,允许用户使用一组凭据(如用户名和密码)来访问多个相关系统或应用,而不需要在每个系统中重新进行身份验证。

在单点登录流程中,用户只需要登录一次,然后就可以访问与该身份验证机制集成的多个应用或系统,而无需在每个应用中单独进行登录。这提供了更方便的用户体验,并减少了用户需要记住多个账号和密码的负担。

要判断用户是否登录,可以使用以下方法:

  • 会话管理:在用户登录成功后,服务器可以创建一个会话,并为该会话分配一个唯一的会话标识(如 Session ID)。服务器将会话标识存储在用户的浏览器 Cookie 或其他存储机制中,并在用户发送请求时进行验证。如果会话有效,则可以判断用户已登录。
  • 令牌验证:在某些情况下,单点登录系统会生成一个令牌(Token),并将其发送给用户。用户在每个请求中都需要携带该令牌。服务器接收到请求后会验证令牌的有效性,如果有效,则判断用户已登录。
  • 单点登录协议:单点登录通常使用一些标准化的协议,如 OAuth、OpenID Connect 等。这些协议定义了身份验证和授权的流程,并提供了一种机制来验证用户的登录状态。

微前端,低代码有了解吗?

微前端(Micro Frontends)是一种架构风格,旨在将前端应用程序拆分为更小、更可管理的部分,每个部分都是独立的子应用。这些子应用可以独立开发、部署和扩展,并可以通过统一的容器应用程序来组合在一起。微前端的目标是提高前端开发的灵活性、可维护性和可扩展性,同时支持团队间的独立开发和快速交付。

微前端的主要概念包括:

  1. 拆分:将前端应用拆分为更小的功能单元,每个单元被开发和维护为独立的子应用。
  2. 集成:通过容器应用程序将多个子应用集成在一起,容器应用程序提供导航、路由和通信等功能。
  3. 独立开发和部署:每个子应用都可以独立开发、测试和部署,不受其他子应用的影响。
  4. 通信和状态管理:子应用之间可以通过事件总线、共享状态或其他通信机制进行交互和共享数据。

低代码(Low-Code)是一种应用开发方法,旨在通过使用可视化界面、拖放组件和少量的手写代码来加速应用程序的开发过程。低代码平台提供了一系列可配置的组件和预定义的业务逻辑,开发人员可以通过配置和定制来创建应用程序,而不是从头开始编写所有代码。

低代码的主要特点包括:

  1. 可视化开发:通过可视化界面进行开发,无需编写大量的代码。
  2. 组件驱动:低代码平台提供了一系列可复用的组件,开发人员可以通过拖放组件来快速搭建界面和业务逻辑。
  3. 快速迭代:低代码平台提供了快速迭代和快速发布的能力,使得应用程序的开发和更新变得更加敏捷和高效。
  4. 可扩展性:低代码平台通常提供了扩展机制,开发人员可以自定义组件或添加自定义代码来满足特定需求。

平时怎么学习前端的

  • 自主学习:强调你的主动性和自学能力,说明你经常主动寻找学习资源,如在线教程、文档、博客文章、视频教程等,并且能够理解和应用所学知识。
  • 实践项目:强调你通过实践项目来巩固所学的知识。你可以提到你参与过的个人项目、练习项目、开源项目等,说明你能够将所学的理论知识应用到实际项目中,并通过项目中遇到的问题来学习和成长。
  • 社区参与:强调你参与技术社区的活动,如参与讨论、提问、回答问题、分享经验等。你可以提到你在技术论坛、开发者社区、GitHub等平台上积极参与,与其他开发者交流和学习,从他们的经验中获得启发和指导。
  • 持续学习:强调你的学习态度和持续学习的能力。你可以提到你关注前端领域的最新动态和发展趋势,如阅读相关技术博客、订阅新闻通讯、关注前端社交媒体账号等,以保持对新技术和工具的了解

webpack 构建流程

webpack 的运行流程是一个串行的过程,它的工作流程就是将各个插件串联起来

从启动到结束会依次执行以下三大步骤:

  • 初始化流程:从配置文件和 Shell 语句中读取与合并参数,并初始化需要使用的插件和配置插件等执行环境所需要的参数
  • 编译构建流程:从 Entry 发出,针对每个 Module 串行调用对应的 Loader 去翻译文件内容,再找到该 Module 依赖的 Module,递归地进行编译处理
  • 输出流程:对编译后的 Module 组合成 Chunk,把 Chunk 转换成文件,输出到文件系统
#23届找工作求助阵地##前端##前端面试##2023毕业生求职有问必答#
真面经解析 文章被收录于专栏

根据真实面试经历盘点面试题目,总结面试经验,分类总结面试题目答案

全部评论
Promise.all()接受三个promise,如果第二个失败了还会执行第三个吗? 第三个Promise会被执行。
1
送花
回复
分享
发布于 2023-06-07 23:29 四川
请问深浅拷贝的方法有哪些?
点赞
送花
回复
分享
发布于 2023-06-02 10:24 辽宁
滴滴
校招火热招聘中
官网直投
事件循环中宏任务和微任务的区别是什么?
点赞
送花
回复
分享
发布于 2023-06-02 10:27 云南

相关推荐

7 34 评论
分享
牛客网
牛客企业服务