前端实习生-字节面试面经
这次字节的一面还是比较简单的,和一般公司的一面差不太多,基本大家只要多复习复习JS的基础和ES6,其实都差不多能够答出来。接下来记下具体这次的面试和流程,希望能对XDM有所帮助
这次是在牛客网上的面试房间面试的,有的面试官会使用腾讯会议面试,有的面试官会使用电话面试,所以碰到在牛客网上面试的情况的话,可以尽量多准备准备算法相关的一些东西,因为经常会有题目需要你手打代码,然后面试官询问思路
CSS
- 居中对齐
- position
首先是面试官让你自我介绍,介绍完之后开始问CSS方面的知识,这部分问的少,居中对齐有哪几个方案,position居中对齐的方案解释下原理,这两个问题回答完就直接JS部分了。CSS部分复习比较广泛繁琐,尽量还是在日常使用中累积经验
JS
- 事件循环
- Promise
- call bind
- 拍平方案
- 状态码
这部分首先是事件循环题,是一个老生常谈的题目了,我没记下原题,这里贴一个类似的题目,当时出的是只有五个打印的题目,这个题目只要注意在微任务中Promise、settimeout的执行顺序,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行就行了
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
/**
* script start
* async1 start
* async2
* promise1
* script end
* async1 end
* promise2
* setTimeout
*/
紧接着的是手写的题目,要求手写call函数和Promise函数(这个其实没有让我去写,只是说了下实现的思路,后面的Redux简单实现也是只要求说了思路),注意以下写的东西并不是当时写的代码
Function.prototype.myCall = function(context) {
context = context || window;
context.func = this;
const params = [...arguments].slice(1);
const result = context.func(...params);
return result;
}
function MyPromise(executor) {
var self = this;
this.status = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
function resolve(value) {
if (self.status === 'pending') {
self.status = 'resolve';
self.value = value;
self.onResolvedCallbacks.map((fn) => {
fn();
})
}
}
function reject(reason) {
if (self.status === 'pending') {
self.status = 'rejected';
self.reason = reason;
self.onRejectedCallbacks.map((fn) => {
fn();
})
}
}
try {
executor(resolve, reject);
} catch (err) {
reject(err)
}
}
MyPromise.prototype.then = function (infulfilled, inrejected) {
var self = this;
if (this.status === 'resolve') {
infulfilled(this.value)
}
if (this.status === 'rejected') {
inrejected(this.reason)
}
if (this.status === 'pending') {
this.onResolvedCallbacks.push(function () {
infulfilled(self.value)
});
this.onRejectedCallbacks.push(function () {
inrejected(self.reason)
});
}
};
Promise部分完之后,面试官问知道拍平吗?拍平能说出有哪几种方案,我说了简单的比如toString+split的方案,递归的方案,还有Array.prototype.flat可以做到这一点,然后这里面试官说希望我能手写一个flat函数,要求传数组进去能够返回拍平后的数组
// 错误示范
// 这个是当时我写的,num并未起作用,然后面试官就让我回答后续的问题了
function flat(arr, num){
let res = [];
if(num > 0){
arr.map(item => {
if(Array.isArray(item)){
res = [...res, flat(item, num - 1)]
} else {
res.push(item)
}
})
}else {
res = arr
}
return res;
}
console.log(flat([1,2,3,[1,2, [3,4], 5], 6], 1))
紧接着面试官询问了我了解哪些状态码,我说完之后他取出304状态码问这个状态码是什么时候会看到的,这个地方其实就是问你对缓存的了解,问完后就进入了React的部分
React
- diff算法
- this.setState异步同步
- 生命周期说一遍
- this.setState为什么不能用在render里
- 为什么hooks不能用在if-else里面
- redux实现
首先简单问了React中diff的原理,key的作用,然后问了生命周期都有哪些,让我按自己的记忆说一遍,因为后面我用的是hooks,所以生命周期我只说了六七个,然后问了我,this.setState是同步的还是异步的,这里是一个小陷阱,因为this.setState在一些时候是同步的,一些时候是异步的,这个大家可以自己去了解一下在监听事件、绑定事件、生命周期中的this.setState表现。然后问了我this.setState为什么不能用在render里,这里也是一点小陷阱,因为事实上不是不能用,而是尽量谨慎,this.setState会触发重新render,你可以为其设置限制条件等控制他的重新渲染。为什么hooks不能用在if-else里面,这个其实我没有太清楚,所以说了不好意思不太清楚。值得一提的是,大厂的面试官不会因为你不懂而改变对你的态度,始终都会是比较温和的面试态度,所以这点对于面试者还是比较舒服的,不会出现面完心态大崩的情况啦。然后问了我懂不懂redux的简单的实现,正好这个我有写过一个简单的实现,然后就边地打了几行,边讲具体的代码和设计思路,具体代码在下方
export default function createStore(reducer){
let state = null;
const listeners = [];
const getState = () => state
const dispatch = (action) => {
state = reducer(state, action)
listeners.forEach(listener => listener())
}
const subscribe = (listener) => listeners.push(listener)
// 这里初始化dispatch的原因是在这之前,state是为null的
dispatch({});
return {
dispatch,
subscribe,
getState,
}
}
其他
- graphql的意义
最后面试官还问了我graphql的意义是什么,这个是因为我的简历上是有说用过graphql的,所以问了用这个的原因,这里我答得是和Restful的一些差别,这个的话大家可以没用过的话就可以不用复习,不用担心面试官会问出除你简历所写之外的技术(昂除非是很基础的比如CSS、html),最后是让我问问题,我询问了该前端团队所选用的技术栈是怎样的,也是gql + apollo那一套加中间层,具体的没有详细问,希望我的面经能够对大家的面试有所帮助