阅读 4951

繁花五月,刚出炉的前端面经千万不要错过|掘金技术征文

前言

你好呀,我是wangly,一名下班摸鱼的前端老倒霉蛋了。受疫情影响,今年初中级岗位普遍少了好多,此时的我已经抱着手机留下了悲痛的泪水。先来说下我的故事吧。然后在总结下对线复盘。

我是今年2020届的专科应届生,已经有实习一年的经历,大厂进不去,小厂压价格,在现在公司15个人的Team担任前端工程师,对公司项目进行协同开发和独立完成。每天下班都会在想以后的发展,本来已经做好的跳槽计划也被一只蝙蝠的故事给打乱了。 之所以萌生跳槽的想法是因为现在公司的业务和我的成长到达了一个需要寻找突破的时候,再加上本身城市并不是互联网非常发达,经济也不是非常景气。慢慢的接触了一些电话面试,可无奈于自己专科的学历,并没有多少好的机会。我的目标很简单,找一家有自己产品的,有经营计划的公司。可无奈于现实就是如此,不是你不够优秀,而是还优秀不到让别人注意到你。 2020年的目标是: 在一线找一家有自己产品的公司稳定下来,沉淀自己。

对线详情

整体都在追问或者被追问的情况下。面试精心动魄。像极了当年的Ryu被丝血反杀。对线时长2个小时15分钟,白嫖水三杯,糕点一盘。

面试过程

面试过程分为笔试和面试两个阶段,笔试考察一些手写代码和理解,面试考察了一些业务场景和怼项目。非常的细致,

笔试

笔试题目很简单,无非就是一些基础的手写代码和常识问题。但如果没有系统过非常容易挂科。

1.实现一个左边固定,右边自适应的DIV布局

// DOM 结构
<div class="container">
  <div class="aside">left</div>
  <div class="section">right</div>
</div>

// Style样式
.container {
  display: flex;
}
.container .aside {
  flex: 0 0 200px;
}
.container .section {
  flex: 1;
}
复制代码

2.使用两种方式实现box居中

// DOM结构
<div class="container">
  <div class="box"></div>
</div>

// 方案一:flex方案

.container {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
.container .box {
  background: red;
  min-width: 100px;
  min-height: 100px;
}

// 方案二:position方案
.container {
  width: 100%;
  height: 100%;
  position: relative;
}
.container .box {
  background: red;
  min-width: 100px;
  min-height: 100px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
复制代码

3.如何给一组列表首尾之外的元素添加样式

// 考察了css伪类的使用

// DOM
<ul class="list">
  <li class="item">1</li>
  <li class="item">2</li>
  <li class="item">3</li>
  <li class="item">4</li>
  <li class="item">5</li>
</ul>

// Style

.list > .item:not(:first-child):not(:last-child) {
  /* ... style */
}

复制代码

4.JavaScript的数据数据类型有哪些?

答:JavaScript钟分为基础类型和引用类型,分别是:

  • 基础类型:number,string,boolean,null,undefined
  • 引用类型: object,function,array

5.下面foo函数输出值是什么

// @function foo
function foo(i) {
  try {
    if (i === 1) {
      return i
    }
  } catch (error) {
    return 0
    
  } finally {
    ++i
    return i
  }
}

// @console
console.log(foo(1))
复制代码

答:2

6.给定一个数组,请你按照升序 & 降序的规则去排列它

原始数组:[1, 4, 10, 2, 5, 18, 14] 答:

// @function bubble
function bubble(arr, state) {
  const len = arr.length
  let template
  for (let i = 0; i < len; i++) {
    for (let j = i + 1; j < len; j++) {
      if (state === 'up') {
        if (arr[i] < arr[j]) {
          template = arr[i]
          arr[i] = arr[j]
          arr[j] = template
        }
      }
      if (state === 'down') {
        if (arr[i] > arr[j]) {
          template = arr[i]
          arr[i] = arr[j]
          arr[j] = template
        }
      }
    }
  }
  return arr
}

// @console
console.log(bubble([1, 4, 10, 2, 5, 18, 14], 'down'))
复制代码

7.下面一段代码执行的结果是什么

var name = 'zangsan';
(function () {
  console.log(name)
  name = 'Lisi'
  console.log(window.name)
  var name = 'wangwu'
  console.log(name)
})();
复制代码

答:  undefined > zangsan > wangwu

8.for 循环和 forEach循环的区别在于?

答:

  • for循环为原生语法糖,无上下文,而forEach则是Array上的方法。
  • for 循环可以通过break, continue进行中途退出循环,而forEach则不行。

9.执行下面的异步函数大约需要消耗多长时间?

// @promise function
function speed() {
  return new Promise(resolve => {
    setTimeout(resolve, 3000)
  })
}

// @async function
async function foo() {
  let mySpeed = speed()
  await mySpeed
  await mySpeed
  await mySpeed
  await speed()
  await speed()
  await speed()
}

foo()
复制代码

答:约等于12S,但是时间超出12S。

10.请你实现一个简单的防抖函数?

答:

// @function shake
function shake(fun, time) {
  let timeController = null
  return (...args) => {
    timeController !== null && clearTimeout(timeController)
    timeController = setTimeout(() => {
      fun.apply(this, args)
    }, time)
  }
}

// @test function
function myText() {
  console.log('text......')
}

// @output
shake(myText, 3000)
复制代码

11. localStorage、sessionStorage、cookie之间的区别?

答: 它们都是用来做数据持久化的存储方式,

  • cookie存放在客户端,随着浏览器关闭,cookie将会丢失。存储大小为4K
  • sessionStorage: 只在本次会话有效,当浏览器关闭或者页面关闭后将会失效,存储大小为 > 4M
  • localStorage:存储在浏览器本地,除非手动清除或意外因素,一般不会丢失。存储大小为4M

12. 一些题目记不起来了...

面试

打完题后,仔细看了一遍。确保无明显问题后,就交给旁边的HR了。估计是拿去技术部做评估。个人觉得其实笔试挺坑的。真正开发中对于一些笔试题基本毫无接触。因此每次面试都需要花大量时间去过一遍知识点,查缺补漏。过了差不多5~6分钟后,人事小改改就带我去一个独立的办公室进行面试。里面已经坐了两个人,一个看上去是经理一个应该是前端。我坐下后,他们手里已经拿了我的简历。估计是已经看过了。随着小改改出去关上门后(全军出击),对线开始:

自我介绍

自我介绍其实很少去看,大致上我也是按照一些点来去说一些不犯错误的废话。

  • 我是谁,XXXX学校专科,所学专业。
  • 先后在两家公司从事Web前端工程师实习和全职工作,有1年以上的工作经验,主要使用Vue技术体系做为项目基建。先后经历4个项目,涉及大型后台管理项目的协同开发,公司内部企业微信H5,小程序服务程序的独立开发。
  • 闲暇之余喜欢看书,学习新技术,写开源项目和博客总结。......其实真的扯不上多少。哪位有好的模板可以救救我这个老倒霉蛋。

自我介绍后,就开始提问对线了。

1. ES6中你常用的新特性有哪些? 你是怎么使用它的 ?

答:

  • 首先是新的块级变量定义方式, let & const, 在项目中我默认使用 const 来定义我的变量,只有涉及变量赋值时,我才会将其声明为 let 。
  • 其次是模板字符串,以前的时候都是采用 + 和 toString 来去做一些字符串的拼接,如 URL 。这样拼接后可读性非常的差。当ES6模板字符串出现后我就立马在项目中使用起来了。
  • 解构赋值是一个非常强大的功能,在Vue中不论是 methods 还是 computd 中都会涉及大量的 data 响应式变量读取,那么我就可以将Vue的 this 解构出来,将需要使用的 data methods ...解构出来,可以避免代码中存在大量的 this.XXX  避免这种糟糕的代码风格。
  • 箭头函数大大的缩短了一些 function 的书写,一般作用在 callback 中,可以快速的进行函数调用。如 foreach , map 等方法。
  • Set & Map在我的项目中经常使用,因为涉及到一个表格模板。因为表格数据格式并不固定,所以我经常规划后台返回数据格式为我上传的格式,通常为 key value ,这样后台返回给我的值,我可以通过Map将其填充成键值对后在表格渲染出来。因为Map的 key 存储的数据类型非常的棒。而Object则做不到这点。
  • Promise和Async异步处理他解决了以前异步的回调地狱,让JavaScript的异步有了更好的体验。通常在Vue中数据请求都是通过Promise的形式来去做数据的异步获取的。

获取是说的有点久了,不然这个东西还能说一个小时。我就说,ES6的更新有点多,我就挑了一些有代表性的特性讲了下。可能面试官也觉得自己问的太宽泛了。也及时同意,开始了下一题。

2.你刚才提到了Promise,你知道它的API吗?

答:

  • resolve
  • reject
  • then
  • catch
  • finally
  • all

3.Promise的rece API你知道吗?

答: 上一题好像忘记说了(尴尬),这个方法我并不是很常用。它的作用是做一个并发的比较,并发N个Promise当有一个返回了结果,它就结束了。谁先执行完,它的结果就是那个Promise的返回值。参数和Promise.all是一样的的。

4. Axios如何同时发送多个请求?

答: Axios本身其实是一个Promise,可以通过Promise.all 的方式去执行多个Axios请求。Axios内部也提供Axios.all方法,使用方式和Promise.all相同。

5. 请求后端数据提示跨域你是如何解决的。

答: 我个人倾向于使用CORS方案,CORS标准新增了一组头部字段,允许服务器声明哪些源站有权限访问哪些资源。这个需要后端来进行配合。另一种就是使用Nginx代理转发了。

这一块我回答的不是很好,小伙伴如果不懂可以去复习下浏览器跨域方案。

6. Vue中v-show 和 v-if的区别

答: v-if指令会在渲染View视图中,主动去忽略绑定的DOM,它不会被加载到虚拟DOM,自然在ViewDOM中也不会去显示。 v-show指令会给绑定的DOM添加一个 display: none 的style样式,来达到实现隐藏和显示功能。

7.computed 和 watch 能和我说下吗?

答: computed是一个单独的属性,不能和methods / data 中的值名称重复。它存在缓存性,当你依赖的计算值没有发生改变时,computed会保持当前的值不变化。不支持异步 watch只能观测 data 中的值,且一个函数只能监视一个。主要用于对某个值进行一个监听操作。

8. Vue3在响应式绑定上做了哪些变化,为什么这么做?

答:

  • 1.Vue2使用了Object。defineProperty来进行数据劫持,Vue3则更换为了新的Proxy API,Object.defineProperty只能劫持对象属性,而Proxy可以直接代理观察对象。
  • Object.defineProperty对对象属性的观察较弱,当对象新增和修改属性时,需要重新指定Observe,不然很可能导致Observe盲区。反之Proxy代理对象支持非常友好,支持大部分常见的操作拦截。

9. VueRoute组件路由守卫有哪些?

答:

  • beforeRouteEnter
  • beforeRouteUpdate
  • beforeRouteLeave

10. VueRoute有哪几种模式,它们有什么不同?

答: 有两种路由模式,分别是 hash history ,

  • hash模式下,URL中会带有一个 # 号,history没有。
  • history路由如果后端部署没有更改页面指向则会出现刷新和跳转404的问题,而hash路由却不会
  • hash路由相对history兼容比较好。

11.Vuex中模块命名空间能和我说下吗?

答: 通过export 导出模块,设置 namespaced: true来开启命名空间,这样模块就拥有自己的模块归属了,如:A模块中有一个action名称为test,则我们就可以通过 a/test 来找到它,避免Vuex的模块产生冲突。

12.  Vuex中Mutation 和 Action有什么区别

答: Mutation主要是用来改变state当中的数据,因此它主要作为一个中间人。它不支持异步,这样就可以被Vue监听,devtools就可以同步到它的记录。如果它是异步的,那么就很可能导致devtools无法同步它究竟什么时候发生改变。而我们常用的方式是通过Action来提交Mutation,因为Action是一个异步的过程,所以这样做既保证了逻辑的异步调用,同时不破坏Mutation的记录良好。方便开发者调试。其实就是一个数据的交换过程。

13. 后面几题忘记了

怼项目

激动人心的怼项目环节, 有些内容有点私密,就不会全写出去。这一块其实都是看自己的项目理解。我这里就挑选几个对话作为参考吧。

Q: 看你公司的项目使用了webSocket,为什么要要去使用它呢?

A:因为我这个项目有些重要消息需要实时的去获取,如果用户长时间不去访问Message的接口,如果错过了重要报警推送会非常的麻烦。这个和美团的骑手微笑行动一样逻辑。

Q:既然使用了webSocket,你能说下webSocket常用的API吗?

A:webSocket的API分为

  • onopen(),打开通道并连接ws
  • send(),发送消息
  • onmessage(),ws消息回调
  • onerror(),ws连接错误
  • onclose(),ws连接关闭

Q:既然要保持socket连接,那么你是如何保持当前socket连接正常的?

A:我做一个定时的ping操作,这里成为:“心跳响应”,人是如何判断自身存活或者死亡的。其实最快的方式就是自己的心跳,只要你的心跳还在跳动,那么你就算还活着。因此,我每隔一定的时间使用ws.send()发送一个无意义的ping消息。告诉后台我还在连接。后台收到后,也就继续推送消息。而如果ping 消息错误了。那么就说明ws可能意外的中断了,那么会走onerror()方法,这时候,我可以从新开始唤醒它。这样我就能怼webSocket保持一个相对的连接持久化了。

后续我就不讲公司项目了,其实就是一个问答环节,自己做的模块自己应该清楚的。(●'◡'●),后面问了我个人项目,这倒是没有啥隐瞒的。

Q:你自己实现了一个UI组件库?

A:是的,这是我下班时候练手写的。一共有22个组件,文档还没有更新到最新版本的。

Q:组件的整体风格是你设计的还是?

A:是我自己凭感觉写的,只是一些尺寸参考了蚂蚁的AntD Vue来去设计的,配色和样式是我自己凭空想出来的,哈哈。

Q:那么你能和我说下你的tooltip是怎么实现吗?

A:这个tooltip组件是我使用伪类去实现的,通过before,after伪类中的content可以通过CSS的attr(属性)函数获取动态值做绑定,然后通过定位去画出来的。核心就是CSS的 伪类,attr(tootip),position定位等CSS的用法。

Q:了解了,看你的大部分组件都是只实现了简单的功能,是否有做过深入呢?

A:这是一个长期维护的项目,一开始只是来练手,随着就是封装经验越来越丰富,对比前面的功能会发现很low,所以后续Vue3出来后会做一个重写。优化代码结构。

Q:看了下你的模态框,感觉挺有意思的,能和我说下吗?

A:好的,这个模态框的设计思路来自于Mac系统的对话框,当时觉得挺有意思,就决定把它搬运到组件库中来,又重新去构思了下,就做成现在这个样子了。不过里面大部分的API都是一些常用的,没有做一些比较定制的功能。

Q:......

A:......

以下省略掉后面都是在看项目,觉得有意思就问下一些东西。

面试总结

总体面试其实不像文章中描述的平淡无奇,其实还有好多紧张,卡顿得地方。省略了一些问题,因为没有带录音笔,所以很多都是凭借记忆复盘的。放假在家刚好喝了点鸡汤,补充了下身体。就做一个总结,希望对还在求职的你有一个帮助。今年找工作确实难,尤其是像我这种学历低,经验少的童鞋,是真的心累。但我还是会坚持下去的,我们一起加油哦。 大家在面试结束后,其实有个套路不知道你们有没有发现:

面试时一直怼你,甚至问炸的情况下,拿offer的几率越大,反之,一路平坦,聊了几下技术就一直聊家长里短的反而是了无音讯。

虽然最后结果是过了,但是我目标还是毕业后去一线城市,可能只是为了不让自己碌碌而为吧。 好了,各位看官都看得差不多了,觉得有用就点个赞吧。顺便给我个人UI库点赞赞哦。

欢迎内推我上岸:

  • 地点:上杭深广
  • 薪资:8K - 12K
  • 拒绝外包

我的github: 立即跳转

UI组件库: 立即跳转中文站点

关注下面的标签,发现更多相似文章
评论