本人毕业后一直在广州从事前端开发,至今接近5年经验。2023是糟糕的一年,本想着过完年后,行情会有所恢复。春节后股票飙升了不少,Sora爆火。。。总感觉给人一种企稳的信心,但事实上经济依旧低迷,大家都不敢高消费。年后回来岗位少的可怜,特别是广州这个互联网荒漠地带。更甚的是,大厂一波接着一波裁员优化,僧多粥少的时代,真就是buff层叠满。
本人2月份就开始看机会,3月底有幸参加了字节的前端面试,总体面试体验还是不错的,分享自己面试经验,话不多说,开始吧。
一轮面试
事件循环
async function a1() {
console.log(1);
await a2();
console.log(2);
}
async function a2() {
console.log(3);
}
setTimeout(() => {
console.log(4);
}, 0);
console.log(5);
a1();
new Promise((resolve) => {
console.log(6);
resolve();
}).then(() => {
console.log(7);
});
console.log(8);
// 5 1 3 6 8 2 7 4
Promise知识
- all 和 allSettled 的区别
- all的实现思路
- Promise.resolve()传入的不同参数结果有什么不同
tree shaking
- 摇树是怎么实现的?
- css 是怎么进行按需加载的
- esm 是怎么转成 cjs 的
- 组件库怎么实现按需加载
webpack
- loader 和 plugin 的区别
- plugin 的实现原理(node 的 eventbus 模块,发布订阅)
sentry
sentry 是怎么捕捉各种错误的,怎么区分错误类型。比如资源请求失败是怎么知道的。(用 error 和 unhandledrejection 事件, 用 Performance 可以监听资源加载失败)
实现并发函数
// 2 为并发最大数
const limit = pLimit(2);
const inputs = [
limit(() => fetchSomething(1000), "param1"),
limit(() => fetchSomething(2000), "param2"),
limit(() => fetchSomething(3000), "param3"),
];
function fetchSomething(time) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, time);
});
}
const time = Date.now();
Promise.all(inputs).then((results) => {
console.log(results);
console.log(Date.now() - time); // 需要打印为 4s。(解释:因为并发数限制为2,第一个和第二个请求并发进行,第三个等待,第一个结束后开始第三个请求。总体时间为4s)
});
// 实现 pLimit 函数?
function pLimit(limit) {}
我的实现
function pLimit(limit) {
const queue = [];
let activeCount = 0;
function schedule() {
if (activeCount < limit && queue.length > 0) {
const { fn, resolve, reject, args } = queue.shift();
activeCount++;
fn(...args)
.then((result) => {
resolve(result);
})
.catch((err) => {
reject(err);
})
.finally(() => {
activeCount--;
schedule();
});
}
}
return function (fn, ...args) {
return new Promise((resolve, reject) => {
queue.push({ fn, resolve, reject, args });
schedule();
});
};
}
二轮面试
根据id查找树节点,打印查找路径
const arr = [
{
id: 1,
child: [
{ id: 3 },
{
id: 4,
child: [
{
id: 5,
child: [{ id: 6 }],
},
],
},
],
},
{
id: 2,
child: [
{
id: 7,
},
],
},
];
我的实现
console.log(BFS(arr, 6)); // 查找id为6,需要打印路径:[1, 4, 5, 6]
function BFS(nodes, id) {
const queue = nodes;
while (queue.length > 0) {
let len = queue.length - 1;
while (len >= 0) {
const node = queue.shift();
if (!node.path) {
node.path = [node.id];
}
if (id === node.id) {
return node.path;
}
if (node.child && node.child.length > 0) {
queue.push(
...node.child.map((item) => ({
...item,
path: [...node.path, item.id],
}))
);
}
len--;
}
}
}
实现异步sum方法
function asyncAdd(a, b, callback) {
setTimeout(function () {
callback(a + b);
}, 1000);
}
// 请实现 sum 方法
sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11).then((sum) => console.log(sum)); // 66
我的实现
function sum(...args) {
return new Promise((resolve) => {
let res = 0;
let count = 0;
for (item of args) {
asyncAdd(res, item, (sum) => {
res += sum;
count++;
if (count === args.length) {
resolve(res);
}
});
}
});
}
性能优化
- 图片懒加载原理
- 虚拟列表原理
vite 简要原理
- esm
- 开发时用 esbuild,生产时用 rollup
- ...
webpack 的 hash、contenthash、chunkhash
- hash: 当任何项目文件发生更改时,Webpack 将生成一个新的哈希。这意味着如果你修改了任何一个文件,那么整个项目的哈希都会改变,导致所有的缓存失效。
- contenthash: 这个哈希是根据文件内容来生成的。当文件的内容发生变化时,Webpack 才会生成新的哈希。这意味着即使项目中其他文件发生了变化,只要特定文件的内容没有改变,它的哈希也不会改变。
- chunkhash: 这个哈希是根据特定的模块生成的。每个入口文件都会有一个唯一的 chunkhash。如果一个模块的内容发生变化,那么该模块的 chunkhash 就会改变,但其他模块的 chunkhash 不受影响。
三轮面试(业务总监)
不具体问技术细节,从项目层面问
- 性能优化做了哪些
- 内存泄露怎么排查 (chrome的性能面板)
- React 和 Vue 的区别
- 生涯规划等等
HRBP面
- 规划,经历等
交叉面
全面介绍你最近做的一个项目
实现 0.1 + 0.2 = 0.3
- 首先为什么 0.1 + 0.2 不等于 0.3 ?(精度问题)
- 然后怎么实现让相加等于 0.3 (转成字符串再相加)
实现 红绿灯
我的实现
/**
* 我的实现
* @param {number} maxCount 红绿灯循环次数
* @param {number} wait 红绿灯间隔时间
*/
function redAndGreen(maxCount, wait) {
let count = 0;
let status = "red";
function run() {
switch (status) {
case "red":
console.log("red");
status = "yellow";
setTimeout(run, wait);
break;
case "yellow":
console.log("yellow");
status = "green";
setTimeout(run, wait);
break;
case "green":
console.log("green");
status = "red";
count++;
if (count < maxCount) {
setTimeout(run, wait);
}
break;
}
}
run();
}
redAndGreen(3, 100);
买卖股票
只能一次买卖,leetcode的简单题
最后
由于薪资职级等一些问题,最终没有去成,还是感到挺惋惜的。说真的,2024面整个互联网差到离谱,前端岗位更是少得可怜。对于切图仔的我有时真感到很无力。但是,我们虽然普通,但并不影响我们提升自己。想着继续保持学习的态度,同时探索副业的可能性,不管怎么样,都要为将来做好准备。最近看完《飞驰人生 2》,真的很喜欢张弛的一句话:“我努力了无数次,我知道机会只会出现在其中一两次”。