面试中被问到过的前端八股(二)

06-01 1154阅读

1、原生js实现深拷贝

递归实现基础深拷贝(常用写法)
function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj; // 原始值直接返回
  }
  // 处理数组
  if (Array.isArray(obj)) {
    return obj.map(item => deepClone(item));
  }
  // 处理对象
  const result = {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      result[key] = deepClone(obj[key]);
    }
  }
  return result;
}
🚫 注意:这个版本不能处理:
  • 日期 Date
  • 正则 RegExp
  • Map / Set
  • 循环引用

    2、React中的Context

    在 React 中,Context 是一种全局状态管理工具,用于在组件树中传递数据,而不必通过一层层的 props 传递。它常用于主题、当前用户、语言、权限等跨组件共享的状态。

    ✨ 简单理解 Context

    如果你有多个组件需要共享一个数据(比如登录用户信息),又不想层层传 props,那就可以用 Context!

    🔧 基本使用步骤
    1️⃣ 创建 Context
    import React from 'react';
    const UserContext = React.createContext();
    

    你可以传一个默认值进去:

    const UserContext = React.createContext({ name: '匿名用户' });
    
    2️⃣ 提供 Context(Provider)

    用 Provider 包裹你的组件树,把共享的数据传进去。

    { name: '小花', age: 18 }}
      
    
    
    3️⃣ 使用 Context

    有两种方式使用:

    ✅ 方式一:使用 useContext(函数组件推荐)
    import { useContext } from 'react';
    const Profile = () => {
      const user = useContext(UserContext);
      return 你好,{user.name};
    };
    
    ✅ 方式二:使用 Context.Consumer
      {user => 你好,{user.name}}
    
    
    🌟 小技巧
    • 可以配合 useReducer 使用,做一个简易的 Redux 替代品
    • 可以封装成自己的全局状态管理工具(比如一个 useUser() 钩子)

      3、闭包及其使用场景

      闭包就是:一个函数可以“记住”它被创建时的作用域,即使它在这个作用域之外执行。

      📦 举个例子
      function makeCounter() {
        let count = 0;
        return function () {
          count++;
          return count;
        };
      }
      const counter = makeCounter();
      console.log(counter()); // 1
      console.log(counter()); // 2
      console.log(counter()); // 3
      

      这里的 count 是 makeCounter 函数内部的变量,但外面的函数 counter() 每次调用都能访问到它。

      使用场景

      闭包的常见用途如下:

      1️⃣ 数据私有化(模拟“私有变量”)
      function createUser(name) {
        let score = 0;
        return {
          getScore: () => score,
          increase: () => score++
        };
      }
      const user = createUser('Alice');
      user.increase();
      user.increase();
      console.log(user.getScore()); // 2
      

      👉 score 不能被外部直接访问或修改,只能通过接口函数来操作。


      2️⃣ 创建工厂函数(动态生成函数)
      function makeAdder(x) {
        return function (y) {
          return x + y;
        };
      }
      const add5 = makeAdder(5);
      console.log(add5(3)); // 8
      

      👉 闭包“记住”了 x = 5,创建出一个“加5”的函数。


      3️⃣ 防抖/节流(很多 JS UI 场景)
      function debounce(fn, delay) {
        let timer = null;
        return function () {
          clearTimeout(timer);
          timer = setTimeout(() => {
            fn.apply(this, arguments);
          }, delay);
        };
      }
      

      👉 timer 是闭包中的变量,不会被外部访问,也不会污染全局。


      4️⃣ 异步场景/循环里的闭包坑(经典题)
      js复制编辑for (var i = 0; i  
      

      解决办法:

      js复制编辑for (var i = 0; i  
      

      👉 闭包“捕获”了当前的 i,每次循环创建一个新的作用域副本。


      总结一句话:

      闭包=“函数 + 它诞生时的作用域”

      它能帮你:

      面试中被问到过的前端八股(二)
      (图片来源网络,侵删)
      • 模拟私有变量
      • 保留状态
      • 创建高阶函数
      • 写工具函数(节流/防抖)
      • 理解 JS 异步和作用域问题

        4、如何用css实现只显示三行文字,多余部分用…表示

        ✅ 方案一:多行文本省略(支持现代浏览器)
        .ellipsis-multiline {
          display: -webkit-box;         /* 必须 -webkit-box 才能生效 */
          -webkit-box-orient: vertical; /* 垂直排列 */
          -webkit-line-clamp: 3;        /* 限制显示3行 */
          overflow: hidden;
        }
        
        🧪 示例 HTML:
          一段超长超长的文本,超过三行的部分将被隐藏并显示省略号,一段超长超长的文本,超过三行的部分将被隐藏并显示省略号,一段超长超长的文本,超过三行的部分将被隐藏并显示省略号。
        
        ✅ 方案二:只显示一行

        如果你只想显示一行 + ...,这样写就行:

        .ellipsis-singleline {
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
        

        5、讲讲React中虚拟dom的diff算法

        在 React 中,虚拟 DOM(Virtual DOM)是一种优化网页更新性能的技术。它通过构建一个虚拟的 DOM 树,减少了直接操作真实 DOM 的次数,从而提高了渲染效率。React 使用了一种称为 diff 算法(差异算法)来更新虚拟 DOM 和真实 DOM 之间的差异。

        面试中被问到过的前端八股(二)
        (图片来源网络,侵删)
        🧩 虚拟 DOM 和 Diff 算法基本概念
        • 虚拟 DOM:React 在内存中创建一个虚拟的 DOM 树,它是一个 JavaScript 对象,代表真实 DOM 的结构。每次组件更新时,React 会生成一个新的虚拟 DOM 树,并与上一次的虚拟 DOM 进行对比,找出不同之处,最后只更新那些发生变化的部分。
        • Diff 算法:这个算法负责对比新旧虚拟 DOM 树的差异,并确定哪些部分需要更新。它的目标是通过尽量减少 DOM 操作的次数来提高性能。
          🚀 Diff 算法的工作原理

          React 使用的 Diff 算法 基本上是通过以下步骤来优化更新的过程:

          1. 分层更新

          React 的 Diff 算法是基于 组件层级 来优化的,意思是它会将虚拟 DOM 树分成多个小的组件进行比较,而不是全局比较整个 DOM。

          • 树的比较:首先,React 会对比新旧虚拟 DOM 树的根节点。若根节点没有变化,它会继续向下比较,逐层进行差异计算。
            2. 同一层级的节点对比

            React 假设同一层级的节点在大多数情况下会有相似的结构。比如,两个 标签,React 会检查它们的属性是否相同,内容是否相同。

            • 同类型节点的对比:如果新旧节点是同一类型(比如 比较 ),React 会继续对比它们的属性和子元素。属性发生变化时,React 会更新对应的 DOM。
            • 不同类型的节点对比:如果新旧节点类型不同(比如 和 ),React 会直接销毁旧的 DOM 元素并创建新的元素。
              3. 键值优化(Key)

              在更新列表类型的组件时,React 会使用 key 属性来优化渲染。key 帮助 React 在比较过程中快速确定哪些元素是相同的,哪些元素是新增或删除的。

              • 有 key 的列表:React 会根据 key 来识别哪些节点被移动、插入或删除,避免不必要的 DOM 操作。
              • 没有 key 的列表:React 会采用默认的方式进行逐一比较,可能会导致性能问题,尤其是在列表较大时。
                4. 递归更新

                Diff 算法使用递归的方式,逐层对比虚拟 DOM 树。每当有变化时,React 会最小化对 DOM 的操作,只更新发生变化的部分。

                ⚡ Diff 算法的优化策略
                1. 假设同层节点较为稳定:React 假设同一层的 DOM 节点大部分情况下不会变化太大,因此它不会深度比较子树。只要节点类型相同,它就会继续更新,避免重复渲染。
                2. 通过 key 来快速定位变化:key 在列表渲染时尤为重要,它可以帮助 React 更高效地识别哪些节点是新增、删除或重新排序的,而不是全盘重新渲染。
                3. 最小化 DOM 操作:React 会尽量减少对 DOM 的操作,尽量一次性更新所有需要更改的部分,而不是逐个修改。

                6、手写节流和防抖

                🎯 1. 节流(Throttle)

                节流 是指限制某个操作在单位时间内只执行一次。它会让操作在一定时间内按照固定的频率执行,防止因为某些事件(比如滚动、窗口大小变化等)触发频繁导致性能问题。

                // 节流函数
                function throttle(func, wait) {
                  let lastTime = 0; // 记录上一次执行的时间
                  
                  return function(...args) {
                    const now = Date.now(); // 获取当前时间
                    if (now - lastTime >= wait) { // 如果距离上次执行的时间大于等于 wait
                      func(...args); // 执行函数
                      lastTime = now; // 更新最后执行时间
                    }
                  };
                }
                // 使用示例
                const handleScroll = throttle(() => {
                  console.log('滚动事件触发');
                }, 1000);
                window.addEventListener('scroll', handleScroll);
                
                🎯 2. 防抖(Debounce)

                防抖 是指在某个操作频繁触发时,只有在操作停止一段时间后才会执行一次。防抖通常用于输入框的搜索建议、表单验证等场景,确保在用户输入完毕后才执行某个操作,而不是每输入一次就执行一次。

                // 防抖函数
                function debounce(func, wait) {
                  let timeout; // 定时器
                  return function(...args) {
                    // 清除上一次的定时器
                    if (timeout) clearTimeout(timeout);
                    
                    // 设置新的定时器,确保在一定时间后执行函数
                    timeout = setTimeout(() => {
                      func(...args);
                    }, wait);
                  };
                }
                // 使用示例
                const handleInput = debounce(() => {
                  console.log('输入完成');
                }, 1000);
                document.getElementById('search').addEventListener('input', handleInput);
                
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码