【前端面经】2023面试复盘之美团

5,270 阅读14分钟

相关链接:
一图搞定前端面试之基础篇
【前端面经】2023面试复盘之字节跳动
【前端面经】2023面试复盘之小红书
【前端面经】2023面试复盘之阿里云
【前端面经】2023面试复盘之蚂蚁金服
【前端面经】2023面试复盘之快手

结论

✅通过

一开始没想投美团来着,毕竟之前在美团呆过,再去也没了新鲜感,不过前同事听说我要换工作就联系了我,也是直推了他们组。可能是之前在的时候绩效比较好,加上有前同事的背书,面试自我感觉答得不是很好,最后也是顺利的通过了。

从技术面来看,美团的一面是这次几家中最难的。不过美团的间隔时间有点久,二面之后等了一周才有消息,一度以为因为想要高职级所以给挂了。还有一点比较奇怪,美团的技术面竟然只有两面,之后就直接约了HR面。

一面

总时长:90min

这场面试真是让我有点汗流浃背,感觉跟其他的面试都不是一个难度,问的还是挺深的,中间有些问题和最后的算法题答的都不是很好,也是今年面试第一次对结果有点拿不准。不过最后面试官有提到“写的算法题二面的时候可能会用到”,也算是暗示了后面会有二面的意思吧(也可能是内推我的前同事给了我背书,哈哈哈)🤣。

详细介绍一段工作经历

考虑到面试的岗位主要是做小程序相关的业务,所以就详细介绍了在美团做小程序的经历,主要就是聊一下做的事情,负责的项目以及项目中使用的一些技术等。详细内容就不在此赘述。

小程序性能优化做了哪些事情

先讲了一下小程序的架构和渲染原理,阐述小程序性能的影响因素,之后则介绍对应的性能优化手段有哪些。
主要包含以下:

  1. 使用小程序原生语法而不是类React或者Vue框架
  2. 减少setData次数,同时优化setData的数据量大小
  3. 请求预加载,重写路由方法,将下一个页面的请求提前到路由方法里调用
  4. 减少wxml的嵌套深度和节点数量,同时对wxss相同样式做合并处理
  5. 一些常规的优化手段:骨架屏、首屏数据缓存、分包、子包预加载、首屏接口合并、懒加载等方式

怎么去发现小程序的性能问题

主要通过小程序的开发者工具,可以先通过Audit去对整体的性能做一个概览,之后可以通过Trace去看小程序页面执行过程中具体的js文件或者方法的执行耗时,从中找出耗时较长的部分针对性做优化方案。

性能优化的标准是什么

在美团对移动端的性能优化是有自己的一套标准,实际优化标准为LVC(Last Visual Change)指标,具体指标的含义可以查看这篇文章前端感官性能的衡量和优化实践。这个指标是我们线下的优化标准,而线上的标准则是通过在代码中打点去获得FMP指标等的趋势情况。

小程序的日志和监控是怎么实现的

分为两部分,第一部分为日志的埋点和上传,包含了代码日志和业务日志。主要是自己实现了一个基于WebSocket的日志服务,在客户端项目加载的时候启动WebSocket,然后通过提供的log方法在代码中去进行日志打点。服务端收到上传的日志之后传入到公司内的数仓,之后通过数仓的API实现日志的查询。
对于业务数据的埋点则是在对应的用户操作时进行埋点上报。

另一部分则是告警的实现,这部分利用公司的统一基础设施去做。在拿到前面的埋点信息之后,在公司的告警平台可以看到对应的埋点数据的趋势图,根据趋势可以设置告警阈值。告警阈值主要是通过人工去指定告警策略并根据实际情况进行调整和优化,以实现更准确的告警。

百度的ER和San框架有什么区别

面试官之前也在百度,所以对百度的一些技术框架也有所了解,聊到这里了便详细问了一下。

ERSan分别是百度内部研发的MVCMVVM两个框架,因此这个问题主要介绍了MVCMVVM两类框架的差异,然后又具体讲了一下两个框架中特性上的一些差别。感兴趣的朋友可以从这里github.com/ecomfe/er/baidu.github.io/san/了解更多内容。

作为前端负责人如何更好的支撑业务

首先要熟悉业务,了解现有的业务逻辑是什么样的,然后理解业务,搞清楚业务逻辑为什么这么设计,之后就是可以去思考一下现有的业务流程或者开发流程中有什么问题和不足,并尝试通过系统性的技术方案去解决。

有没有通过技术手段去提升业务收益

在负责监控告警项目的时候,通过自定义指标的方式将业务核心流程进行量化,并形成可监控的线上指标趋势。这样在新需求上线之后可以通过业务指标的趋势图看出当前需求的上线对实际业务是否带来正向收益,在产生负向收益时可以及时复盘并回滚。同时当有纯技术改造上线时也可以通过业务指标的趋势看出技术改造带来的业务收益,从而可量化的衡量出技术的价值

js中为什么会出现变量提升

这个问题真是把我问住了,一开始讲了一下js中变量提升的几种情况,以及通过letconst去阻止变量提升,但面试官告诉我让我从js语言的设计上去想想。然后我就又扯到了静态语言动态语言的差别,绕了一大圈最后也没有讲明白😅。

js的垃圾回收机制是怎么实现

引用计数法标记清除法
引用计数法即在变量引用的时候将变量的引用计数+1,当变量的引用失效时(如离开作用域或者手动删除)将计数-1,直到计数为0时将该变量销毁。但是这种方法在出现循环引用时会有问题,所以后来js更新了自己的垃圾回收机制,采用了标记清除法
标记清除法是在变量进入到某个作用域时对变量计数+1,从某个作用域离开时则对变量计数-1,最终计数为0时则销毁变量。

NodeJS中模块的循环引用会出现什么效果

这个问题不太清楚,但是讲了一下CommonJS的导入规则和导入时的代码执行流程。

内存泄露有哪些情况

最常见的情况就是异步任务的回调未清除或者定时器任务没有清楚,其他的还有DOM引用未清除等。

如何排查内存泄露

通过开发者工具中的Performance模块,可以对页面加载和执行流程进行录制,之后在录制快照里查看内存的使用情况。如果发现有内存异常,则可以进一步缩小排查范围,最终找到引发内存泄露的代码。

有哪些技术手段可以用来监控内存泄露

这个确实也不太清楚,考虑到小程序里内存不足会导致页面白屏或无法打开,便从监控页面白屏的思路上讲了讲。之后面试官让我讲讲在NodeJS中有什么工具可以去监控,只能回答不清楚。

讲一讲Web安全

这个问题正好是复习过了,所以答得很全面,主要从浏览器同源策略CSPXSSCSRF以及SQL注入等方面分别做了介绍。

浏览器同源策略:

  1. 现代浏览器以及HTTPS会对非同源的请求进行拦截以保证安全
  2. 若请求链接中的协议、主机名、端口、方法等任何一个不一样,都是不同源请求

CSP:

  1. 内容安全策略,可以在HTML中的meta标签或者服务端返回的Content-Secrity-Policy头中进行设置
  2. 可以指定资源的请求域、资源的加载方式等

XSS:

  1. 跨站脚本攻击,分为了持久型XSS、反射型XSS和DOM型XSS
  2. 持久型XSS是最常见的XSS攻击,主要通过输入框、富文本等组件输入一些恶意的脚本代码,存储到服务端之后,当其他用户打开页面加载该脚本时便出现攻击行为
  3. 反射型XSS是需要用户点击黑客提供的恶意链接,该恶意链接会在跳转到正常页面的同时执行黑客脚本
  4. DOM型XSS存在于一些第三方插件中,如浏览器插件去恶意修改页面DOM等方式
  5. 对于XSS的防范主要是防范持久型XSS,在页面的输入框和富文本提交时对字符串做过滤处理,同时在页面中只对可信的HTML文本做解析

CSRF:

  1. 跨站请求伪造,当用户在正常的网站登录之后,由于同源请求会默认携带Cookie,因此黑客可以在自己的网站中向正常网站发送伪造请求来冒充用户自己的操作
  2. 攻击方式主要包含通过标签的src属性、href属性以及form的action属性等,通常是伪造GET请求
  3. 防范方式包含使用POST请求处理资源、服务端验证请求的Referer、禁止第三方网站请求携带Cookie以及最后在请求时增加csrftoken字段做校验

【代码题】盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。

//  第一种方式,暴力解法,直接两层循环,依次去找最大值,但是这种方式复杂度会超限制
var maxArea = function(height) {
    let n = height.length - 1;
    let result = 0;
    for (let i = 0; i < n - 1; i++) {
        for (let j = i + 1; j < n; j++) {
            const area = Math.min(height[i], height[j]) * (j - i);
            result = area > result ? area : result;
        }
    }
    return result;
};

//  之后面试官让我优化一下,想了下面的解法,但好像也算是暴力解法,依然没有全部通过
var maxArea = function(height) {
    let i = 0;
    let n = height.length - 1;
    let result = 0;
    while (n) {
        let j = i + n;
        if (j > height.length) {
            i = 0;
            n--;
            continue;
        }
        const area = Math.min(height[i], height[j]) * n;
        result = area > result ? area : result;
        i++;
    }
    return result;
};

//  想第三种解法的时候倒是很容易想到双指针,但是没有想明白双指针怎么控制指针的移动,最后也是没有写出来
//  下面是复盘之后重新写出来的双指针方式,重点就是要考虑到”木桶效应“,短板存在的时候一定是移动短板那一侧的指针
//  因为长的那一侧不管如何移动,最大值都是由短的那一侧决定的
var maxArea = function(height) {
    let i = 0;
    let j = height.length - 1;
    let result = 0;
    while (i < j) {
        const area = Math.min(height[i], height[j]) * (j - i);
        result = area > result ? area : result;
        if (height[i] < height[j]) {
            i++;
        } else {
            j--;
        }
    }
    return result;
};

二面

总时长:60min

可能是一面问的技术细节较多,二面基本没怎么问太多细节的问题,大都是聊管理上的事情以及项目中的一些实践和思考。整体聊的还算轻松,感觉要么是面试官跟我之前的ld聊过,要么是内推人给了我背书,聊完之后差不多就知道可以通过。

聊一聊管理上做的事情

招聘:

  1. 招聘的话比较简单,主要就是找人、然后面试等

业务:

  1. 需求评审之前:根据每个人的时间情况和需求内容,完成需求的分配
  2. 需求评审之后:由开发同学进行任务的拆解、估时,之后我会对估时进行二次确认
  3. 开发过程中:定时或在关键节点检查任务进度,了解当前开发过程有无风险
  4. 提测之前:要求开发同学编写自测case,在提测之前需要先把自测case走通

技术:

  1. 了解当前业务中的一些疑难问题以及开发流程中低效的部分,提出对应的技术手段以解决该问题
  2. 指导低级别同学参与到技术项目中,并对其技术方案进行review
  3. 调研业内技术方案及最新技术,组织团队分享和新技术尝试

遇到管理上比较棘手的事情是什么

产品投诉开发质量问题,解决方案有以下:

  1. 在提测之前要求先提供自测用例,并需要自己完整通过用例后才能提测给QA
  2. 对同学进行引导和提示,强调开发质量的重要性
  3. 了解同学的能力边界,对于无法胜任复杂项目的同学进行换岗,使其完成自己能力之内的事情
  4. 若上面的手段都不行,那就只能最终劝退

如何评判团队成员的绩效

本身团队不大,所有人的绩效都由老板管理,自己不参与团队成员的绩效。

靠什么激励团队成员

无激励......我自己都没有激励,怎么激励团队成员😅

讲一下业务监控告警是怎么做的

根据业务流程中对应环节的埋点数据可以计算出业务指标,如提单成功率 = 支付成功的埋点数 / 购物车页点击下单的埋点数。获取到各个业务指标的计算公式之后,可以在告警平台去配置对应的趋势图,之后对不同时间段的趋势设置不同的告警阈值即可。

如何实现让其他业务快速接入

之前在负责监控告警项目的时候,因为大部分的SDK都是使用的公司通用组件,因此更多的事做了一些流程性的一些事情。先是在自己负责的业务模块进行了可行性验证,然后整理成了接入文档,并推动其他业务模块逐个接入。

面试官想了解有没有在技术上做什么事情,让一个新的业务想使用这套方案时能最小成本接入,这部分确实是没有做。

发版流程是什么样的

在多人协作的时候,通过lightmerge的方式去实现分支的管理,每次发版需要lightmerge中所有分支的需求都测试通过且达到可以上线状态。若发版前有需求分支存在bug,则需要开发同学自行跟owner以及产品确认其需求是否需要延迟到下个版本,或发通知跟随当前版本但整体略微延迟发布。

回滚流程是什么样的

当发现线上问题时,由业务的owner去判断问题的影响面,若影响较大则立即回滚,否则无需回滚并立即走bugfix流程。当需求回滚之后,由QA再次回测确认线上问题所在的需求分支,之后发版负责人可选择将该需求分支移除lightmerge并将剩余需求分支合并后再次上线。若下线需求较为重要,则继续走前述的整体延迟发布流程。