在准备面试吗,或许可以收藏下这份面试解析

1,323 阅读18分钟

笔者现在研三,很荣幸在春招期间获得了阿里实习offer,在实习搬砖的同时,复习了以往的前端基础知识和刷leetcode题,在秋招期间获得了较多大厂的面试机会,并且拿到了一些offer。现在就整理下自己的面经,对于较难的题目也会附一些自己的见解。下文有附我的联系方式喔~,欢迎与我进行前端交流~

面试套路:

面试大致分为3个部分,自我介绍,面试官提问,你反问面试官,其中第一部分和第三部分都是你可以准备的,可以事先根据你所面试的部门,准备自我介绍中的亮点和最后提问的问题,有针对性的提问也是提高面试评价的手段之一。

例如对于我,在自我介绍部分,我会先说明自己毕业于哪,从什么时候开始学习前端,前端技术栈主要是什么,做过些什么东西,对什么方向感兴趣,从哪里了解到贵部门,很希望加入贵部门等。实际是对一个简历的简单概括,并展示自己对部门的了解程度,自我介绍部分大致时长控制在2-3分钟左右。

在最后提问环节,会事先准备2个技术问题和2个业务问题,例如,贵部门是怎么做错误监控的,有无自动化测试工具,基础建设做的如何。业务方面,贵部门主要负责的业务是什么,若是和其余大厂有重叠,有哪些优势等,这些都是可以提问的点。如何看待一些新兴技术,serveless等,在贵部门是否有落地。体现你对前沿技术的关注。

在第二部分,面试官提问环节,会问常规的面试题,例如跨域是什么,对于这种问题,我大致分为3个步骤来回答。

  1. 什么是跨域。
  2. 跨域的常见解决方案。
  3. 各种方案优缺点,若有自己的应用,可以结合自己的实际应用来谈理解。 因此,跨域问题你便可以这样回答。
  4. 产生:从同源策略方面解释跨域的产生。
  5. 跨域的通常解决方案(9种)。从简单到复杂来回答,对于常见的解决方案重点阐述实现过程。
  6. 各种方案优缺点,谈如何根据项目复杂度选择方案。和自己在项目中的应用。

这就可以展现给面试官你对这个知识点的全面了解。并且在面试的过程中埋雷,引导面试官往自己熟知的方向上提问。

对于实习和项目经历,可以提前猜测出面试官会问的问题,并且根据star原则来整理你的项目。例如项目难点是什么,你是怎么解决的,在回答中,你可以大致介绍下项目背景和遇到的业务痛点,技术痛点等,你是如何通过技术,沟通的手段去解决的,在哪些方面获得了提升。实习问题亦是如此,例如你在实习中遇到的最大困难,实习收获等。

下面我就将我遇到的一些问题进行一些简单整理和附上答案的链接或者自己的看法。若有不正确的地方或您有更好的方案的话欢迎底部留言评论!

网易一二三面:

  1. 跨域的基本概念和解决方法,在项目中的实际应用。
  • 产生:同源策略影响同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSRF等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
  • 解决方案
  • 在自己项目中的应用,常见操作是在后端设置access-control-allow-orgin为*,但是这会产生安全问题。例如a.com网站发出的请求,在后端设置该响应头为* 返回后,b.com也可以接收该信息,因此,常见是判断请求的网站域名是否在白名单内,若在白名单内,则access-control-allow-origin设置为对应的域名。
  1. JS事件循环和Node事件循环,两者有何区别。 参考链接
  • 介绍JS事件循环机制,以一个script文件的解析为例,从上往下解析时,当遇到setTimeout时,会将其放到宏任务队列中,当遇到promise等,会将其放到微任务队列中,随后在事件循环中,是每次首先清空微任务队列,随后再去执行一个宏任务。这样反复循环。
  • Node的事件循环过程,可以解释的不用像JS那么详细,大致的6个过程介绍下即可。分别为外部输入数据-->轮询阶段(poll)-->检查阶段(check)-->关闭事件回调阶段(close callback)-->定时器检测阶段(timer)-->I/O事件回调阶段(I/O callbacks)-->闲置阶段(idle, prepare)-->轮询阶段(按照该顺序反复运行)...
  • 区别:浏览器环境下,microtask的任务队列是每个macrotask执行完之后执行。而在Node.js中,microtask会在事件循环的各个阶段之间执行,也就是一个阶段执行完毕,就会去执行microtask队列的任务。
  1. BFC,块级格式化上下文。
  • BFC块级上下文概念:Formatting context 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。
  • 如何产生的和布局规则
  • 常见应用
  1. 强缓存和协商缓存,缓存的应用,如何用在页面性能优化上。
  • 缓存的优势
  • 协商缓存和强缓存的区别
  • 缓存在css和图片上的应用,webpack中根据内容产生对于hash值,当hash值不变时,浏览器可以应用本地缓存内容,而不用去请求服务器。
  1. ES6新增特性。
  • 从常见的几个新特性下手,例如let,const。es6新增的解构赋值,map和set等,
  1. async await如何利用generator实现。参考
  2. Vue2.0与Vue3.0双向绑定,proxy实现。
  • 我个人总结了一篇说辞:首先我们来区分是vue2还是vue3,vue3里面使用的是proxy,我们稍后再聊,我们重点聊vue2里的object.defineProperty, 是怎么实现的呢,我们以一个例子为例,定义了一个object,里面有{a:1,b:2}, 我们通过for key in object 来遍历这个对象,将每个键key通过object.defineProperty设置为可监听的,在get中来搜集,我们在哪里使用到了这个key,比如, {{a}} 这里就对应一个个watcher, 那我们怎么保存呢,一个key都会对应一个Dep类,而这个类里有一个deps数组,我们就来保存这些watcher。在get中搜集完了,我们怎么去触发呢,比如a此时值变成了3,我们可以把a对应的Dep类拿出来,遍历里面的dep数组,设置成最新的值,这样就可以达到双向绑定
  • vue3.0双向绑定简单实现
  1. 移动端点击穿透问题。
  1. 爬虫方面问题,反爬如何实现,针对反爬的实现(IP代理等)。
  • 爬虫主要遇到的问题是当频繁的访问某个网站的时候,服务器端会检测到该爬虫,因此会有对应的反爬策略,例如页面自动关闭,或者跳出验证码,需要你手动识别等。我们针对这些反爬策略,可以由简单到复杂说明如何应对。
  • 1.大众点评需要用户登录情况下才能看见全部评论消息,那我们可以做模拟登录。提前登录保存cookie信息,随后利用selenium模拟浏览器打开,将cookie信息写入,来模拟用户登录。
  • 2.pc端网站有反爬,但h5页面没有,因此可以使用h5页面进行爬虫。
  • 3.买一个IP代理工具,每隔2-3分钟切换IP,让服务器检测不到我们是一个爬虫程序。
  • 4.我们通常是爬取html页面上的信息,找到信息与我们所需数据的映射关系,随后定义好规则,进行解析。
  1. 图片懒加载具体实现方案和思路。
  1. 实习难点,收获。
  • 有实习小伙伴的同学总结下自己实习中遇到的困难和自己解决问题的思路和过程。
  1. code review需要注意的点,你做code reivew的话,会重点查看哪里,怎么写出高内聚,低耦合的代码,以实习中遇到的一个通用组件实现举例。
  • code review主要查看的是你的代码风格和是否有逻辑性的错误,若发现一个逻辑重复2次以上,就想办法将抽离出来成为一种公共组件。如何抽离的,可以以业务中遇到的问题举例。
  1. 未来规划,如何学习前端的,自己感兴趣的前端方向是什么。
  • 学习前端的过程,从基础->工程->源码,如何做总结的。
  • 感兴趣的前端方向,可以说目前前端几个较热的方向,例如工程化,跨端,serverless,图形学等,结合自己的理解来谈。

拼多多一二面:

  1. 常见攻击,CSRF是什么,如何防范,token产生策略。
  • 1.回答CSRF攻击是什么。即跨站请求伪造,是一种常见的Web攻击,它利用用户已登录的身份,在用户毫不知情的情况下,以用户的名义完成非法操作。
  • 如何防范,从简单复杂,samesite属性 -> referer check -> token
  • 常见web攻击汇总
  1. React Fiber原理。有什么优势。
  • 首先阐述老的React15更新算法有什么劣势。
  • 老的更新过程:当React决定要加载或者更新组件树时,会做很多事,比如调用各个组件的生命周期函数,计算和比对Virtual DOM,最后更新DOM树,这整个过程是同步进行的,也就是说只要一个加载或者更新过程开始,那React就以不破楼兰终不还的气概,一鼓作气运行到底,中途绝不停歇。总归一句话会造成阻塞。
  • 新的更新过程:把一个耗时长的任务分成很多小片,每一个小片的运行时间很短,虽然总时间依然很长,但是在每个小片执行完之后,都给其他任务一个执行的机会,这样唯一的线程就不会被独占,其他任务依然有运行的机会。
  • React Fiber更新过程
  1. React生命周期,React16.3版本后变化,为什么要这样做。(结合React Fiber),有哪些不安全的生命周期。
  • React新老生命周期对比
  • 为什么这样做:如果开启了异步渲染,在render函数之前的所有函数,都有可能被多次执行。
  1. JS事件循环。
  2. 两列布局实现。
  • 代码实现:两列布局和三栏布局实现的方式差不多,1.浮动。2.绝对定位。3.flex布局。4.表格布局 5.网格布局实现。
  1. 函数防抖,节流实现,不同方案实现。
  • 所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
  • 防抖有立即触发版和非立即触发板 代码实现
  • 非立即执行版:
function debounce(func, wait) {
  let timeout;
  return function () {
      let context = this;
      let args = arguments;

      if (timeout) clearTimeout(timeout);
      
      timeout = setTimeout(() => {
          func.apply(context, args)
      }, wait);
  }
}
  • 立即执行版
function debounce(func,wait) {
    let timeout;
    return function () {
        let context = this;
        let args = arguments;

        if (timeout) clearTimeout(timeout);

        let callNow = !timeout;
        timeout = setTimeout(() => {
            timeout = null;
        }, wait)

        if (callNow) func.apply(context, args)
    }
}
  • 节流(throttle)
  • 所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。对于节流,一般有两种方式可以实现,分别是时间戳版和定时器版。
  • 时间戳版:
function throttle(func, wait) {
    let previous = 0;
    return function() {
        let now = Date.now();
        let context = this;
        let args = arguments;
        if (now - previous > wait) {
            func.apply(context, args);
            previous = now;
        }
    }
}
  • 定时器版:
function throttle(func, wait) {
    let timeout;
    return function() {
        let context = this;
        let args = arguments;
        if (!timeout) {
            timeout = setTimeout(() => {
                timeout = null;
                func.apply(context, args)
            }, wait)
        }

    }
}
  1. 二面主要在扯实习的事情,问了Redux原理,实习难点啥的,编程题实现一个EventBus和手写一个深拷贝。

腾讯一二面:

  1. 弱网环境下页面首屏如何快速加载
  • 1.缓存的使用,对于css和图片中资源,利用hash值来存储
  • 2.SSR使用(使用服务端渲染)
  • 3.骨架屏使用,让用户感受到页面正在加载。
  1. 跨域问题和解决方案。
  2. 宏任务和微任务区别。
  1. node是IO密集型体现在哪里。从nodde异步的角度来回答这个问题。
  1. http2 http3优化点在哪 https建立连接过程
  • 阐述http1.0和http1.1中存在的问题。
  • http2的优势:二进制传输,头部压缩 多路复用 主动推送 基于SPDY协议
  • http3的优势:基于QUIC协议,本质是基于UDP,而不像http2.0继续基于TCP.
  • 参考链接
  • https链接创建过程
  1. 函数式编程思想的体现
  1. 25匹马、5个赛道,怎么用最少的次数决出前三名
  1. CSRF攻击问题。
  2. 项目中遇到的问题,重点说了下爬虫遇到的问题,如何解决反爬的。
  3. 实习遇到的问题,如何沟通,解决
  4. 个人规划。

快手一二三面

  1. js实现继承
  1. 闭包。
  1. js事件循环。
  2. vue双向绑定实现原理
  3. vue中指令的使用
  1. vue中nextTick的原理
  1. 虚拟dom以及diff算法。
  1. 错误监控方法。
  1. 页面加载会触发哪些事件
  • 大致分为如下步骤:开始解析HTML文档结构 -> 加载外部样式表及JavaScript脚本 ->   解析执行JavaScript脚本 -> DOM树渲染完成 -> 加载未完成的外部资源(如图片)页面加载成功
  • 参考链接
  1. babel源码。
  • babel的作用:Babel是一个工具链,主要用于将ECMAScript 2015+版本代码向后兼容 Javascript 语法,以便可以运行到旧版本浏览器或其他环境中。
  • babel解析的大致步骤:解析 -> 转换 -> 生成
  • 参考链接
  1. setState原理
  • 大致过程:setState之后不会立马触发更新,它会根据当前isBatchingUpdate 判断是否处于批量更新中,如果当前isBatchingUpdate为true,说明处于批量跟新中,它会将要更新的值放入到一个队列中,随后将要更新的组件放入dirtyComponent中,当本次批量更新结束后,会将isBatchingUpdate中设置为false,开启本次的批量跟新,情况队列,会用object.assign()将多次更新进行一个合并。 react会开启一个事务机制,进行dom diff算法等来进行跟新。
  • 参考链接
  1. 实现一个EventEmitter类,支持事件的on,off,emit,once,setMaxListeners
  2. document.ready和window.onload的区别
  1. webpack loader和plugin区别
  • 深入浅出webpack中提到过loader和webpack的区别。
  • loader一般是将某个语法统一处理为统一的语法
  • plugin一般是在打包前或打包后对结果进行再次操作
  1. 打包gulp,webpack,rollup一些区别。
  • gulp: Gulp 是基于“流”的自动化构建工具,采用代码优于配置的策略,更易于学习和使用
  • webpack:Webpack 是模块化管理工具和打包工具。通过 loader 的转换,任何形式的资源都可以视作模块,比如 CommonJs 模块、AMD 模块、ES6 模块、CSS、图片等。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载
  • rollup: Rollup 是下一代 ES6 模块化工具,它最大的亮点是利用 ES6 模块设计,生成更简洁、更简单的代码。尽可能高效地构建出能够直接被其它 JavaScript 库引用的模块
  • 可以结合最新的vite(基于ES import的来动态化打包) 分析各个打包工具的优缺点和适用场景
  1. webpack中循环引用问题,a里面引用了b,b里面引用了a.
  1. CICD,如何实现一个自动化部署工具,结合github中的webhook机制。
  • 本地push代码后->github进行webhook监听-> 进行构建部署,重启docker -> 随后开启微信或钉钉群通知,监控错误
  1. 全排列算法的实现。
  2. 斐波那契算法。
  3. 实习遇到的困难。实习期间干的事情。

字节一二三面

  1. 1px问题。
  • 产生原因:由于不同的手机有不同的像素密度导致的。如果移动显示屏的分辨率始终是普通屏幕的2倍,1px的边框在devicePixelRatio=2的移动显示屏下会显示成2px,所以在高清瓶下看着1px总是感觉变胖了
  • 解决方案
  1. 清楚浮动的方案。
  1. js基础数据类型,如何判断,有什么方法。
  • number,boolean,string,undefined,null。
  • typeof,instanceof,constructor判断,Object.prototype.toString.call()几种方法区别。
  1. 闭包问题。
  2. node事件循环
  3. 进程和线程区别。
  • 概述:进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
  • 简而言之:个程序至少有一个进程,一个进程至少有一个线程. 可以从浏览器中线程和进程的区别来阐述
  1. cpu调度算法
  1. 2台计算机底层之间如何通信 socket IO通信实现。
  1. 计算机网络中,http地址,在四层层协议中,如何一步步向下解析,从应用层到最底层的物理层,每一层处理的事情。
  2. 位图和矢量图的区别。
  3. cookie中常见的字段。
  1. 同源策略
  2. http中一些常见的响应头和请求头,有什么应用。
  • 可以结合缓存中常见的响应头来回答。
  1. 简单请求和非简单请求区别。
  • 满足简单请求的几个条件
  • 非简单请求的几个条件。
  • 在跨域中的使用。 参考链接
  1. 函数式编程思想。
  2. ts自己的看法,和应用
  • 谈js与ts之间的区别 和ts相对于js有什么优势
  • 参考链接
  1. react fiber原理
  2. http2.0 http3.0分别改进了什么
  3. 手写diff
  4. 手写Promise.All()
  5. 算法题:版本号比较
  6. IP地址复原

总结:

以上便是自己遇到的一些面试题的简单总结,实际上个人认为参考答案因人而异,就像每个人心中都有一个哈姆雷特一样,因此我附上了一些答案的链接。在你自己总结和理解这个知识点后,可能会得到更符合你自己的答案,尝试将其说出来,在面试前进行多次的模拟,便可以轻松的面对每一次面试,要相信一切资本主义都是纸老虎!。祝愿各位小伙伴都能获得心仪的offer! 若对上述答案有疑问,欢迎添加我的微信或者进入天天大佬的前端交流群,与我进行讨论~,谢谢!

天天前端交流群~