前端面试题详解整理41|时针分针夹角webpack与vite区别,对象的key下划线转驼峰,设计一个通用缓存方案,缓存,service worker模块化方案,

130 阅读10分钟

www.nowcoder.com/discuss/527…

腾讯前端面经

一面(8.29 1h45min)

八股

  • 实习经历
  • js基础,闭包,原型,事件循环xxx
  • webpack、vite区别,模块化方案,用过哪些插件,写过哪些插件

webpack与vite区别

  1. 构建方式:

    • webpack:基于配置文件进行构建,需要配置各种loader和plugin,比较复杂。
    • Vite:基于现代浏览器原生 ES 模块的开发服务器,利用浏览器的原生模块加载速度快的特性,不需要打包,开发时即时编译。
  2. 启动速度:

    • webpack:由于需要进行打包,启动速度较慢,尤其是在大型项目中。
    • Vite:由于不需要打包,启动速度非常快,几乎是即时的。
  3. 热更新:

    • webpack:热更新依赖于webpack-dev-server,需要重新构建并刷新浏览器页面。
    • Vite:利用ES模块的特性,支持快速的热更新,只更新修改的模块,不需要刷新整个页面。
  4. 生态支持:

    • webpack:成熟的生态系统,有大量的loader和plugin,可以满足各种需求。
    • Vite:相对较新,生态系统还在发展阶段,部分webpack的loader和plugin可能不兼容。
  5. 打包输出:

    • webpack:支持生成生产环境的打包文件,适用于传统的构建场景。
    • Vite:开发时不进行打包,生产环境需要使用其他工具进行打包(如rollup等)。

模块化方案

常见的模块化方案有CommonJS、ES6 Module、AMD、UMD等,其中:

  • CommonJS 是Node.js的模块化方案,通过requiremodule.exports来导入和导出模块。
  • ES6 Module 是JavaScript的官方模块化方案,通过importexport来导入和导出模块。
  • AMD (Asynchronous Module Definition) 是RequireJS的模块化方案,用于浏览器端异步加载模块。
  • UMD (Universal Module Definition) 是一种通用模块定义规范,兼容CommonJS、AMD和全局变量的模块导入方式。

使用过的插件

常见的webpack插件有:

  • HtmlWebpackPlugin:用于生成HTML文件,并自动注入打包后的资源。
  • MiniCssExtractPlugin:用于将CSS提取为独立的文件。
  • CleanWebpackPlugin:用于清理输出目录。
  • CopyWebpackPlugin:用于复制文件或目录到构建目录。
  • DefinePlugin:用于定义全局变量。
  • ProvidePlugin:自动加载模块,无需使用import或require。

写过的插件

编写webpack插件的方式可以扩展webpack的功能,常见的插件包括loader和plugin。

  • Loader是用于加载资源文件的转换器,例如将ES6转换为ES5、将SCSS转换为CSS等。
  • Plugin是用于扩展webpack功能的插件,可以在构建过程中的各个阶段执行自定义操作,例如文件压缩、代码分割、自动引入CDN等。

编写webpack插件需要了解webpack的内部原理和钩子机制,常见的钩子包括compilercompilation,通过这些钩子可以在合适的时机执行自定义操作。

  • vue2、vue3区别,nextTick原理

缓存,service worker,延伸至移动端弱网环境下如何优化,具体没听懂

在移动端弱网环境下,优化缓存和使用Service Worker可以有效提高网页加载速度和用户体验。以下是一些优化策略:

  1. 优化缓存策略:

    • 使用合适的缓存策略,可以减少网络请求次数,降低页面加载时间。对于移动端弱网环境,应当尽量减少对服务器的请求,可以通过合理设置缓存头部来实现。
    • 将静态资源(如图片、样式表、脚本文件)进行本地缓存,减少网络请求的依赖。
    • 使用浏览器缓存机制,将不经常变动的资源进行缓存,减少重复下载。
  2. 使用Service Worker进行离线缓存:

    • Service Worker 是运行在浏览器背后的一段脚本,可以拦截和处理网络请求,实现离线缓存和资源预加载。
    • 在移动端弱网环境下,可以通过Service Worker将页面所需的资源缓存到本地,以便在网络不可用时能够快速加载页面。
    • 使用Service Worker的缓存策略,可以根据不同的资源类型和更新频率,动态地调整缓存策略,以满足页面的实时性和性能需求。
  3. 优化页面加载速度:

    • 减少页面的体积和请求次数,可以通过压缩资源、合并文件、异步加载等方式来减小页面的加载时间。
    • 使用图片懒加载和延迟加载技术,优化页面中图片资源的加载顺序和时间,提高页面加载速度。
  4. 使用WebP等优化图片格式:

    • 在移动端环境下,可以使用WebP等现代图片格式来替代传统的图片格式,以减小图片体积,提高加载速度。
  5. 优化网络请求:

    • 减少不必要的网络请求,可以通过合并请求、使用CDN等方式来减少页面加载时的网络开销。
    • 使用HTTP/2协议等新一代网络协议,可以提高网络请求的并发性和传输效率。

综上所述,通过优化缓存策略、使用Service Worker、优化页面加载速度和网络请求等方式,可以在移动端弱网环境下提高网页加载速度和用户体验。这些优化策略可以根据实际情况进行灵活调整,以达到最佳的性能优化效果。

设计一个通用缓存方案(具体忘了,牛客上应该有朋友记录过)

设计一个通用的缓存方案可以涵盖多种场景和需求,以下是一个简单的缓存方案设计示例:

缓存方案设计

  1. 缓存策略:

    • 根据业务需求和数据特性选择合适的缓存策略,常见的缓存策略包括:FIFO(先进先出)、LRU(最近最少使用)、LFU(最不经常使用)等。
    • 可以结合缓存的大小、数据更新频率、访问模式等因素来确定缓存策略。
  2. 缓存层级:

    • 可以设计多层缓存结构,根据数据的访问频率和重要性进行分层管理。
    • 比如可以使用内存缓存(如Redis、Memcached)作为一级缓存,将常用的数据缓存到内存中,以提高访问速度;而较少使用的数据可以缓存到磁盘中作为二级缓存。
  3. 缓存更新机制:

    • 设计缓存更新机制,确保缓存数据的及时更新。
    • 可以采用定时更新、手动更新或根据数据变化自动更新等方式来更新缓存数据。
  4. 缓存失效策略:

    • 设计缓存失效策略,根据数据的特性和业务需求确定缓存的失效时间。
    • 可以根据数据的更新频率和重要性来设置缓存的过期时间,以避免缓存数据过期而导致数据不一致的问题。
  5. 缓存监控和管理:

    • 设计缓存监控和管理机制,实时监控缓存的使用情况和缓存命中率。
    • 可以使用监控工具或自定义监控系统来监控缓存的运行状态,并根据监控数据进行缓存的优化和调整。

实现思路

  1. 选择合适的缓存技术:

    • 根据业务需求和数据特性选择合适的缓存技术,比如使用Redis、Memcached等内存缓存技术,或使用文件系统、数据库等持久化缓存技术。
  2. 设计缓存接口:

    • 设计统一的缓存接口,包括数据的读取、写入、更新和删除等操作,以便在不同的缓存技术之间进行切换和扩展。
  3. 实现缓存管理模块:

    • 编写缓存管理模块,负责缓存的初始化、配置和管理,包括缓存策略的选择和调整、缓存的监控和管理等功能。
  4. 实现缓存存储模块:

    • 根据选择的缓存技术,实现相应的缓存存储模块,负责数据的读取、写入、更新和删除等操作。
  5. 实现缓存更新机制:

    • 根据缓存更新策略,实现缓存的更新机制,包括定时更新、手动更新或根据数据变化自动更新等方式。
  6. 实现缓存失效策略:

    • 根据缓存失效策略,实现缓存的失效机制,包括设置缓存的过期时间、监控缓存的使用情况并根据需要进行缓存的清理和更新等操作。
  7. 实现缓存监控和管理:

    • 根据缓存监控和管理需求,实现缓存的监控和管理模块,包括监控缓存的运行状态、命中率和使用情况,并根据监控数据进行缓存的优化和调整等操作。

通过以上设计和实现,可以构建一个通用的缓存方案,满足不同场景下的缓存需求,并提高系统的性能和可扩展性。

  • 计网八股

手写

  • HardMan
  • promise并发

对象的key下划线转驼峰

将对象的键名中的下划线格式转换为驼峰格式是一个常见的需求,可以通过编写一个函数来实现。以下是一个 JavaScript 函数示例:

function convertKeysToCamelCase(obj) {
    // 检查参数是否为对象
    if (typeof obj !== 'object' || obj === null) {
        throw new Error('Input must be an object');
    }

    // 创建一个新的对象,用于存储转换后的键值对
    const newObj = {};

    // 遍历对象的键值对
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            // 将下划线格式的键名转换为驼峰格式
            const camelCaseKey = key.replace(/_([a-z])/g, function(match, group1) {
                return group1.toUpperCase();
            });
            // 将转换后的键值对存入新对象中
            newObj[camelCaseKey] = obj[key];
        }
    }

    return newObj;
}

// 示例
const obj = {
    user_name: 'John',
    age: 30,
    address_info: {
        street_name: 'Main St',
        postal_code: '12345'
    }
};

const newObj = convertKeysToCamelCase(obj);
console.log(newObj);

在上面的示例中,convertKeysToCamelCase 函数接受一个对象作为参数,并返回一个新的对象,其中的键名已经转换为驼峰格式。这里使用了正则表达式来匹配下划线后面的字母,并将其转换为大写字母。

二面(8.31 45min)

  • 项目拷打
  • 实习拷打

写一个时针分针夹角

要计算时针和分针之间的夹角,可以通过以下步骤来实现:

  1. 计算时针和分针分别与12点钟方向的夹角。
  2. 计算两个夹角之间的差值,即时针与分针之间的夹角。

以下是一个 JavaScript 函数示例:

function calcClockAngle(hour, minute) {
    // 小时制转换为角度制,每小时30度,每分钟0.5度
    const hourAngle = (hour % 12) * 30 + minute * 0.5;
    const minuteAngle = minute * 6; // 每分钟6度

    // 计算夹角
    let angle = Math.abs(hourAngle - minuteAngle);

    // 如果角度大于180度,则取360度减去角度
    if (angle > 180) {
        angle = 360 - angle;
    }

    return angle;
}

// 示例
const hour = 3; // 时针指向3点
const minute = 15; // 分针指向3点的方向,即15分钟
const angle = calcClockAngle(hour, minute);
console.log("时针和分针夹角为:" + angle + "度");

在这个示例中,calcClockAngle 函数接受两个参数:hour 表示小时数(取值范围为0到11),minute 表示分钟数(取值范围为0到59)。函数首先将小时和分钟转换为角度制,然后计算时针和分针的夹角,并返回结果。

第二天挂, 二面答得确实差,整体面试体验良好,部门是QQ

作者:IpKKpi
链接:www.nowcoder.com/discuss/527…
来源:牛客网