logo

4/6 字节三面真刺激!前端都这么难?

作者
Modified on
Reading time
10 分钟阅读:..评论:..

下面我将分享一位同学在字节跳动的三面面试经历,对于这次面试,他的评价是非常注重深度和技术广度,准备好挑战你的前端知识储备了吗?

【提醒】通过这次面试经验,你将可以复习到以下知识点:

  • Vue 2和Vue 3的差异
  • Vue模板编译过程及AST的角色
  • 虚拟DOM的生成过程
  • React Hooks中useState的上下文环境保存
  • Webpack的模块化实现原理
  • 后端知识点及数据库索引相关问题
  • 网络协议,特别是HTTP协议的不同版本比较
  • 微前端技术及其工程化实践
  • 实习项目经历和技术实现细节

面试官: 你好,欢迎来到字节跳动的面试。我看到你对Vue的底层实现很熟悉,那么能简单地谈谈Vue 2和Vue 3之间的区别吗?

求职者: 当然可以。Vue 3相比于Vue 2来说做了很多底层的优化和改进。首先,Vue 3使用了Proxy代替了Object.defineProperty来实现响应式,这让Vue 3能够更好地监测到数据的变化,包括新增属性和删除属性。其次,Vue 3提供了Composition API,这是一组基于函数的API,让逻辑复用和组织更加灵活。此外,Vue 3的虚拟DOM重写了,提高了渲染性能,同时也减小了整个框架的体积。

面试官: 很好。那么接下来,请你详细说明下,Vue的template是如何被转化的,以及这个过程中AST扮演了什么角色?

求职者: Vue的模板编译过程大致分为三个步骤:解析、优化和代码生成。首先,模板会被解析成AST(抽象语法树),这个过程中,编译器会将模板字符串解析成DOM元素树的JS对象表示。然后,Vue会遍历AST进行静态节点标记,这样在比较虚拟DOM时,可以跳过静态树的比较。最后,根据AST生成渲染函数的代码字符串,这个渲染函数在被调用时会生成虚拟DOM。

面试官: 那你能详细说说AST如何转化为虚拟DOM的吗?

求职者: AST到虚拟DOM的转化实际上是在编译时的代码生成阶段完成的。编译器会根据AST来构建虚拟DOM树结构,每个AST节点都对应一个虚拟DOM节点,包含了元素的类型、属性、事件等信息。通过递归遍历AST,编译器会生成一系列创建虚拟DOM节点的函数调用,并最终返回一个渲染函数。当数据变化时,这个渲染函数会被重新调用,生成新的虚拟DOM,并和旧的虚拟DOM进行比较,以确定哪些部分需要在真实DOM上更新。

面试官: 好的。现在我们换个话题,你知道React中的useState是如何保存上下文环境的吗?

求职者: useState在React中是通过Hooks机制实现的。每次组件渲染时,useState都会返回当前的状态值以及一个更新状态的函数。React内部会保持一个状态列表,其中的状态值和组件的渲染是绑定的。当状态更新函数被调用时,它会更新React的状态列表中相应的状态值,然后触发组件的重新渲染。而这些状态值是保存在React的Fiber节点中的,这就保证了即使组件多次渲染,状态也会被持久化。

面试官: 很好。接下来,谈谈你对Webpack模块化实现原理的理解。

求职者: Webpack是一个模块打包工具,它的核心原理是将各种资源都视作模块,然后通过加载器和插件对这些模块进行处理,最后打包成浏览器可以识别的文件。在打包过程中,Webpack会从入口文件开始,分析出所有依赖的模块,然后加载这些模块,最终生成一个或多个bundle。Webpack中的每个模块都被封装在一个函数闭包中,通过__webpack_require__函数来实现模块间的依赖加载。

面试官: 明白了。那你是否对后端开发有所了解?比如Java或Node.js

求职者: 我对后端也有一定的了解。我使用过Node.js来开发一些服务端程序,主要涉及HTTP服务的搭建、请求处理、与数据库交云存储等。至于Java,我对它的基本语法和一些框架如Spring Boot有所接触,但没有深入的开发经验。

面试官: 好的,那你对数据库索引有了解吗?你知道索引和顺序之间的关系吗?

求职者: 数据库索引对于提升查询性能非常关键,它类似于书籍的目录,可以帮助数据库快速定位到数据。索引与数据的物理顺序有关,一个良好设计的索引通常是按照某种顺序存储的,比如B+树索引,它会根据键值的顺序来组织数据,这样可以加速查找和排序等操作。

面试官: 很好,这样的理解是正确的。那你听说过数据库的交叉索引吗?

求职者: 交叉索引,或者叫复合索引,是指在数据库表上同时按照多个列来建立索引。它可以极大提升查询性能,特别是当查询条件包含多个列时。不过需要注意的是,复合索引的列顺序会影响其效率,通常对于查询条件中出现频率高的列应该放在索引的前面。

面试官: 了解了。那我们再换一个话题,你说你擅长网络知识,那么HTTP 1.0和HTTP 2.0有什么区别

求职者: HTTP 2.0相比于HTTP 1.0有了很多改进。最主要的是它支持多路复用,允许在同一个TCP连接上并行传输多个请求和响应,这减少了延迟。它还引入了头部压缩来减小开销,以及服务器推送功能,服务器可以推送额外资源到客户端缓存中以提升性能。而HTTP 1.0每次请求都需要建立一个TCP连接,且不支持现代Web的许多高效功能。

面试官: 很好,那请谈谈你在项目中尝试过的一些工程化的实践

求职者: 在项目中,我尝试过多种工程化的实践,比如通过CLI工具来快速生成项目模板,搭建组件库来复用UI组件,以及利用微前端技术来整合多个子应用。例如,在使用微前端框架qiankun时,我利用其提供的生命周期钩子和沙盒解决方案来确保主应用和子应用能够独立运行,互不干扰。

面试官: 对于微前端,你了解qiankun的沙盒方案吗?除了你提到的Proxy和Shadow DOM还有其他的实现方式吗?

求职者: 是的,qiankun框架的沙盒方案主要是基于JavaScript的Proxy来实现的,它通过拦截子应用中的全局变量的操作,确保不同的子应用之间的全局变量不会相互影响。除了Proxy,qiankun还利用了快照沙箱,在应用切换时对全局环境进行快照和恢复,防止应用间的污染。还有使用iframe作为沙盒的传统方式,它可以提供一个完全隔离的运行环境,但这种方式存在性能和体验上的缺陷。

面试官: 很好。你了解哪些其他的微前端实现方案,它们的优势和劣势是什么?

求职者: 除了qiankun,我还了解了single-spa、IFrame、Web Components等微前端实现方案。single-spa可以实现前端服务的集成,支持多种框架共存,但它的缺点是需要一定的学习成本,并且需要对现有系统做一定改造。IFrame方案的优势是完全隔离,易于集成,但通信复杂、加载性能差。Web Components可以提供封装性和复用性,但浏览器支持度和生态圈还不够成熟。

面试官: 非常全面。接下来,请谈谈你的项目实习经历

求职者: 我在实习期间主要负责了一个电商平台的前端开发工作,使用Vue.js框架。我参与了购物车模块的开发,实现了商品选择、编辑、结算等功能,并对性能进行了优化。此外,我还参与了前端组件库的建设,设计并实现了多个通用组件,提高了开发效率。

面试官: 最后一个问题,现在请你手写一个类似于百度搜索框的功能,包括键盘上下键选择搜索建议的功能以及虚拟滚动的实现。

求职者: 好的,请稍等,我开始编码。

// 假设有一个输入框元素 inputElem 和一个搜索建议展示元素 suggestionElem // 监听输入框的输入事件,获取搜索建议 inputElem.addEventListener('input', function(event) { const query = event.target.value; // 这里调用获取搜索建议的函数,假设返回的是一个Promise fetchSearchSuggestions(query).then(suggestions => { // 根据搜索建议更新DOM updateSuggestionsDOM(suggestions); }); }); // 更新DOM的函数 function updateSuggestionsDOM(suggestions) { // 清空现有的搜索建议 suggestionElem.innerHTML = ''; // 添加新的搜索建议 suggestions.forEach(suggestion => { const div = document.createElement('div'); div.textContent = suggestion; suggestionElem.appendChild(div); }); // 虚拟滚动的实现会根据滚动位置动态加载或卸载搜索建议的DOM节点 } // 监听键盘事件以实现上下键选择 let selectedIndex = -1; inputElem.addEventListener('keydown', function(event) { const suggestions = suggestionElem.children; if (event.key === 'ArrowDown') { selectedIndex = (selectedIndex + 1) % suggestions.length; highlightSuggestion(selectedIndex); event.preventDefault(); } else if (event.key === 'ArrowUp') { selectedIndex = (selectedIndex - 1 + suggestions.length) % suggestions.length; highlightSuggestion(selectedIndex); event.preventDefault(); } }); // 高亮选中的搜索建议 function highlightSuggestion(index) { // 先去除所有高亮 [...suggestionElem.children].forEach(div => div.classList.remove('highlight')); // 高亮当前选中的元素 suggestionElem.children[index].classList.add('highlight'); // 确保高亮的元素在可视范围内 suggestionElem.children[index].scrollIntoView({ block: 'nearest' }); }

面试官: 很好,你的基础知识掌握得很扎实,对微前端也有深入的了解。这次面试就到这里,感谢你的参与。我们会尽快给你反馈。有没有什么想要问我的?

求职者: 谢谢,我想了解一下,如果我有幸加入贵公司,我会参与哪些类型的项目?

面试官: 在字节跳动,我们的项目范围非常广泛,包括但不限于Web前端开发、移动端应用开发、后端服务架构等。根据你的技术背景和兴趣,我们会为你匹配合适的项目和团队,确保你能够发挥最大的潜力并不断成长。再次感谢你今天的表现,希望你有一个美好的一天。

题库

开始新面试:字节三面 1.自我介绍,说自己更懂vue底层 2.来个简单点的,vue2和3区别,5分钟吟诵 3.vue的template是如何转化的,说说这个过程,中间提到了ast 4.详细说说ast如何转化为虚拟dom(g,磕磕绊绊没说出来) 5.useState这么保存上下文环境,答了闭包,但是还有呢 6._webpack_require实现原理 7.后端,会用吗,java,node? 8.数据库,索引和顺序有关吗知道 9.数据库的交叉索引? 10.擅长什么基础课?网络 11.http1.0和2.0区别,即答,这部分没问题我们再问问别的吧 12.谈谈你试下的一些工程化的东西?cli,组件库,微前端 13.谈谈微前端qiankun的沙盒方案,答了proxy和shaowDom还有吗,有好几种 14.还知道哪些微前端,优势劣势 15.谈项目实习经历 16.手写百度搜索,包括上下键选中以及虚拟滚动