字节跳动前端面试
一面
约的 10 月 17 日下午三点,14:42 进直播间,此时室友都还在睡觉。面试官大概三点过了几分才进来。简单的介绍了一下(没听清他说自己姓啥了)糊了一下就开始面试了。尽量还原一下情景,顺序可能有偏差。
1. 介绍一下自己
幸好看了一下 moy 的面经,拿出了提前准备好的稿子开始吟唱
2. 介绍一下你做过的项目罢
虽然没有提前准备过,但好歹都是自己亲生的娃,拿机房监控的项目吹了一下。中间问了几个技术问题,比如用了什么框架之类的。
当然,提到用 Websocket 传输视频的时候面试官两眼发光,给后面的问题打下了坚实的伏笔
3. 你遇到最难的问题以及怎么解决的
一群背时研究生学长,跑的识别的代码不晓得在哪的 tutorial 改的,rtmp 识别完就变成 rawvideo 了。我在网上找了一堆方案最后拼出来了一个免去可以用的(flv.js + node-fluent-ffmpeg + 给学长的代码插了一段 socket 传 rawvideo 到 node 的 py)
4. 刚刚听你提到了 Websocket,能讲讲有什么特点吗
TCP,双向连接,持久不断开,兼容有问题
伏笔很快的就冒了出来,要不是用了好几次 Websocket 还写过一个同构的 json-websocket 工具怕是要遭
4.1 你用什么东西查的兼容性呢
有个网站
4.1.1 你平常在什么地方翻文档呢
MDN,刚刚那个网站是 canIuse
十分尴尬的忘了丢出来 StackOverflow 和 Google
4.2 Websocket 用的是什么库
ws
难不成我还会说用的是 express-ws 是因为别人给的 demo 是用的这个库
4.3 Websocket 整个过程都是 socket 吗
当然不是,前面要走 HTTP 来升级
4.3.1 那 Upgrade 时候返回的 HTTP 状态码是多少
101 Switching Protocol
还好之前写浏览器同构 WS 的时候看了一眼
4.4 了解视频流吗
仅限项目用到的
除了找怎么直播的时候看过一点各种直播方案以外还真没看过,可以看出来面试官是经常用 Websocket 而且还对视频直播很熟悉的,说不定是抖音那边的前端
5.1 js 怎么判断把类数组转换成数组
[...arr]
, Array.from(arr)
5.1.1 有 ES5 的方法吗
写个 for 循环一个一个 push
直到写文的时候才想起来 ES5 通篇的都是 Array.prototype
5.1.2 那怎么判断数组
Array.isArray()
, arr instanceof Array
,
“类数组判断不了吧”“判断不了吗”
当然判断不了啊,类数组都是一些名字都叫不出来的特殊类
5.2 讲一下 js 为什么要用异步
大概讲了下同步会阻塞 UI 影响用户体验
5.3 了解事件循环吗
宏任务和微任务那个吗(都讲一下吧) 开始口胡一通,这种东西看一下文档就会了,你问我他是啥我还真讲不出来
之前写 funcode 的时候就魔改过引擎的背时事件循环(加了一个用时间戳的事件系统),也被 Unity 背时的多重循环(Unity 应该是跑了好几个线程的循环)搞过,但是没怎么看过浏览器和 libuv 的东西。(突然想起自己还是看过一点背时的 epoll)。只能拿着宏任务和微任务吹一吹
5.6 这有一道题,讲一讲它的输出
console.log('script start') //1
async function async1() {
await async2()
console.log('async1 end') //5
}
async function async2() {
console.log('async2 end') //2
}
async1()
setTimeout(function () {
console.log('setTimeout') //8
}, 0)
new Promise((resolve) => {
console.log('Promise') //3
resolve()
})
.then(function () {
console.log('promise1') //6
})
.then(function () {
console.log('promise2') //7
})
console.log('script end') //4
console.log('script start') //1
async function async1() {
await async2()
console.log('async1 end') //5
}
async function async2() {
console.log('async2 end') //2
}
async1()
setTimeout(function () {
console.log('setTimeout') //8
}, 0)
new Promise((resolve) => {
console.log('Promise') //3
resolve()
})
.then(function () {
console.log('promise1') //6
})
.then(function () {
console.log('promise2') //7
})
console.log('script end') //4
在纸上画队列的时候面试官怀疑我在切 tab 搜答案,安逸牛客网,lose focus 了都不得通知
5.6.1 我在 setTimeout 后面加个 requestAnimationFrame 应该怎么输出
不清楚不知道没用过
6 你的简历上面写了对 Vue 挺熟悉的,那问你几个 Vue 的问题
6.1 你用了多久 Vue
大二做二手市场的时候用的,之后就一直在用
6.2 Vue 的双向绑定是怎么实现的
用的 Object.defineProperty(不过没说变异数组方法和后面改成 Proxy 了)
6.2.1 具体呢?出了一个例子
define 了 setter,然后变动的时候触发了 setter 更新 vDOM,再和 DOM 比较渲染
6.2.2 是和 DOM 比较吗
不知道,也有可能是和上一个时刻的 vDOM 吧
不知道,不清楚,没看过
6.3 vue.nextTick() 用过吗
不知道,不清楚,没用过
7. 又发过来一道题
var x = 3
var y = 4
var obj = {
x: 1,
y: 6,
getX: function () {
var x = 5
return (function () {
return this.x
})()
},
getY: function () {
var y = 7
return this.y
},
}
console.log(obj.getX()) //5
console.log(obj.getY()) //6
var x = 3
var y = 4
var obj = {
x: 1,
y: 6,
getX: function () {
var x = 5
return (function () {
return this.x
})()
},
getY: function () {
var y = 7
return this.y
},
}
console.log(obj.getX()) //5
console.log(obj.getY()) //6
“5 和 7 吧”
“是吗”
“不对感觉是 5 和 6”
“5 和 6 对吧”
“应该是吧”
“那 this 指向的是哪呢”
”getX 的作用域吧”
“作用域吗,好吧”
后来在 console 里面跑了一下发现是 3 和 6,return 的函数 this 指向的是 window。
背时函数,安逸箭头函数。
8. 平时做算法题吗
不做
8.1 那我选道简单点的
给定一个数组代表某支股票连续多个交易日的价格。你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
Input: [2, 3, 5, 1, 4]
Output: 3
Input: [ 5, 3, 2, 1]
Output: 0
一眼就看出来肯定是解法肯定是 O(n) 的,然后陷进 DP 列状态转移出不来了
非常无奈的写了暴力,面试官非常努力的鼓励我也想不出来
9. 居中应该怎么写
我用的多的 flex 和绝对定位,但是也可以 table-cell 和 margin
面试官:“margin 啊...”
9.1 用绝对定位写一个居中
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
10. 你有什么问题想问的吗
“这个团队有多少人呢”
“不清楚,我不是他们团队的”
一面总结
感觉表现的并不咋样,有好多东西都没有想起来。算法一如既往的垃圾,我太菜了罢。面试大概 50 分钟,结束后一个小时 HR 电话通知一面过了,约了二面。
二面
二面的面试官好像在家里,但是又会时不时左右望一下,让人十分迷惑。但是周日加班也太惨了。跟一面一样面试官晚了几分钟才进房间。
1.做个自我介绍吧
掏出简介开始吟唱
2.讲讲做过的项目吧
跟一面几乎一样的梦幻开头,拿出二手市场开始吹
3.有什么技术难点吗
二手市场讲了讲记录查看位置,压缩图片之类的,然后又抱着智慧课堂那个直播讲了一遍
3.1 你们这项目组多少人
我 + 俩 java 后端 + python
3.2 这个 node 也是你写的吗
是的
3.3 这个 Websocket 有鉴权吗
没有的(实际上 socket 的 url 都是后端返回拼出来的)
3.3.1 那要实现鉴权该怎么办
“配上 java 后端吗”“是的” 那就 java 登陆后返回 token,前端带着 token 去请求 websocket 面试官想了一会,非常不情愿的说好像可以 看起来他有一个别的方案,但是带 token 不是单点登陆的正常操作么
4.有没有做过前端安全方面的
(实际上没做过)硬着头皮糊了个 XSS
4.1 XSS 是什么原理
一瞬间仿佛看见了 moy 面后端写的面经,脱口而糊 实际上拿了之前在 CTF 看 XSS 看到的一段背了出来 背时,没写过 XSS,现在 CTF 都不咋流行了
4.2 还有其他的吗
想起刚看的面经里面有一个跨域(虽然算不上啥安全问题),赶紧糊了上去试图转移话题
4.2.1 跨域有哪些头
只记得两个,实际上有三四个
4.2.2 怎么处理跨域问题
后端加跨域头
4.2.3 还有吗
JSONP,但是没用过 还有我们用的 Websocket 也不会受跨域限制,因为鉴权是手动实现的,Websocket 后端可以随时断开连接
5.给一道题
if (!Function.prototype.bind){
Function.prototype.bind = function (o) {
if (typeof this !== 'function') {
throw TypeError("Bind must be called on a function");
} else {
//Write here
let args = [...arguments].slice(1)
return () => this.apply(o, [...args, ...arguments])
}
}
if (!Function.prototype.bind){
Function.prototype.bind = function (o) {
if (typeof this !== 'function') {
throw TypeError("Bind must be called on a function");
} else {
//Write here
let args = [...arguments].slice(1)
return () => this.apply(o, [...args, ...arguments])
}
}
一开始写的时候写的return () => this.apply(this, [...args, ...arguments])
被面试官提醒参数 o 没有用到才改回来 (而且还忘了绑 prototype, 但面试官似乎没有发现) 面试官似乎短暂的理解不能,解释了一下 this 指向的是调用 bind 的函数之后反应过来 “嗯,应该也可以” 那是当然,毕竟我提前写了一下,在浏览器稍微调试过
6.又给了一道题
这算法简直完全不用脑子,跟上一轮的一比就是 Easy 嘛
function findMaxDuplicateChar(str) {
let maxChar = '',
maxValue = 1
//Write here
let dict = {}
for (let i = 0; i < str.length; i++) {
if (str[i] !== ' ') dict[str[i]] = dict[str[i]] ? dict[str[i]] + 1 : 1
}
for (let c in dict) {
if (maxValue < dict[c]) {
maxValue = dict[c]
maxChar = c
}
}
return {
maxChar,
maxValue,
}
}
const str = 'this is a fe test at toutiao on September'
console.log(findMaxDuplicateChar(str)) // output: { maxChar:"t", maxValue:7 }
function findMaxDuplicateChar(str) {
let maxChar = '',
maxValue = 1
//Write here
let dict = {}
for (let i = 0; i < str.length; i++) {
if (str[i] !== ' ') dict[str[i]] = dict[str[i]] ? dict[str[i]] + 1 : 1
}
for (let c in dict) {
if (maxValue < dict[c]) {
maxValue = dict[c]
maxChar = c
}
}
return {
maxChar,
maxValue,
}
}
const str = 'this is a fe test at toutiao on September'
console.log(findMaxDuplicateChar(str)) // output: { maxChar:"t", maxValue:7 }
第一次遍历出来是空格(8 次),确认了一下不算空格以后写了一下 ''.join(str.split(' '))
发现跑不起来 背时 JS,连 join 都没有 然后在循环里面加了个 if 判断 “这个跑的起来吗” 我在 QQ 里面回了一下消息发现面试官毫无反应 点了一下提交运行结果是对的 “跑的起来” “那行吧” 面试官似乎不是非常擅长算法,倒是 moy 那个面试官相反
7.还有什么要问的吗
问了一下是啥部门的(广州的效率工程) 干什么的(to B) “我们会在一周之内通知你结果”
二面总结
在听到一周之内通知的时候都感觉要凉了,毕竟前面答的很糊,而且上次一面之后一个小时就收到了电话。周一上午在厕所里的时候接到面试过了的电话,约了周四电话面。