前言
本科,两年半经验前端,坐标杭州。目前在一家外企干外包的活,最近想试试各个大厂,遂梳理基础知识,投了字节、阿里、快手等几家简历。基本都直接被刷,有不招三年以下的,有觉得跳槽频繁的(第一家公司待了一年跳的现在这家,干了一年半了,行吧),最早投的盒马倒是打来了面试电话,还是非常感动的,至少能让我体验一次大厂的面试流程。
一面
一面先做三道笔试题,限时一个小时;笔试题做完开始提问。面试官态度很好,总体体验不错,答不出来的地方会引导你,提问的联系性也很强。
笔试题
const bigPrint = (n) => {
const type1 = " 0";
const type2 = "0000";
const type3 = "0 0";
const type4 = "0 ";
const data = {
1: [type1, type1, type1, type1, type1, type1, type1],
2: [type2, type1, type1, type2, type4, type4, type2],
3: [type2, type1, type1, type2, type1, type1, type2],
4: [type3, type3, type3, type2, type1, type1, type1],
5: [type2, type4, type4, type2, type1, type1, type2],
6: [type2, type4, type4, type2, type3, type3, type2],
7: [type2, type1, type1, type1, type1, type1, type1],
8: [type2, type3, type3, type2, type3, type3, type2],
9: [type2, type3, type3, type2, type1, type1, type2],
0: [type2, type3, type3, type3, type3, type3, type2],
};
const arr = n.toString().split("");
for (let i = 0; i < 7; i++) {
let rowOutput = "";
arr.map((e) => {
rowOutput = rowOutput + data[e][i] + " ";
});
console.log(rowOutput);
}
};
这题答得真的很水,还想了蛮久的,最后还是用这种对每行的归纳搞出来了。
const generateMessage = (template, data) => {
let result = template;
Object.keys(data).map((key) => {
const reg = new RegExp("\\${" + key + "}", "g");
result = result.replace(reg, data[key]);
});
return result;
};
这道题比第一题简单,注意$在正则里是特殊字符,用双斜杠去整出/\${key}/g形式的正则就行了。
第三题看着很长一段,但其实理顺了逻辑也不难。先初始化个二维数组,然后用
Math.random()随机一个坐标点出来,去判断是不是在用户点击范围内或该点已经有雷了,若在范围内或者已经有雷则继续随机坐标点。当时第一题胡思乱想太久,第三题思路已有,奈何时间不够没有写完,直接交卷了。
后续面试结束把这题写完顺便优化了一下,用fill代替遍历去生成数组,减少一些不必要的变量,缩了一下行数。
const generateMines = (M, N, mineCount, firstClickRow, firstClickcol) => {
let mines = Array.from(new Array(M), () => new Array(N).fill("O"));
const rowRange = [firstClickRow - 1, firstClickRow, firstClickRow + 1];
const colRange = [firstClickcol - 1, firstClickcol, firstClickcol + 1];
const pointGeneratorOutRange = () => {
const r = Math.round(Math.random() * (M - 1) + 1);
const c = Math.round(Math.random() * (N - 1) + 1);
if (
!(rowRange.includes(r) && colRange.includes(c)) &&
mines[r - 1][c - 1] !== "X"
) {
return { r, c };
}
return pointGeneratorOutRange();
};
for (let i = 0; i < mineCount; i++) {
const p = pointGeneratorOutRange();
mines[p.r - 1][p.c - 1] = "X";
}
return mines;
};
面试官提问
先简单问了我一下项目,主要了解下我的项目是干啥的,功能模块等,有什么难点么,遇到什么问题,怎么解决的。
项目问的比较简单,然后进入基础面试,css、js、浏览器、网络、es6、框架都有涉猎,会从我一个问题的回答引导出下一个问题,不会的也会引导你作答。因为有提前梳理过基础知识,所以答起来还行,列一下我记得的问题:
- get/post请求有什么区别
- 浏览器缓存相关(强缓存、协商缓存,对应属性介绍...)
- css怎么实现居中(我说最常用的是flex,他就笑笑说不用介绍别的了)
- flex两个轴居中的属性,轴方向调换用的是?
- flex:1,什么作用(综合了flex-grow,flex-shrink,flex-basis三个属性)
- flex-grow具体是什么作用,flex-basis呢
- 有没有遇到过z-index小的反而在上层的情况?(层叠上下文,当时有点小懵没答出来,其实是遇到过的,父级z-index更小,子元素大也没用)
- 箭头函数,this指向,es5实现(闭包)
- promise.all介绍,有什么不足?(引出promise.allsettled)
- promise.allsettled怎么用es5实现(之前没了解到allsettled,给了提示也没答上)
- for in遍历和for of遍历(讲完问我,for of可以遍历的迭代器相关,没复习到generator/yield和Iterator,面试后去mdn恶补了一下,只能说面试官尽力在引导了)
- 讲讲react生命周期,单项数据流有啥有点,常用hooks有哪些,分别有啥作用(我项目用的就是react hooks,之前也写过class形式,回答轻松)
- 项目里用的什么去管理状态?
- react中父子组件都订阅了一个store中的值,且子组件又从父组件获取了一个依赖的变量,store中值改了会导致子组件先渲染,父组件后渲染,因为依赖子组件会再渲染一次的情况,这种情况其实react帮我们处理了,你知道怎么回事嘛(我问题描述的有点乱,将就看,这道题想了一会儿,答了react在需要重新渲染组件时会去维护一个队列,当父组件和子组件都在队列中时,会把父组件提到子组件前面去,这样避免上述问题。之前看了react渲染有关的知识里有个dirty component的概念,就说了一下,基本猜对了)
- ...
还有一些问题,印象不深,基本我都复习到过,不列了。
最后面试官问我有什么问题么,我问了下目前项目组的业务相关,一面就这么结束了。
其实感觉一面有点凉,毕竟算法题没来得及,基础题也有两道没答上,没抱啥希望。不过当晚二面面试官来电话约面试了,直接就约了当晚。
二面
二面面试官是个说话比较犀利潇洒的,没有问基础,直接问的项目。
让我讲讲最近搞的最满意的项目,我讲了一下我最近在搞的前端侧自动化测试的项目,与之前java侧的自动化测试相比速度提升了50%,且更容易让无代码基础的人上手。项目细节不展开了,面试官很能抓住描述的点去提出犀利的问题,我列举一些如下:
- 自动化测试跑的频率(我们对内系统,每个发布日会完整跑一次,平时不会完整去跑,面试官质问我那你们auto的意义在哪)
- 自动化测试的质量(其实我不太理解这个质量只的是什么,通过率?稳定性?最后的报表?反正没答好)
- 前端侧做这个和java侧做有什么区别和优势?
- 这个项目你是如何推进的,有遇到什么难点,怎么处理的,那些细节有优化?
- 你觉得这项目还有什么不足,需要后续改进的,怎么保持自动化测试的稳定性?(答了动态引入测试数据,貌似光这点还不太满意)
- ...
其他还有一些问题,不列举了。感觉选这个项目聊有点吃力,因为问了我不少测试相关的问题,而我主要focus在前端侧构建来解决之前java侧构建的缺陷。第二天也是去找测试同事狠狠了解了一波,补习补习。
后续也没有再联系我了,凉凉。不过也是吸取了一波经验教训,继续补足知识吧,慢慢来面...
最后
上述代码或者观点若有错误或者更优解欢迎评论区指教,虚心向各位大佬学习~
顺便求大佬内推下,给个面试机会吧,想体验大厂面试的压迫感~