一面50min 1.自我介绍 2.怎么学习前端 3.输入url到页面渲染完成 4.TCP/IP协议分层,TCP在哪一层 5.三次握手 四次挥手,为什么挥手多一次 6.浏览器缓存,强缓存、协商缓存,为什么cache-control优先级更高 7. no-cache,no-store分别代表什么 8. html、css、js文件会放在磁盘缓存还是内存缓存 9. DOM树和css om树是互斥的还是同时的 10. JS脚本阻塞DOM构建,js脚本会不会对css om树影响 11.重绘、重排概念 12.看题说输出 var name = 'window'const obj = { name: 'obj', sayName:function() { console.log(this.name) },}obj.sayMyName = () => { console.log(this.name)}const fn1 = obj.sayName()const fn2 = obj.sayMyName()fn1() // windowobj.sayName() // objfn2() // windowobj.sayMyName() // window 13.箭头函数和普通函数的区别,箭头函数如何表示不定长的参数 14.有哪些类型的作用域 15.var let const区别 16.实现eventbus class eventBus { constructor() { this.eventMap = {} } addEventListener(eventname, fn, isOnce) { const taskObj = {fn,isOnce} if (!this.eventMap[eventname]) { this.eventMap[eventname] = [taskObj] } else { this.eventMap[eventname].push(taskObj) } } on(eventname, fn) { this.addEventListener(eventname, fn, false) } once(eventname, fn) { this.addEventListener(eventname, fn, true) } off(eventname) { this.eventMap[eventname] = [] } trigger(eventname) { const tasks = this.eventMap[eventname] const onceTasks = [] tasks && tasks.forEach((item, index) => { const { fn,isOnce } = item fn && fn() if (isOnce) { onceTasks.push(index) } }) onceTasks.forEach((index) => { this.eventMap[eventname].splice(index, 1) }) }}const bus = new eventBus()const fn1 = () => { console.log('fn1')}const fn2 = () => { console.log('fn2')}bus.on('fn', fn1)bus.once('fn', fn2)bus.on('fn', fn1)bus.trigger('fn') // fn1 fn2 fn1bus.trigger('fn') // fn1 fn1bus.off('fn')bus.trigger('fn') // null 17. 岛屿数量 18. 反问:表现,业务 总结 no-cache没了解到,cssom构建和js之间的关系之前没了解过作用域没说好,变量提升、暂时性死区也没讲到eventbus实现比较丑陋,但是面试官很友好,给了提示 二面50min 1.自我介绍 2.http2.0和http1.0的区别 3.多路复用怎么实现的 4.https和http之间的区别,https握手过程 5.中间人攻击如何实现?怎样防范? 6.position取值,reletive相对谁 7.flex属性,flex布局 8.第二个子元素的高度是多少 <div class="container"> <div style="height: 100px"></div> <div style="min-height: 10px"></div></div><style> .container{ display: flex; } .container > div { width: 100px; }</style> 9.事件循环讲解 10.看代码说输出 async function async1(){ console.log('async1') await async2() console.log('async1 end')}async function async2(){ console.log('async2')}console.log('script start')setTimeout(() =>{ console.log('setTimeOut')},0)async1()new Promise((resolve) => { console.log('promise') resolve()}).then(() =>{ console.log('promise2')})console.log('script end') 11. 继承有哪些方法 12. Vue常见的组件通信方法 13. 兄弟组件通信你会考虑用哪些方法 14. Vue MVVM实现思路 15. proxy对比defineproperty的优势 16. 实现lodash _get方法,后面给了优化思路 function _get(obj,path){ let splitedPath = path if(typeof path === 'string'){ splitedPath = path.replace(/\[(\d+)\]/g, '.$1').split('.') } const firstPath = splitedPath.shift() if(splitedPath.length === 0){ return obj[firstPath] }else{ return _get(obj[firstPath],splitedPath.join('.')) }} 17. 实习过程中遇到的困难,最有成就感的事 18. 实习的时候做的浏览器插件简单讲一下 19. 反问 总结 flex那个高度没说对,继承说的乱七八糟get写的有点丑陋,不过算是把case都跑通了,面试官挺友好的感觉面试官是个开源社区的贡献者,比较在意这个 三面 70min 1.自我介绍 2.介绍一下实习的项目 3.遇到的困难和问题,怎么解决 4.线上出问题是怎么排查的 5.React和Vue的区别 6.如何理解闭包 7.如何理解面向对象 8.设计模式 9.输入url到渲染的过程(对服务器如何定位到具体文件追问了) 10.keep-alive,websocket 11.最大连续子数组,输出值和索引 总结 几乎没问前端向的东西,几乎都答得不好最后的算法题写出来了,但是对复杂度不满意,优化了大概得有20分钟都没优化出来