前端面试题详解整理21|防抖和节流,fiber,redux,react和vue区别 ,http和https的区别 ,输入URL到页面渲染,设计模式,

117 阅读20分钟

58云视 前端 50分钟

学信网可查?
自我介绍,离职原因

react hooks有哪些,usememo和usecallback的区别

React Hooks是React 16.8版本引入的新特性,它提供了一种在函数组件中使用状态和其他React特性的方式。以下是React Hooks中常用的一些钩子函数:

  1. useState:用于在函数组件中添加状态管理能力。

  2. useEffect:用于在函数组件中执行副作用操作,比如订阅数据、操作DOM等。

  3. useContext:用于在函数组件中获取上下文(Context)。

  4. useRef:用于在函数组件中创建可变的引用。

  5. useReducer:用于在函数组件中实现类似Redux的状态管理。

  6. useCallback:用于在函数组件中缓存回调函数。

  7. useMemo:用于在函数组件中缓存计算结果。

  8. useLayoutEffect:与useEffect类似,但在DOM更新之后同步调用副作用操作。

  9. useImperativeHandle:用于在使用ref时,自定义对外暴露的实例值。

  10. useDebugValue:用于在开发工具中显示自定义的hook标签。

关于useMemo和useCallback的区别:

  1. useMemo

    • useMemo会在渲染过程中执行,并返回一个memoized值(缓存的值)。
    • 当依赖的变量发生变化时,useMemo会重新计算memoized值,否则会直接返回上一次计算的结果。
    • 主要用于性能优化,在计算昂贵的值或者渲染中的数据转换时使用。
  2. useCallback

    • useCallback会返回一个memoized版本的回调函数。
    • 当依赖的变量发生变化时,useCallback会返回一个新的回调函数,否则会返回上一次返回的回调函数。
    • 主要用于避免不必要的回调函数重复创建,以提高性能。通常在将回调函数作为props传递给子组件时使用,以避免子组件因props的变化而重新渲染。

综上所述,useMemo和useCallback的主要区别在于其返回值的类型不同(useMemo返回一个值,useCallback返回一个函数),以及在何时重新计算或重新创建返回值。

react18新特性

截至我了解的最后更新时间(2022年1月),React 18还未正式发布,但React团队已经公布了一些React 18的新特性和改进方向。以下是一些可能包含在React 18中的新特性和改进:

  1. Concurrent Rendering模式

    • React 18预计将引入Concurrent Rendering模式的稳定版本。这个模式将使得React能够在多个优先级之间调整渲染任务的执行顺序,从而更好地响应用户操作和网络请求,提升应用的交互性和性能。
  2. 新的Root API

    • React 18可能会引入新的Root API,以支持更灵活的渲染树组织方式,从而使得应用更容易进行分片加载和并发渲染。
  3. Server Components

    • React 18可能会引入Server Components,这是一种新的组件类型,旨在支持在服务器端进行渲染,并且能够在客户端进行交互和动态更新。
  4. 新的React交互模式

    • React 18可能会引入新的React交互模式,使得React能够更好地处理用户交互,例如提供更平滑的过渡动画和更灵活的事件处理机制。
  5. 更好的性能优化工具

    • React 18可能会提供更好的性能优化工具,帮助开发者识别和解决性能瓶颈,从而提升应用的性能和响应速度。

需要注意的是,以上内容仅是根据React团队的公开信息和社区讨论得出的预测,并不代表React 18最终发布版本的确切内容。随着React 18的不断开发和完善,可能会有更多新特性和改进被添加进来。因此,建议关注React官方发布的更新和文档,以获取最新的信息。

redux的流程

Redux是一种用于JavaScript应用程序状态管理的库。它的设计思想是将应用的状态(state)抽象出来,统一由一个称为store的对象管理,通过一种可预测的方式修改状态,从而使得应用的状态变化变得可控和可追踪。下面是Redux的基本流程:

  1. 定义Actions

    • Action是一个描述状态变化的普通JavaScript对象,它必须包含一个type字段用来表示行为的类型,以及其他任意字段表示行为所需的数据。定义各种可能发生的行为,例如增加数据、删除数据等。
  2. 定义Reducers

    • Reducer是一个纯函数,接收旧的state和action作为参数,并返回新的state。它负责处理特定的action,并根据action的类型来修改state。在Redux中,所有的状态修改都是由Reducer完成的。
  3. 创建Store

    • Store是Redux的核心,它是一个保存应用所有状态的对象。在创建Store时,需要将Reducer传入,用来初始化Store的初始状态。
  4. 分发Actions

    • 通过调用store.dispatch(action)方法来分发action,触发状态的变化。当调用dispatch方法时,Redux会将action传递给Reducer,并执行相应的逻辑来修改状态。
  5. 监听状态变化

    • 通过调用store.subscribe(listener)方法来监听状态的变化。当状态发生变化时,Redux会调用listener函数,并将新的状态传递给它。
  6. 视图更新

    • 在React应用中,通常会将store中的状态映射到组件的props上,并通过props来渲染视图。当状态发生变化时,组件会重新渲染,并显示新的状态。

总的来说,Redux的流程可以概括为:定义行为(Actions) -> 编写逻辑(Reducers) -> 创建Store -> 分发Actions -> 监听状态变化 -> 视图更新。通过这种方式,Redux实现了应用状态的统一管理和可控化,使得应用的状态变化变得可预测和易于调试。

react fiber是为了解决什么问题

React Fiber 是 React 16 中引入的一种新的 reconciler 架构,旨在解决 React 应用中的性能问题,主要解决了以下几个问题:

  1. 优先级调度

    • React Fiber 可以实现任务的拆分和优先级调度,使得 React 应用在执行任务时可以根据优先级动态地调整任务的执行顺序,从而更好地响应用户操作和提高用户体验。这种优先级调度机制使得 React 能够更好地处理动画、用户输入等高优先级任务,保证页面的流畅度。
  2. 增量渲染

    • React Fiber 使用了增量渲染的思想,将渲染过程分为多个小任务,并允许中途中断、暂停和重新启动任务的执行,从而实现了异步渲染。这种增量渲染的机制使得 React 能够更好地利用浏览器空闲时间,提高渲染效率,避免了长时间的渲染阻塞。
  3. 异步渲染

    • React Fiber 使得渲染过程可以被中断和暂停,并且能够在下一个浏览器帧中继续执行,从而实现了异步渲染。这种异步渲染的机制使得 React 能够更好地控制任务的执行时间,避免了长时间的渲染阻塞,提高了页面的响应速度和用户体验。
  4. 更好的可中断性和控制性

    • React Fiber 具有更好的可中断性和控制性,可以在渲染过程中根据需要中断、暂停和重新启动任务的执行,从而更灵活地控制任务的执行顺序和优先级。这种可中断性和控制性使得 React 能够更好地响应用户操作和网络请求,提高了页面的交互性和性能。

综上所述,React Fiber 主要解决了 React 应用中的性能问题,通过优先级调度、增量渲染、异步渲染和更好的可中断性和控制性,使得 React 应用能够更好地响应用户操作,提高用户体验,并且提高了页面的渲染效率和性能。

防抖和节流,应用场景
防抖(Debounce)和节流(Throttle)是常用的优化函数,用于控制事件触发频率,防止过多的重复操作导致性能问题。它们的应用场景如下:

防抖(Debounce):

  1. 输入框搜索

    • 当用户输入搜索关键词时,防抖可以确保在用户停止输入一段时间后才触发搜索请求,从而减少不必要的网络请求和服务器压力。
  2. 窗口大小变化

    • 当窗口大小变化时,防抖可以确保在用户停止调整窗口大小一段时间后才执行相应的响应式布局或重新计算元素尺寸,从而减少不必要的重绘和重新渲染。
  3. 按钮点击

    • 当用户频繁点击按钮时,防抖可以确保只有在用户停止点击一段时间后才触发相应的操作,从而避免多次重复操作导致的问题。

节流(Throttle):

  1. 页面滚动

    • 当页面滚动时,节流可以确保在用户滚动过程中只触发一次滚动事件,从而减少滚动事件的频率,提高页面性能和流畅度。
  2. 鼠标移动

    • 当用户频繁移动鼠标时,节流可以确保在用户移动过程中只触发一次鼠标移动事件,从而减少事件的频率,提高页面性能。
  3. 滚动加载

    • 当用户滚动到页面底部时触发加载更多内容的操作时,节流可以确保只有在用户停止滚动一段时间后才触发加载操作,从而减少不必要的加载请求和服务器压力。

总的来说,防抖和节流都是用于控制事件触发频率的优化函数,适用于各种需要控制事件触发频率的场景,可以有效地提高页面性能和用户体验。

事件循环
从输入url到渲染完成都发生了什么
从输入URL到页面渲染完成经历了以下几个主要步骤:

  1. DNS解析

    • 浏览器首先会解析输入的URL中的域名,将其转换为对应的IP地址。如果该域名已经解析过且缓存了IP地址,则直接跳过此步骤。
  2. 建立TCP连接

    • 浏览器通过DNS解析得到的IP地址,向服务器发起TCP连接请求。经过三次握手建立连接后,浏览器和服务器之间建立了可靠的通信通道。
  3. 发起HTTP请求

    • 浏览器通过已建立的TCP连接,向服务器发送HTTP请求。请求中包含了用户请求的资源信息,例如页面HTML文件、CSS、JavaScript等。
  4. 服务器处理请求

    • 服务器收到浏览器发送的HTTP请求后,根据请求的资源路径和参数,进行相应的处理。如果请求的是静态文件,服务器直接返回文件内容;如果请求的是动态资源,服务器会调用相应的后端程序进行处理,并生成HTML页面返回给浏览器。
  5. 接收响应数据

    • 浏览器收到服务器返回的响应数据,包括HTTP响应头和响应体。响应头中包含了响应的状态码、内容类型等信息,响应体中包含了请求的资源数据。
  6. 解析HTML文件

    • 浏览器解析HTML文件,构建DOM(Document Object Model)树。同时,解析过程中会发起对CSS、JavaScript等外部资源的请求,并继续进行后续步骤。
  7. 构建渲染树

    • 浏览器根据DOM树和CSS样式表,构建渲染树(Render Tree),即将DOM树和CSS样式表合并成一棵渲染树。渲染树中包含了所有需要渲染的节点以及其样式信息。
  8. 布局和绘制

    • 浏览器根据渲染树,进行布局(Layout)和绘制(Paint),计算每个节点在屏幕上的位置和样式,并将其绘制到屏幕上。
  9. 显示页面

    • 经过布局和绘制后,页面内容被渲染到浏览器窗口上,并呈现给用户。
  10. JavaScript执行

    • 如果HTML中包含了JavaScript代码,浏览器会执行JavaScript代码,可能会对DOM进行操作,修改页面的内容或样式。
  11. 完成页面加载

    • 当所有资源都加载完成、DOM树构建完成、样式计算完成、JavaScript执行完成后,页面渲染完成,此时浏览器触发DOMContentLoaded事件,表示DOM已经完全加载。
  12. 加载完毕

    • 当所有资源(包括图片、样式表、脚本等)都加载完成后,浏览器触发load事件,表示页面已经完全加载。

以上是从输入URL到页面渲染完成的主要步骤,不同的步骤可能会有一些交叉和重叠,但整个过程是按照这个顺序依次进行的。

今日头条经典笔试题异步读取顺序

手写字符串对象转树(不会,给我换了一道)

要实现字符串对象转换成树,你需要解析字符串并将其转换为树形结构。下面是一个简单的示例代码,演示了如何实现这个过程:

// 示例字符串对象
const strObj = {
  "a.b.c": 1,
  "a.b.d": 2,
  "a.e": 3,
  "f": 4
};

// 将字符串对象转换为树形结构
function objToStrTree(obj) {
  const tree = {};

  for (const key in obj) {
    const parts = key.split('.');
    let currentNode = tree;

    for (let i = 0; i < parts.length; i++) {
      const part = parts[i];

      // 创建节点
      if (!currentNode[part]) {
        if (i === parts.length - 1) {
          // 叶子节点
          currentNode[part] = obj[key];
        } else {
          // 中间节点
          currentNode[part] = {};
        }
      }

      // 移动当前节点
      currentNode = currentNode[part];
    }
  }

  return tree;
}

// 测试
const tree = objToStrTree(strObj);
console.log(JSON.stringify(tree, null, 2));

这段代码将字符串对象转换为树形结构。例如,输入的字符串对象strObj会被转换成如下的树形结构:

{
  "a": {
    "b": {
      "c": 1,
      "d": 2
    },
    "e": 3
  },
  "f": 4
}

在这个树中,每个节点都是一个对象,对象的属性名对应字符串的每一级子项。

手写排序不限制算法,解释,还知道什么排序?快排和冒泡的时间复杂度
下面我将手写一个简单的排序算法,并解释其原理。这个排序算法是选择排序(Selection Sort),它的原理是每次从未排序的部分中选择最小的元素,放到已排序部分的末尾,直到所有元素都被排序完毕。

function selectionSort(arr) {
  const len = arr.length;
  for (let i = 0; i < len - 1; i++) {
    let minIndex = i;
    for (let j = i + 1; j < len; j++) {
      if (arr[j] < arr[minIndex]) {
        minIndex = j;
      }
    }
    if (minIndex !== i) {
      [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
    }
  }
  return arr;
}

// 测试
const arr = [64, 34, 25, 12, 22, 11, 90];
console.log(selectionSort(arr)); // [11, 12, 22, 25, 34, 64, 90]

选择排序的时间复杂度是 O(n^2),其中 n 是数组的长度。虽然选择排序的时间复杂度较高,但它是一种简单直观的排序算法,对于小规模数据集来说还是比较有效的。

其他常见的排序算法还包括:

  1. 冒泡排序(Bubble Sort)
  2. 插入排序(Insertion Sort)
  3. 归并排序(Merge Sort)
  4. 快速排序(Quick Sort)
  5. 堆排序(Heap Sort)
  6. 希尔排序(Shell Sort)
  7. 计数排序(Counting Sort)
  8. 桶排序(Bucket Sort)
  9. 基数排序(Radix Sort) 等等。

快速排序的时间复杂度为 O(n log n),冒泡排序的时间复杂度为 O(n^2)。因此,快速排序通常比冒泡排序更快,特别是在大数据集上。

设计模式知道哪些,单例模式是什么,举例
设计模式是解决特定问题的可复用解决方案,它们提供了一套经过验证的方法来解决软件设计中的常见问题。常见的设计模式包括但不限于:

  1. 创建型模式:

    • 单例模式(Singleton Pattern)
    • 工厂模式(Factory Pattern)
    • 抽象工厂模式(Abstract Factory Pattern)
    • 建造者模式(Builder Pattern)
    • 原型模式(Prototype Pattern)
  2. 结构型模式:

    • 适配器模式(Adapter Pattern)
    • 装饰器模式(Decorator Pattern)
    • 外观模式(Facade Pattern)
    • 代理模式(Proxy Pattern)
    • 桥接模式(Bridge Pattern)
    • 组合模式(Composite Pattern)
    • 享元模式(Flyweight Pattern)
  3. 行为型模式:

    • 观察者模式(Observer Pattern)
    • 策略模式(Strategy Pattern)
    • 命令模式(Command Pattern)
    • 模板方法模式(Template Method Pattern)
    • 迭代器模式(Iterator Pattern)
    • 责任链模式(Chain of Responsibility Pattern)
    • 状态模式(State Pattern)
    • 访问者模式(Visitor Pattern)
    • 中介者模式(Mediator Pattern)
    • 备忘录模式(Memento Pattern)

单例模式(Singleton Pattern)是一种创建型模式,其主要目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式在需要控制某些资源的共享访问权限时很有用,例如数据库连接池、线程池等。单例模式通常有以下几种实现方式:

  1. 饿汉式单例:

    • 在类加载时就创建实例,天生线程安全,但可能会导致资源浪费。
    public class Singleton {
        private static final Singleton instance = new Singleton();
        private Singleton() {}
        public static Singleton getInstance() {
            return instance;
        }
    }
    
  2. 懒汉式单例:

    • 在需要时才创建实例,但不是线程安全的,需要考虑多线程环境下的同步问题。
    public class Singleton {
        private static Singleton instance;
        private Singleton() {}
        public static Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    
  3. 双重检查锁单例:

    • 在懒汉式的基础上增加了双重检查锁,提高了性能,同时保持了懒加载和线程安全。
    public class Singleton {
        private static volatile Singleton instance;
        private Singleton() {}
        public static Singleton getInstance() {
            if (instance == null) {
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

这些是单例模式的一些常见实现方式,具体选择哪种实现方式取决于具体的需求和使用场景。

项目优化有哪些?

http和https的区别

项目优化是指对项目中的各个方面进行改进,以提高性能、可维护性、可扩展性等方面的指标。以下是一些常见的项目优化技巧:

  1. 性能优化

    • 减少页面加载时间:压缩和合并静态资源、使用CDN加速、优化图片大小和格式、延迟加载或异步加载资源等。
    • 减少服务器响应时间:优化数据库查询、使用缓存、减少HTTP请求等。
    • 减少页面渲染时间:使用前端性能优化技术,如减少DOM操作、合理使用CSS和JavaScript、使用虚拟列表等。
  2. 代码优化

    • 提高代码质量:遵循编码规范、代码复用、模块化设计、避免冗余代码、优化算法和数据结构等。
    • 优化性能关键路径:针对性能瓶颈的代码进行优化,提高关键路径上的执行效率。
  3. 资源优化

    • 合理分配服务器资源:根据项目需求和流量情况,合理配置服务器资源,如CPU、内存、带宽等。
    • 使用资源管理工具:使用监控工具、日志分析工具等来监控和管理服务器资源的使用情况,及时发现和解决问题。
  4. 用户体验优化

    • 提高页面交互体验:使用合适的动画效果、交互设计,提供友好的用户界面。
    • 改进用户导航和流程:简化用户操作流程、提供清晰的导航结构、优化用户登录注册流程等。
  5. 安全优化

    • 防止常见安全风险:加强身份认证、权限管理、数据加密等,防止SQL注入、跨站脚本攻击等安全漏洞。
    • 定期安全检查:定期进行安全漏洞扫描、代码审查和漏洞修复,确保项目安全性。
  6. 团队协作优化

    • 优化团队工作流程:采用敏捷开发、持续集成等开发模式,提高团队协作效率。
    • 促进知识共享和技术沉淀:建立知识库、开展技术分享会议、培训团队成员等,促进团队技术水平提升和经验积累。

以上是一些常见的项目优化技巧,实际项目中还可能根据具体情况采取其他优化措施。综合考虑项目需求、技术实现和团队资源等方面,选择合适的优化策略,以提高项目的整体质量和效率。

react和vue区别

React 和 Vue 是两个流行的前端框架,它们都有自己的特点和优势。以下是它们之间的一些主要区别:

  1. 设计理念

    • React:React 是一款由Facebook开发的JavaScript库,专注于构建UI界面。它采用了一种称为虚拟DOM的机制,将组件化和声明式编程作为核心理念,通过组件化开发和单向数据流来构建应用。
    • Vue:Vue 是一款由尤雨溪开发的渐进式JavaScript框架,旨在更简单、更快速地构建交互式界面。Vue的设计理念是"渐进式框架",允许开发者逐步引入Vue的特性,同时提供了双向数据绑定和组件化开发。
  2. 模板语法

    • React:React 使用JSX语法,将HTML结构和JavaScript逻辑混合在一起,提供了一种更直观、更强大的组件化编程方式。
    • Vue:Vue 使用模板语法,允许开发者在HTML中直接编写Vue指令和数据绑定,提供了一种更简洁、更灵活的编码方式。
  3. 数据绑定

    • React:React采用了单向数据流,数据的流动是自顶向下的,子组件通过props接收父组件传递的数据,父组件通过回调函数更新子组件的状态。
    • Vue:Vue支持双向数据绑定,可以通过v-model指令实现表单元素和数据模型之间的双向绑定,数据的变化会自动反映到视图上。
  4. 状态管理

    • React:React使用Context和Redux等状态管理库来管理组件之间共享的状态,提供了一种可预测、可维护的状态管理方案。
    • Vue:Vue提供了Vuex状态管理库,用于管理大型应用的状态,提供了一种集中式的状态管理方案。
  5. 生态系统

    • React:React生态系统庞大,拥有丰富的第三方库和组件,社区活跃度高,有大量的文档和教程可供参考。
    • Vue:Vue生态系统也很健全,社区活跃度高,有大量的插件和组件可供选择,文档完善、易于上手。

总的来说,React和Vue都是优秀的前端框架,各有其特点和优势,选择合适的框架取决于项目需求、团队技术栈和个人偏好。

独立负责的项目?什么时候离职?现在offer有?期望薪资?

作者:牛客297260894号
链接:www.nowcoder.com/feed/main/d…
来源:牛客网